@@ -11,6 +11,7 @@ const GoogleStorage = require('../../util/google_storage_wrap');
1111
1212const P = require ( '../../util/promise' ) ;
1313const dbg = require ( '../../util/debug_module' ) ( __filename ) ;
14+ const SensitiveString = require ( '../../util/sensitive_string' ) ;
1415const config = require ( '../../../config' ) ;
1516const MDStore = require ( '../object_services/md_store' ) . MDStore ;
1617const BucketStatsStore = require ( '../analytic_services/bucket_stats_store' ) . BucketStatsStore ;
@@ -39,6 +40,7 @@ const bucket_semaphore = new KeysSemaphore(1);
3940const Quota = require ( '../system_services/objects/quota' ) ;
4041const { STORAGE_CLASS_GLACIER_IR } = require ( '../../endpoint/s3/s3_utils' ) ;
4142const noobaa_s3_client = require ( '../../sdk/noobaa_s3_client/noobaa_s3_client' ) ;
43+ const string_utils = require ( '../../util/string_utils' ) ;
4244
4345const VALID_BUCKET_NAME_REGEXP =
4446 / ^ ( ( [ a - z 0 - 9 ] | [ a - z 0 - 9 ] [ a - z 0 - 9 - ] * [ a - z 0 - 9 ] ) \. ) * ( [ a - z 0 - 9 ] | [ a - z 0 - 9 ] [ a - z 0 - 9 - ] * [ a - z 0 - 9 ] ) $ / ;
@@ -512,12 +514,43 @@ async function get_bucket_policy(req) {
512514 } ;
513515}
514516
517+ /**
518+ Validate and return account by principal ARN.
519+ 1. validate basic ARN, like arn prefix `arn:aws:iam::`
520+ 2. If principal ARN ends with `root` suffix, it's an account and get account with id
521+ eg: arn:aws:iam::${account_id}:root
522+ 3. if principal ARN contains `user`, it's an IAM user and get account with username and id
523+ eg: arn:aws:iam::${account_id}:user/${iam_path}/${user_name}
524+ account email = ${iam_user_name}:${account_id}
525+
526+ @param {SensitiveString | String } principal Bucket policy principal
527+ */
528+ async function get_account_by_principal ( principal ) {
529+ const principal_as_string = principal instanceof SensitiveString ? principal . unwrap ( ) : principal ;
530+ const root_sufix = 'root' ;
531+ const user_sufix = 'user' ;
532+ const arn_parts = principal_as_string . split ( ':' ) ;
533+ if ( ! string_utils . AWS_IAM_ARN_REGEXP . test ( principal_as_string ) ) {
534+ return ;
535+ }
536+ const account_id = arn_parts [ 4 ] ;
537+ const arn_sufix = arn_parts [ 5 ] ;
538+ if ( principal_as_string . endsWith ( root_sufix ) && ! arn_sufix . startsWith ( user_sufix ) ) {
539+ return system_store . data . accounts . find ( account => account . _id . toString ( ) === account_id ) ;
540+ } else if ( arn_sufix && arn_sufix . startsWith ( user_sufix ) ) {
541+ const arn_path_parts = principal_as_string . split ( '/' ) ;
542+ const iam_user_name = arn_path_parts [ arn_path_parts . length - 1 ] . trim ( ) ;
543+ return system_store . get_account_by_email ( new SensitiveString ( `${ iam_user_name } :${ account_id } ` ) ) ;
544+ } //else {
545+ // wrong principal ARN should not return anything.
546+ //}
547+ }
515548
516549async function put_bucket_policy ( req ) {
517550 dbg . log0 ( 'put_bucket_policy:' , req . rpc_params ) ;
518551 const bucket = find_bucket ( req , req . rpc_params . name ) ;
519552 await bucket_policy_utils . validate_s3_policy ( req . rpc_params . policy , bucket . name ,
520- principal => system_store . get_account_by_email ( principal ) ) ;
553+ principal => get_account_by_principal ( principal ) ) ;
521554
522555 if (
523556 bucket . public_access_block ?. block_public_policy &&
0 commit comments