APE access to receive specific object from specific container #1101

Open
opened 2024-04-19 11:24:52 +00:00 by alexvanin · 2 comments
Owner

I got this APE rule set by S3 Gateway

([]*chain.Chain) (len=2 cap=2) {                                                                   
 (*chain.Chain)(0xc001193580)({                                                                    
  ID: (chain.ID) (len=43 cap=43) {                                                                 
   00000000  69 6e 67 72 65 73 73 3a  62 6b 74 28 d9 8b af 8e  |ingress:bkt(....|                  
   00000010  6c a8 d1 2e 76 3a 73 27  b1 91 98 9f ff 5d 0d 49  |l...v:s'.....].I|
   00000020  08 34 b4 8b 94 a0 fd 7c  14 b2 2f                 |.4.....|../|                       
  },                                                                                               
  Rules: ([]chain.Rule) (len=1 cap=1) {                                                            
   (chain.Rule) {                                                                                  
    Status: (chain.Status) Allowed,                                                                
    Actions: (chain.Actions) {                                                   
     Inverted: (bool) false,                                                                       
     Names: ([]string) (len=6 cap=6) {                                                             
      (string) (len=12) "GetContainer",                                          
      (string) (len=9) "GetObject",                                                                
      (string) (len=10) "HeadObject",                                                              
      (string) (len=12) "SearchObject",                                          
      (string) (len=11) "RangeObject",                                                             
      (string) (len=10) "HashObject"
     }
    },
    Resources: (chain.Resources) {
     Inverted: (bool) false,
     Names: ([]string) (len=2 cap=2) {
      (string) (len=61) "native:object//3kThyGz5pBKiWMBWMCufnCB77BaUyLqjLd8JBYX5TXhQ/*",
      (string) (len=62) "native:container//3kThyGz5pBKiWMBWMCufnCB77BaUyLqjLd8JBYX5TXhQ"
     }
    },
    Any: (bool) false,
    Condition: ([]chain.Condition) (len=2 cap=2) {
     (chain.Condition) {
      Op: (chain.ConditionType) StringEquals,
      Object: (chain.ObjectType) 1,
      Key: (string) (len=16) "$Actor:publicKey",
      Value: (string) (len=66) "0212f413f56c7da16102f721b4e3c7302efb35013e2291e28a1b58ce28ec1117c4"
     },
     (chain.Condition) {
      Op: (chain.ConditionType) StringLike,
      Object: (chain.ObjectType) 0,
      Key: (string) (len=8) "FilePath",
      Value: (string) (len=7) "cat.jpg"
     }
    }
   }
  },
  MatchType: (chain.MatchType) 0
 }),

To access cat.jpg, S3 Gateway uses tree service and object service (head / get object). Requests contain bearer token with impersonate flag, signed by 0212f413f56c7da16102f721b4e3c7302efb35013e2291e28a1b58ce28ec1117c4 public key.

Expected Behavior

Access is granted.

Current Behavior

Access is denied due to several issues:

  1. Tree service denies request because FilePath attribute is not passed to request context.
  2. Object service denies Head request.

Possible Solution

Steps to Reproduce (for bugs)

  1. Create private bucket in S3 Gateway
  2. Attach bucket policy
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "AWS": "arn:aws:iam:::user/catvisitor"
         },
         "Action": [
            "s3:GetObject"
         ],
         "Resource": "arn:aws:s3:::private-cat-stor/cat.jpg"
      }
   ]
}

Regression

No

Your Environment

frostfs-node v0.38.5
frostfs-s3-gw v0.29.0-rc.7

/cc @fyrchik, @dkirillov

