github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/policy_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "reflect" 22 "testing" 23 24 miniogopolicy "github.com/minio/minio-go/v7/pkg/policy" 25 "github.com/minio/minio-go/v7/pkg/set" 26 "github.com/minio/pkg/v2/policy" 27 "github.com/minio/pkg/v2/policy/condition" 28 ) 29 30 func TestPolicySysIsAllowed(t *testing.T) { 31 p := &policy.BucketPolicy{ 32 Version: policy.DefaultVersion, 33 Statements: []policy.BPStatement{ 34 policy.NewBPStatement("", 35 policy.Allow, 36 policy.NewPrincipal("*"), 37 policy.NewActionSet(policy.GetBucketLocationAction), 38 policy.NewResourceSet(policy.NewResource("mybucket")), 39 condition.NewFunctions(), 40 ), 41 policy.NewBPStatement("", 42 policy.Allow, 43 policy.NewPrincipal("*"), 44 policy.NewActionSet(policy.PutObjectAction), 45 policy.NewResourceSet(policy.NewResource("mybucket/myobject*")), 46 condition.NewFunctions(), 47 ), 48 }, 49 } 50 51 anonGetBucketLocationArgs := policy.BucketPolicyArgs{ 52 AccountName: "Q3AM3UQ867SPQQA43P2F", 53 Action: policy.GetBucketLocationAction, 54 BucketName: "mybucket", 55 ConditionValues: map[string][]string{}, 56 } 57 58 anonPutObjectActionArgs := policy.BucketPolicyArgs{ 59 AccountName: "Q3AM3UQ867SPQQA43P2F", 60 Action: policy.PutObjectAction, 61 BucketName: "mybucket", 62 ConditionValues: map[string][]string{ 63 "x-amz-copy-source": {"mybucket/myobject"}, 64 "SourceIp": {"192.168.1.10"}, 65 }, 66 ObjectName: "myobject", 67 } 68 69 anonGetObjectActionArgs := policy.BucketPolicyArgs{ 70 AccountName: "Q3AM3UQ867SPQQA43P2F", 71 Action: policy.GetObjectAction, 72 BucketName: "mybucket", 73 ConditionValues: map[string][]string{}, 74 ObjectName: "myobject", 75 } 76 77 getBucketLocationArgs := policy.BucketPolicyArgs{ 78 AccountName: "Q3AM3UQ867SPQQA43P2F", 79 Action: policy.GetBucketLocationAction, 80 BucketName: "mybucket", 81 ConditionValues: map[string][]string{}, 82 IsOwner: true, 83 } 84 85 putObjectActionArgs := policy.BucketPolicyArgs{ 86 AccountName: "Q3AM3UQ867SPQQA43P2F", 87 Action: policy.PutObjectAction, 88 BucketName: "mybucket", 89 ConditionValues: map[string][]string{ 90 "x-amz-copy-source": {"mybucket/myobject"}, 91 "SourceIp": {"192.168.1.10"}, 92 }, 93 IsOwner: true, 94 ObjectName: "myobject", 95 } 96 97 getObjectActionArgs := policy.BucketPolicyArgs{ 98 AccountName: "Q3AM3UQ867SPQQA43P2F", 99 Action: policy.GetObjectAction, 100 BucketName: "mybucket", 101 ConditionValues: map[string][]string{}, 102 IsOwner: true, 103 ObjectName: "myobject", 104 } 105 106 yourbucketAnonGetObjectActionArgs := policy.BucketPolicyArgs{ 107 AccountName: "Q3AM3UQ867SPQQA43P2F", 108 Action: policy.GetObjectAction, 109 BucketName: "yourbucket", 110 ConditionValues: map[string][]string{}, 111 ObjectName: "yourobject", 112 } 113 114 yourbucketGetObjectActionArgs := policy.BucketPolicyArgs{ 115 AccountName: "Q3AM3UQ867SPQQA43P2F", 116 Action: policy.GetObjectAction, 117 BucketName: "yourbucket", 118 ConditionValues: map[string][]string{}, 119 IsOwner: true, 120 ObjectName: "yourobject", 121 } 122 123 testCases := []struct { 124 args policy.BucketPolicyArgs 125 expectedResult bool 126 }{ 127 {anonGetBucketLocationArgs, true}, 128 {anonPutObjectActionArgs, true}, 129 {anonGetObjectActionArgs, false}, 130 {getBucketLocationArgs, true}, 131 {putObjectActionArgs, true}, 132 {getObjectActionArgs, true}, 133 {yourbucketAnonGetObjectActionArgs, false}, 134 {yourbucketGetObjectActionArgs, true}, 135 } 136 137 for i, testCase := range testCases { 138 result := p.IsAllowed(testCase.args) 139 140 if result != testCase.expectedResult { 141 t.Fatalf("case %v: expected: %v, got: %v\n", i+1, testCase.expectedResult, result) 142 } 143 } 144 } 145 146 func getReadOnlyStatement(bucketName, prefix string) []miniogopolicy.Statement { 147 return []miniogopolicy.Statement{ 148 { 149 Effect: string(policy.Allow), 150 Principal: miniogopolicy.User{AWS: set.CreateStringSet("*")}, 151 Resources: set.CreateStringSet(policy.NewResource(bucketName).String()), 152 Actions: set.CreateStringSet("s3:GetBucketLocation", "s3:ListBucket"), 153 }, 154 { 155 Effect: string(policy.Allow), 156 Principal: miniogopolicy.User{AWS: set.CreateStringSet("*")}, 157 Resources: set.CreateStringSet(policy.NewResource(bucketName + "/" + prefix).String()), 158 Actions: set.CreateStringSet("s3:GetObject"), 159 }, 160 } 161 } 162 163 func TestPolicyToBucketAccessPolicy(t *testing.T) { 164 case1Policy := &policy.BucketPolicy{ 165 Version: policy.DefaultVersion, 166 Statements: []policy.BPStatement{ 167 policy.NewBPStatement("", 168 policy.Allow, 169 policy.NewPrincipal("*"), 170 policy.NewActionSet(policy.GetBucketLocationAction, policy.ListBucketAction), 171 policy.NewResourceSet(policy.NewResource("mybucket")), 172 condition.NewFunctions(), 173 ), 174 policy.NewBPStatement("", 175 policy.Allow, 176 policy.NewPrincipal("*"), 177 policy.NewActionSet(policy.GetObjectAction), 178 policy.NewResourceSet(policy.NewResource("mybucket/myobject*")), 179 condition.NewFunctions(), 180 ), 181 }, 182 } 183 184 case1Result := &miniogopolicy.BucketAccessPolicy{ 185 Version: policy.DefaultVersion, 186 Statements: getReadOnlyStatement("mybucket", "myobject*"), 187 } 188 189 case2Policy := &policy.BucketPolicy{ 190 Version: policy.DefaultVersion, 191 Statements: []policy.BPStatement{}, 192 } 193 194 case2Result := &miniogopolicy.BucketAccessPolicy{ 195 Version: policy.DefaultVersion, 196 Statements: []miniogopolicy.Statement{}, 197 } 198 199 case3Policy := &policy.BucketPolicy{ 200 Version: "12-10-2012", 201 Statements: []policy.BPStatement{ 202 policy.NewBPStatement("", 203 policy.Allow, 204 policy.NewPrincipal("*"), 205 policy.NewActionSet(policy.PutObjectAction), 206 policy.NewResourceSet(policy.NewResource("mybucket/myobject*")), 207 condition.NewFunctions(), 208 ), 209 }, 210 } 211 212 testCases := []struct { 213 bucketPolicy *policy.BucketPolicy 214 expectedResult *miniogopolicy.BucketAccessPolicy 215 expectErr bool 216 }{ 217 {case1Policy, case1Result, false}, 218 {case2Policy, case2Result, false}, 219 {case3Policy, nil, true}, 220 } 221 222 for i, testCase := range testCases { 223 result, err := PolicyToBucketAccessPolicy(testCase.bucketPolicy) 224 expectErr := (err != nil) 225 226 if expectErr != testCase.expectErr { 227 t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr) 228 } 229 230 if !testCase.expectErr { 231 if !reflect.DeepEqual(result, testCase.expectedResult) { 232 t.Fatalf("case %v: result: expected: %+v, got: %+v\n", i+1, testCase.expectedResult, result) 233 } 234 } 235 } 236 } 237 238 func TestBucketAccessPolicyToPolicy(t *testing.T) { 239 case1PolicyInfo := &miniogopolicy.BucketAccessPolicy{ 240 Version: policy.DefaultVersion, 241 Statements: getReadOnlyStatement("mybucket", "myobject*"), 242 } 243 244 case1Result := &policy.BucketPolicy{ 245 Version: policy.DefaultVersion, 246 Statements: []policy.BPStatement{ 247 policy.NewBPStatement("", 248 policy.Allow, 249 policy.NewPrincipal("*"), 250 policy.NewActionSet(policy.GetBucketLocationAction, policy.ListBucketAction), 251 policy.NewResourceSet(policy.NewResource("mybucket")), 252 condition.NewFunctions(), 253 ), 254 policy.NewBPStatement("", 255 policy.Allow, 256 policy.NewPrincipal("*"), 257 policy.NewActionSet(policy.GetObjectAction), 258 policy.NewResourceSet(policy.NewResource("mybucket/myobject*")), 259 condition.NewFunctions(), 260 ), 261 }, 262 } 263 264 case2PolicyInfo := &miniogopolicy.BucketAccessPolicy{ 265 Version: policy.DefaultVersion, 266 Statements: []miniogopolicy.Statement{}, 267 } 268 269 case2Result := &policy.BucketPolicy{ 270 Version: policy.DefaultVersion, 271 Statements: []policy.BPStatement{}, 272 } 273 274 case3PolicyInfo := &miniogopolicy.BucketAccessPolicy{ 275 Version: "12-10-2012", 276 Statements: getReadOnlyStatement("mybucket", "/myobject*"), 277 } 278 279 testCases := []struct { 280 policyInfo *miniogopolicy.BucketAccessPolicy 281 expectedResult *policy.BucketPolicy 282 expectErr bool 283 }{ 284 {case1PolicyInfo, case1Result, false}, 285 {case2PolicyInfo, case2Result, false}, 286 {case3PolicyInfo, nil, true}, 287 } 288 289 for i, testCase := range testCases { 290 result, err := BucketAccessPolicyToPolicy(testCase.policyInfo) 291 expectErr := (err != nil) 292 293 if expectErr != testCase.expectErr { 294 t.Fatalf("case %v: error: expected: %v, got: %v\n", i+1, testCase.expectErr, expectErr) 295 } 296 297 if !testCase.expectErr { 298 if !reflect.DeepEqual(result, testCase.expectedResult) { 299 t.Fatalf("case %v: result: expected: %+v, got: %+v\n", i+1, testCase.expectedResult, result) 300 } 301 } 302 } 303 }