@@ -14,6 +14,7 @@ const http_utils = require('../../util/http_utils');
1414const signature_utils = require ( '../../util/signature_utils' ) ;
1515const config = require ( '../../../config' ) ;
1616const s3_utils = require ( './s3_utils' ) ;
17+ const { _create_detailed_message_for_iam_user_access_in_s3 } = require ( '../iam/iam_utils' ) ; // for IAM policy
1718
1819const S3_MAX_BODY_LEN = 4 * 1024 * 1024 ;
1920
@@ -331,7 +332,7 @@ async function authorize_request_policy(req) {
331332 throw new S3Error ( S3Error . AccessDenied ) ;
332333}
333334
334- // TODO - move the function and throw message error with details
335+ // TODO - move the function
335336async function authorize_request_iam_policy ( req ) {
336337 const auth_token = req . object_sdk . get_auth_token ( ) ;
337338 const is_anonymous = ! ( auth_token && auth_token . access_key ) ;
@@ -341,10 +342,14 @@ async function authorize_request_iam_policy(req) {
341342 const is_iam_user = account . owner !== undefined ;
342343 if ( ! is_iam_user ) return ; // IAM policy is only on IAM users (account root user is authorized here)
343344
344- const resource_arn = _get_arn_from_req_path ( req ) ;
345+ const resource_arn = _get_arn_from_req_path ( req ) || '*' ; // special case for list all buckets in an account
345346 const method = _get_method_from_req ( req ) ;
346347 const iam_policies = account . iam_user_policies || [ ] ;
347- if ( iam_policies . length === 0 && req . object_sdk . nsfs_config_root ) return ; // We do not have IAM policies in NC yet
348+ if ( iam_policies . length === 0 ) {
349+ if ( req . object_sdk . nsfs_config_root ) return ; // We do not have IAM policies in NC yet
350+ dbg . error ( 'authorize_request_iam_policy: IAM user has no inline policies configured' ) ;
351+ _throw_iam_access_denied_error_for_s3_operation ( account , method , resource_arn ) ;
352+ }
348353
349354 // parallel policy check
350355 const promises = [ ] ;
@@ -359,14 +364,23 @@ async function authorize_request_iam_policy(req) {
359364 const permission_result = await Promise . all ( promises ) ;
360365 let has_allow_permission = false ;
361366 for ( const permission of permission_result ) {
362- if ( permission === "DENY" ) throw new S3Error ( S3Error . AccessDenied ) ;
367+ if ( permission === "DENY" ) {
368+ dbg . error ( 'authorize_request_iam_policy: user has explicit DENY inline policy' ) ;
369+ _throw_iam_access_denied_error_for_s3_operation ( account , method , resource_arn ) ;
370+ }
363371 if ( permission === "ALLOW" ) {
364372 has_allow_permission = true ;
365373 }
366374 }
367375 if ( has_allow_permission ) return ;
368- dbg . log1 ( 'authorize_request_iam_policy: user have inline policies but none of them matched the method' ) ;
369- throw new S3Error ( S3Error . AccessDenied ) ;
376+ dbg . error ( 'authorize_request_iam_policy: user has inline policies but none of them matched the method' ) ;
377+ _throw_iam_access_denied_error_for_s3_operation ( account , method , resource_arn ) ;
378+ }
379+
380+ function _throw_iam_access_denied_error_for_s3_operation ( requesting_account , method , resource_arn ) {
381+ const message_with_details = _create_detailed_message_for_iam_user_access_in_s3 ( requesting_account , method , resource_arn ) ;
382+ const { code, http_code } = S3Error . AccessDenied ;
383+ throw new S3Error ( { code, message : message_with_details , http_code} ) ;
370384}
371385
372386async function authorize_anonymous_access ( s3_policy , method , arn_path , req , public_access_block ) {
@@ -399,6 +413,7 @@ function _get_method_from_req(req) {
399413}
400414
401415function _get_arn_from_req_path ( req ) {
416+ if ( ! req . params . bucket ) return ;
402417 const bucket = req . params . bucket ;
403418 const key = req . params . key ;
404419 let arn_path = `arn:aws:s3:::${ bucket } ` ;
0 commit comments