I got this APE rule set by S3 Gateway ``` ([]*chain.Chain) (len=2 cap=2) { (*chain.Chain)(0xc001193580)({ ID: (chain.ID) (len=43 cap=43) { 00000000 69 6e 67 72 65 73 73 3a 62 6b 74 28 d9 8b af 8e |ingress:bkt(....| 00000010 6c a8 d1 2e 76 3a 73 27 b1 91 98 9f ff 5d 0d 49 |l...v:s'.....].I| 00000020 08 34 b4 8b 94 a0 fd 7c 14 b2 2f |.4.....|../| }, Rules: ([]chain.Rule) (len=1 cap=1) { (chain.Rule) { Status: (chain.Status) Allowed, Actions: (chain.Actions) { Inverted: (bool) false, Names: ([]string) (len=6 cap=6) { (string) (len=12) "GetContainer", (string) (len=9) "GetObject", (string) (len=10) "HeadObject", (string) (len=12) "SearchObject", (string) (len=11) "RangeObject", (string) (len=10) "HashObject" } }, Resources: (chain.Resources) { Inverted: (bool) false, Names: ([]string) (len=2 cap=2) { (string) (len=61) "native:object//3kThyGz5pBKiWMBWMCufnCB77BaUyLqjLd8JBYX5TXhQ/*", (string) (len=62) "native:container//3kThyGz5pBKiWMBWMCufnCB77BaUyLqjLd8JBYX5TXhQ" } }, Any: (bool) false, Condition: ([]chain.Condition) (len=2 cap=2) { (chain.Condition) { Op: (chain.ConditionType) StringEquals, Object: (chain.ObjectType) 1, Key: (string) (len=16) "$Actor:publicKey", Value: (string) (len=66) "0212f413f56c7da16102f721b4e3c7302efb35013e2291e28a1b58ce28ec1117c4" }, (chain.Condition) { Op: (chain.ConditionType) StringLike, Object: (chain.ObjectType) 0, Key: (string) (len=8) "FilePath", Value: (string) (len=7) "cat.jpg" } } } }, MatchType: (chain.MatchType) 0 }), ``` To access `cat.jpg`, S3 Gateway uses tree service and object service (head / get object). Requests contain bearer token with `impersonate` flag, signed by `0212f413f56c7da16102f721b4e3c7302efb35013e2291e28a1b58ce28ec1117c4` public key. ## Expected Behavior Access is granted. ## Current Behavior Access is denied due to several issues: 1) Tree service denies request because `FilePath` attribute is not passed to request context. 2) Object service denies Head request. ## Possible Solution ## Steps to Reproduce (for bugs) 1. Create private bucket in S3 Gateway 2. Attach bucket policy ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam:::user/catvisitor" }, "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::private-cat-stor/cat.jpg" } ] } ``` ## Regression No ## Your Environment frostfs-node v0.38.5 frostfs-s3-gw v0.29.0-rc.7 /cc @fyrchik, @dkirillov
alexvanin added the
bug
triage
labels 2024-04-19 11:24:52 +00:00
aarifullin was assigned by alexvanin 2024-04-19 11:24:52 +00:00
fyrchik added this to the v0.39.0 milestone 2024-05-02 14:56:18 +00:00
fyrchik modified the milestone from v0.39.0 to vNext 2024-05-14 14:03:45 +00:00
Member
https://git.frostfs.info/TrueCloudLab/frostfs-node/pulls/1090
Author
Owner

I've checked this issue and it doesn't work for me yet.
frostfs-node v0.42.0-rc.6

I am not sure this can be fixed without introduction of separate policy actions for tree service.

S3 Gateway wants GetObject access with FilePath condition.
It also wants GetSubtree access without any specific conditions in this container.

While these two different operations are processed by the same GetObject action, we either fail on one of them (current behaviour) or S3 gateway should drop condition for GetObject, which may be considered as access policy violation by the user.

Thus, reopen to test this again when tree service actions are introduced.

To test it, we can simplify policy a bit:

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": "*",
         "Action": [
            "s3:GetObject",
            "s3:GetObjectTagging",
         ],
         "Resource": "arn:aws:s3:::private-cat-stor/cat.jpg"
      }
   ]
}

It should produces this ingress rule

