@@ -2487,3 +2487,232 @@ func TestS3TablesActionsWithImplicitMatching(t *testing.T) {
24872487 })
24882488 }
24892489}
2490+
2491+ func TestPolicyParseS3VectorsExamples (t * testing.T ) {
2492+ tests := []struct {
2493+ name string
2494+ policyJSON string
2495+ expectedActions []Action
2496+ expectedResources []string
2497+ }{
2498+ {
2499+ name : "VectorBucketFullAccess" ,
2500+ policyJSON : `{
2501+ "Version": "2012-10-17",
2502+ "Statement": [
2503+ {
2504+ "Effect": "Allow",
2505+ "Action": [
2506+ "s3vectors:CreateVectorBucket",
2507+ "s3vectors:DeleteVectorBucket",
2508+ "s3vectors:GetVectorBucket",
2509+ "s3vectors:ListVectorBuckets"
2510+ ],
2511+ "Resource": "arn:aws:s3:::vectors-bucket/*"
2512+ }
2513+ ]
2514+ }` ,
2515+ expectedActions : []Action {
2516+ Action (S3VectorsCreateVectorBucketAction ),
2517+ Action (S3VectorsDeleteVectorBucketAction ),
2518+ Action (S3VectorsGetVectorBucketAction ),
2519+ Action (S3VectorsListVectorBucketsAction ),
2520+ },
2521+ expectedResources : []string {"arn:aws:s3:::vectors-bucket/*" },
2522+ },
2523+ {
2524+ name : "IndexOperations" ,
2525+ policyJSON : `{
2526+ "Version": "2012-10-17",
2527+ "Statement": [
2528+ {
2529+ "Effect": "Allow",
2530+ "Action": [
2531+ "s3vectors:CreateIndex",
2532+ "s3vectors:DeleteIndex",
2533+ "s3vectors:GetIndex",
2534+ "s3vectors:ListIndexes"
2535+ ],
2536+ "Resource": "arn:aws:s3:::vectors-bucket/*"
2537+ }
2538+ ]
2539+ }` ,
2540+ expectedActions : []Action {
2541+ Action (S3VectorsCreateIndexAction ),
2542+ Action (S3VectorsDeleteIndexAction ),
2543+ Action (S3VectorsGetIndexAction ),
2544+ Action (S3VectorsListIndexesAction ),
2545+ },
2546+ expectedResources : []string {"arn:aws:s3:::vectors-bucket/*" },
2547+ },
2548+ {
2549+ name : "VectorDataOperations" ,
2550+ policyJSON : `{
2551+ "Version": "2012-10-17",
2552+ "Statement": [
2553+ {
2554+ "Effect": "Allow",
2555+ "Action": [
2556+ "s3vectors:PutVectors",
2557+ "s3vectors:GetVectors",
2558+ "s3vectors:DeleteVectors",
2559+ "s3vectors:ListVectors",
2560+ "s3vectors:QueryVectors"
2561+ ],
2562+ "Resource": "arn:aws:s3:::vectors-bucket/*"
2563+ }
2564+ ]
2565+ }` ,
2566+ expectedActions : []Action {
2567+ Action (S3VectorsPutVectorsAction ),
2568+ Action (S3VectorsGetVectorsAction ),
2569+ Action (S3VectorsDeleteVectorsAction ),
2570+ Action (S3VectorsListVectorsAction ),
2571+ Action (S3VectorsQueryVectorsAction ),
2572+ },
2573+ expectedResources : []string {"arn:aws:s3:::vectors-bucket/*" },
2574+ },
2575+ {
2576+ name : "AllVectorsActions" ,
2577+ policyJSON : `{
2578+ "Version": "2012-10-17",
2579+ "Statement": [
2580+ {
2581+ "Effect": "Allow",
2582+ "Action": "s3vectors:*",
2583+ "Resource": "arn:aws:s3:::vectors-bucket/*"
2584+ }
2585+ ]
2586+ }` ,
2587+ expectedActions : []Action {Action (AllS3VectorsActions )},
2588+ expectedResources : []string {"arn:aws:s3:::vectors-bucket/*" },
2589+ },
2590+ }
2591+
2592+ for _ , tt := range tests {
2593+ t .Run (tt .name , func (t * testing.T ) {
2594+ p , err := ParseConfig (strings .NewReader (tt .policyJSON ))
2595+ if err != nil {
2596+ t .Fatalf ("failed to parse policy: %v" , err )
2597+ }
2598+
2599+ if len (p .Statements ) != 1 {
2600+ t .Fatalf ("expected 1 statement, got %d" , len (p .Statements ))
2601+ }
2602+
2603+ stmt := p .Statements [0 ]
2604+
2605+ // Check actions
2606+ if len (stmt .Actions ) != len (tt .expectedActions ) {
2607+ t .Errorf ("expected %d actions, got %d" , len (tt .expectedActions ), len (stmt .Actions ))
2608+ }
2609+ for _ , expectedAction := range tt .expectedActions {
2610+ if ! stmt .Actions .Contains (expectedAction ) {
2611+ t .Errorf ("expected action %v not found in statement" , expectedAction )
2612+ }
2613+ }
2614+
2615+ // Check resources
2616+ if len (stmt .Resources ) != len (tt .expectedResources ) {
2617+ t .Errorf ("expected %d resources, got %d" , len (tt .expectedResources ), len (stmt .Resources ))
2618+ }
2619+ for _ , expectedResource := range tt .expectedResources {
2620+ found := false
2621+ for r := range stmt .Resources {
2622+ if r .String () == expectedResource {
2623+ found = true
2624+ break
2625+ }
2626+ }
2627+ if ! found {
2628+ t .Errorf ("expected resource %v not found in statement" , expectedResource )
2629+ }
2630+ }
2631+ })
2632+ }
2633+ }
2634+
2635+ func TestS3VectorsActionsAllowed (t * testing.T ) {
2636+ policyJSON := `{
2637+ "Version": "2012-10-17",
2638+ "Statement": [
2639+ {
2640+ "Effect": "Allow",
2641+ "Action": ["s3vectors:*"],
2642+ "Resource": ["arn:aws:s3:::vectors-bucket/*"]
2643+ }
2644+ ]
2645+ }`
2646+
2647+ testCases := []struct {
2648+ name string
2649+ args Args
2650+ expectedResult bool
2651+ description string
2652+ }{
2653+ {
2654+ name : "CreateVectorBucket allowed" ,
2655+ args : Args {
2656+ Action : Action (S3VectorsCreateVectorBucketAction ),
2657+ BucketName : "vectors-bucket" ,
2658+ ObjectName : "my-vector-bucket" ,
2659+ },
2660+ expectedResult : true ,
2661+ description : "CreateVectorBucket should be allowed with s3vectors:*" ,
2662+ },
2663+ {
2664+ name : "ListIndexes allowed" ,
2665+ args : Args {
2666+ Action : Action (S3VectorsListIndexesAction ),
2667+ BucketName : "vectors-bucket" ,
2668+ ObjectName : "my-vector-bucket/indexes" ,
2669+ },
2670+ expectedResult : true ,
2671+ description : "ListIndexes should be allowed with s3vectors:*" ,
2672+ },
2673+ {
2674+ name : "PutVectors allowed" ,
2675+ args : Args {
2676+ Action : Action (S3VectorsPutVectorsAction ),
2677+ BucketName : "vectors-bucket" ,
2678+ ObjectName : "my-vector-bucket/index/my-index" ,
2679+ },
2680+ expectedResult : true ,
2681+ description : "PutVectors should be allowed with s3vectors:*" ,
2682+ },
2683+ {
2684+ name : "QueryVectors allowed" ,
2685+ args : Args {
2686+ Action : Action (S3VectorsQueryVectorsAction ),
2687+ BucketName : "vectors-bucket" ,
2688+ ObjectName : "my-vector-bucket/index/my-index" ,
2689+ },
2690+ expectedResult : true ,
2691+ description : "QueryVectors should be allowed with s3vectors:*" ,
2692+ },
2693+ {
2694+ name : "Wrong bucket not allowed" ,
2695+ args : Args {
2696+ Action : Action (S3VectorsCreateVectorBucketAction ),
2697+ BucketName : "wrong-bucket" ,
2698+ ObjectName : "my-vector-bucket" ,
2699+ },
2700+ expectedResult : false ,
2701+ description : "CreateVectorBucket should not be allowed on wrong bucket" ,
2702+ },
2703+ }
2704+
2705+ for _ , tc := range testCases {
2706+ t .Run (tc .name , func (t * testing.T ) {
2707+ p , err := ParseConfig (strings .NewReader (policyJSON ))
2708+ if err != nil {
2709+ t .Fatalf ("failed to parse policy: %v" , err )
2710+ }
2711+
2712+ result := p .IsAllowed (tc .args )
2713+ if result != tc .expectedResult {
2714+ t .Errorf ("%s: expected %v, got %v" , tc .description , tc .expectedResult , result )
2715+ }
2716+ })
2717+ }
2718+ }
0 commit comments