@@ -224,7 +224,9 @@ async function authorize_request(req) {
224224 req . object_sdk . authorize_request_account ( req ) ,
225225 // authorize_request_policy(req) is supposed to
226226 // allow owners access unless there is an explicit DENY policy
227- authorize_request_policy ( req )
227+ authorize_request_policy ( req ) ,
228+ // authorize_request_iam_policy(req) is for users only
229+ authorize_request_iam_policy ( req ) ,
228230 ] ) ;
229231}
230232
@@ -299,14 +301,17 @@ async function authorize_request_policy(req) {
299301 // we start the permission check on account identifier intentionally
300302 if ( account_identifier_id ) {
301303 permission_by_id = await s3_bucket_policy_utils . has_bucket_policy_permission (
302- s3_policy , account_identifier_id , method , arn_path , req , public_access_block ?. restrict_public_buckets ) ;
304+ s3_policy , account_identifier_id , method , arn_path , req ,
305+ { disallow_public_access : public_access_block ?. restrict_public_buckets }
306+ ) ;
303307 dbg . log3 ( 'authorize_request_policy: permission_by_id' , permission_by_id ) ;
304308 }
305309 if ( permission_by_id === "DENY" ) throw new S3Error ( S3Error . AccessDenied ) ;
306310
307311 if ( ( ! account_identifier_id || permission_by_id !== "DENY" ) && account . owner === undefined ) {
308312 permission_by_name = await s3_bucket_policy_utils . has_bucket_policy_permission (
309- s3_policy , account_identifier_name , method , arn_path , req , public_access_block ?. restrict_public_buckets
313+ s3_policy , account_identifier_name , method , arn_path , req ,
314+ { disallow_public_access : public_access_block ?. restrict_public_buckets }
310315 ) ;
311316 dbg . log3 ( 'authorize_request_policy: permission_by_name' , permission_by_name ) ;
312317 }
@@ -316,11 +321,50 @@ async function authorize_request_policy(req) {
316321 throw new S3Error ( S3Error . AccessDenied ) ;
317322}
318323
324+ async function authorize_request_iam_policy ( req ) {
325+ const auth_token = req . object_sdk . get_auth_token ( ) ;
326+ const is_anonymous = ! ( auth_token && auth_token . access_key ) ;
327+ if ( is_anonymous ) return ;
328+
329+ const account = req . object_sdk . requesting_account ;
330+ const is_iam_user = account . owner !== undefined ;
331+ if ( ! is_iam_user ) return ; // IAM policy is only on IAM users (account root user is authorized here)
332+
333+ const resource_arn = _get_arn_from_req_path ( req ) ;
334+ const method = _get_method_from_req ( req ) ;
335+ const iam_policies = account . iam_user_policies || [ ] ;
336+ if ( iam_policies . length === 0 ) return ;
337+
338+ // parallel policy check
339+ const promises = [ ] ;
340+ for ( const iam_policy of iam_policies ) {
341+ // We are reusing the bucket policy util function as it checks the policy document
342+ const promise = s3_bucket_policy_utils . has_bucket_policy_permission (
343+ iam_policy . policy_document , undefined , method , resource_arn , req ,
344+ { should_pass_principal : false }
345+ ) ;
346+ promises . push ( promise ) ;
347+ }
348+ const permission_result = await Promise . all ( promises ) ;
349+ let has_allow_permission = false ;
350+ for ( const permission of permission_result ) {
351+ if ( permission === "DENY" ) throw new S3Error ( S3Error . AccessDenied ) ;
352+ if ( permission === "ALLOW" ) {
353+ has_allow_permission = true ;
354+ }
355+ }
356+ if ( has_allow_permission ) return ;
357+ dbg . log1 ( 'authorize_request_iam_policy: user have inline policies but none of them matched the method' ) ;
358+ throw new S3Error ( S3Error . AccessDenied ) ;
359+ }
360+
319361async function authorize_anonymous_access ( s3_policy , method , arn_path , req , public_access_block ) {
320362 if ( ! s3_policy ) throw new S3Error ( S3Error . AccessDenied ) ;
321363
322364 const permission = await s3_bucket_policy_utils . has_bucket_policy_permission (
323- s3_policy , undefined , method , arn_path , req , public_access_block ?. restrict_public_buckets ) ;
365+ s3_policy , undefined , method , arn_path , req ,
366+ { disallow_public_access : public_access_block ?. restrict_public_buckets }
367+ ) ;
324368 if ( permission === "ALLOW" ) return ;
325369
326370 throw new S3Error ( S3Error . AccessDenied ) ;
0 commit comments