(*chain.Chain)(0xc0008eb4c0)({                                                         
 ID: (chain.ID) (len=43 cap=48) {                                                      
  00000000  69 6e 67 72 65 73 73 3a  62 6b 74 56 6f 58 ec 74  |ingress:bktVoX.t|       
  00000010  1a 12 38 26 74 c2 6f 48  16 9d 91 f6 55 a4 04 8a  |..8&t.oH....U...|       
  00000020  a5 09 ab 61 11 51 5f 7a  07 a2 9c                 |...a.Q_z...|            
 },                                                                                    
 Rules: ([]chain.Rule) (len=1 cap=1) {                                                 
  (chain.Rule) {                                                                       
   Status: (chain.Status) Allowed,                                                     
   Actions: (chain.Actions) {                                                          
    Inverted: (bool) false,                                                            
    Names: ([]string) (len=6 cap=6) {                                                  
     (string) (len=9) "GetObject",                                                     
     (string) (len=10) "HeadObject",                                                   
     (string) (len=12) "SearchObject",                                                 
     (string) (len=11) "RangeObject",                                                  
     (string) (len=10) "HashObject",                                                   
     (string) (len=12) "GetContainer"                                                  
    }                                                                                  
   },                                                                                  
   Resources: (chain.Resources) {                                                      
    Inverted: (bool) false,                                                            
    Names: ([]string) (len=2 cap=2) {                                                  
     (string) (len=61) "native:object//6pQYDRU5Zt76brJjiU4yfyf1syqU35vcKKWC6984vUsd/*",
     (string) (len=62) "native:container//6pQYDRU5Zt76brJjiU4yfyf1syqU35vcKKWC6984vUsd"
    }                                                                                  
   },                                                                                  
   Any: (bool) false,                                                                  
   Condition: ([]chain.Condition) (len=1 cap=1) {                                      
    (chain.Condition) {                                                                
     Op: (chain.ConditionType) StringLike,                                             
     Kind: (chain.ConditionKindType) 0,                                                
     Key: (string) (len=8) "FilePath",                                                 
     Value: (string) (len=8) "cat.jpg"                                                
    }                                                                                  
   }                                                                                   
  }                                                                                    
 },                                                                                    
 MatchType: (chain.MatchType) 0                                                        
I've checked this issue and it doesn't work for me yet. frostfs-node v0.42.0-rc.6 I am not sure this can be fixed without introduction of separate policy actions for tree service. S3 Gateway wants GetObject access **with** FilePath condition. It also wants GetSubtree access **without** any specific conditions in this container. While these two different operations are processed by the same `GetObject` action, we either fail on one of them (current behaviour) or S3 gateway should drop condition for GetObject, which may be considered as access policy violation by the user. Thus, reopen to test this again when tree service actions are introduced. To test it, we can simplify policy a bit: ``` { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:GetObjectTagging", ], "Resource": "arn:aws:s3:::private-cat-stor/cat.jpg" } ] } ``` It should produces this ingress rule ``` (*chain.Chain)(0xc0008eb4c0)({ ID: (chain.ID) (len=43 cap=48) { 00000000 69 6e 67 72 65 73 73 3a 62 6b 74 56 6f 58 ec 74 |ingress:bktVoX.t| 00000010 1a 12 38 26 74 c2 6f 48 16 9d 91 f6 55 a4 04 8a |..8&t.oH....U...| 00000020 a5 09 ab 61 11 51 5f 7a 07 a2 9c |...a.Q_z...| }, Rules: ([]chain.Rule) (len=1 cap=1) { (chain.Rule) { Status: (chain.Status) Allowed, Actions: (chain.Actions) { Inverted: (bool) false, Names: ([]string) (len=6 cap=6) { (string) (len=9) "GetObject", (string) (len=10) "HeadObject", (string) (len=12) "SearchObject", (string) (len=11) "RangeObject", (string) (len=10) "HashObject", (string) (len=12) "GetContainer" } }, Resources: (chain.Resources) { Inverted: (bool) false, Names: ([]string) (len=2 cap=2) { (string) (len=61) "native:object//6pQYDRU5Zt76brJjiU4yfyf1syqU35vcKKWC6984vUsd/*", (string) (len=62) "native:container//6pQYDRU5Zt76brJjiU4yfyf1syqU35vcKKWC6984vUsd" } }, Any: (bool) false, Condition: ([]chain.Condition) (len=1 cap=1) { (chain.Condition) { Op: (chain.ConditionType) StringLike, Kind: (chain.ConditionKindType) 0, Key: (string) (len=8) "FilePath", Value: (string) (len=8) "cat.jpg" } } } }, MatchType: (chain.MatchType) 0 ```
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: TrueCloudLab/frostfs-node#1101
No description provided.