@@ -15,7 +15,8 @@ const { OP_NAME_TO_ACTION } = require('../endpoint/sts/sts_rest');
1515const IamError = require ( '../endpoint/iam/iam_errors' ) . IamError ;
1616const { create_arn_for_user, get_action_message_title } = require ( '../endpoint/iam/iam_utils' ) ;
1717const { IAM_ACTIONS , MAX_NUMBER_OF_ACCESS_KEYS , IAM_DEFAULT_PATH ,
18- ACCESS_KEY_STATUS_ENUM , IAM_SPLIT_CHARACTERS } = require ( '../endpoint/iam/iam_constants' ) ;
18+ ACCESS_KEY_STATUS_ENUM , IAM_SPLIT_CHARACTERS , IAM_ACTIONS_USER_INLINE_POLICY ,
19+ AWS_LIMIT_CHARS_USER_INlINE_POLICY } = require ( '../endpoint/iam/iam_constants' ) ;
1920
2021const demo_access_keys = Object . freeze ( {
2122 access_key : new SensitiveString ( '123' ) ,
@@ -360,8 +361,7 @@ function _check_if_requesting_account_is_root_account(action, requesting_account
360361 dbg . log1 ( `AccountSpaceNB.${ action } requesting_account ID: ${ requesting_account . _id } ` +
361362 `name: ${ requesting_account . name . unwrap ( ) } ` , 'is_root_account' , is_root_account ) ;
362363 if ( ! is_root_account ) {
363- dbg . error ( `AccountSpaceNB.${ action } requesting account is not a root account` ,
364- requesting_account ) ;
364+ dbg . error ( `AccountSpaceNB.${ action } requesting account is not a root account` , requesting_account . _id ) ;
365365 _throw_access_denied_error ( action , requesting_account , user_details , "USER" ) ;
366366 }
367367}
@@ -449,6 +449,13 @@ function _throw_error_no_such_entity_access_key(action, access_key_id) {
449449 throw new IamError ( { code, message : message_with_details , http_code, type } ) ;
450450}
451451
452+ function _throw_error_no_such_entity_policy ( action , policy_name ) {
453+ dbg . error ( `AccountSpaceNB.${ action } The user policy with name does not exist` , policy_name ) ;
454+ const message_with_details = `The user policy with name ${ policy_name } cannot be found` ;
455+ const { code, http_code, type } = IamError . NoSuchEntity ;
456+ throw new IamError ( { code, message : message_with_details , http_code, type } ) ;
457+ }
458+
452459function _throw_access_denied_error ( action , requesting_account , details , entity ) {
453460 const full_action_name = get_action_message_title ( action ) ;
454461 const account_id_for_arn = _get_account_owner_id_for_arn ( requesting_account ) ;
@@ -459,7 +466,8 @@ function _throw_access_denied_error(action, requesting_account, details, entity)
459466 let message_with_details ;
460467 if ( entity === 'USER' ) {
461468 let user_message ;
462- if ( action === IAM_ACTIONS . LIST_ACCESS_KEYS ) {
469+ if ( action === IAM_ACTIONS . LIST_ACCESS_KEYS ||
470+ IAM_ACTIONS_USER_INLINE_POLICY . includes ( action ) ) {
463471 user_message = `user ${ details . username } ` ;
464472 } else {
465473 user_message = create_arn_for_user ( account_id_for_arn , details . username , details . path ) ;
@@ -473,6 +481,14 @@ function _throw_access_denied_error(action, requesting_account, details, entity)
473481 throw new IamError ( { code, message : message_with_details , http_code, type } ) ;
474482}
475483
484+ function _throw_error_delete_conflict ( action , account_to_delete , resource_name ) {
485+ dbg . error ( `AccountSpaceNB.${ action } requested account ` +
486+ `${ account_to_delete . name } ${ account_to_delete . _id } has ${ resource_name } ` ) ;
487+ const message_with_details = `Cannot delete entity, must delete ${ resource_name } first.` ;
488+ const { code, http_code, type } = IamError . DeleteConflict ;
489+ throw new IamError ( { code, message : message_with_details , http_code, type } ) ;
490+ }
491+
476492// ACCESS KEY VALIDATIONS
477493
478494function _check_number_of_access_key_array ( action , requested_account ) {
@@ -569,6 +585,63 @@ function _list_access_keys_from_account(requesting_account, account, on_itself)
569585 return members ;
570586}
571587
588+ function _check_user_policy_exists ( action , iam_user_policies , policy_name ) {
589+ const iam_user_policy_index = _get_iam_user_policy_index ( iam_user_policies , policy_name ) ;
590+ if ( iam_user_policy_index === - 1 ) {
591+ _throw_error_no_such_entity_policy ( action , policy_name ) ;
592+ }
593+ return iam_user_policy_index ;
594+ }
595+
596+ function _get_iam_user_policy_index ( iam_user_policies , policy_name ) {
597+ const iam_user_policy_index = iam_user_policies . findIndex ( current_iam_user_policy =>
598+ current_iam_user_policy . policy_name === policy_name ) ;
599+ return iam_user_policy_index ;
600+ }
601+
602+ function _check_total_policy_size ( iam_user_policies , username ) {
603+ const total_chars_size = _get_total_size_of_policies ( iam_user_policies ) ;
604+ if ( total_chars_size > AWS_LIMIT_CHARS_USER_INlINE_POLICY ) {
605+ const message_with_details = `Maximum policy size of 2048 bytes exceeded for user ${ username } ` ;
606+ const { code, http_code, type } = IamError . LimitExceeded ;
607+ throw new IamError ( { code, message : message_with_details , http_code, type } ) ;
608+ }
609+ }
610+
611+ // each char is byte and not including whitespaces
612+ function _get_total_size_of_policies ( iam_user_policies ) {
613+ let total_size = 0 ;
614+ for ( const iam_user_policy of iam_user_policies ) {
615+ const policy_as_string = JSON . stringify ( iam_user_policy ) ;
616+ total_size += policy_as_string . length ;
617+ }
618+ return total_size ;
619+ }
620+
621+ // only resources of IAM (without the case of root account)
622+ function _check_if_user_does_not_have_resources_before_deletion ( action , account_to_delete ) {
623+ _check_if_user_does_not_have_access_keys_before_deletion ( action , account_to_delete ) ;
624+ _check_if_user_does_not_have_user_policy_before_deletion ( action , account_to_delete ) ;
625+ }
626+
627+ function _check_if_user_does_not_have_access_keys_before_deletion ( action , account_to_delete ) {
628+ const resource_name = 'access keys' ;
629+ const access_keys = account_to_delete . access_keys || [ ] ;
630+ const is_access_keys_empty = access_keys . length === 0 ;
631+ if ( ! is_access_keys_empty ) {
632+ _throw_error_delete_conflict ( action , account_to_delete , resource_name ) ;
633+ }
634+ }
635+
636+ function _check_if_user_does_not_have_user_policy_before_deletion ( action , account_to_delete ) {
637+ const resource_name = 'policies' ;
638+ const iam_user_policies = account_to_delete . iam_user_policies || [ ] ;
639+ const is_policies_removed = iam_user_policies . length === 0 ;
640+ if ( ! is_policies_removed ) {
641+ _throw_error_delete_conflict ( action , account_to_delete , resource_name ) ;
642+ }
643+ }
644+
572645function validate_create_account_permissions ( req ) {
573646 const account = req . account ;
574647 //For new system creation, nothing to be checked
@@ -665,3 +738,7 @@ exports._check_if_account_exists = _check_if_account_exists;
665738exports . _returned_username = _returned_username ;
666739exports . _check_if_requested_is_owned_by_root_account = _check_if_requested_is_owned_by_root_account ;
667740exports . _check_if_requested_account_is_root_account_or_IAM_user = _check_if_requested_account_is_root_account_or_IAM_user ;
741+ exports . _get_iam_user_policy_index = _get_iam_user_policy_index ;
742+ exports . _check_user_policy_exists = _check_user_policy_exists ;
743+ exports . _check_if_user_does_not_have_resources_before_deletion = _check_if_user_does_not_have_resources_before_deletion ;
744+ exports . _check_total_policy_size = _check_total_policy_size ;
0 commit comments