Skip to content

Commit 1f497fa

Browse files
authored
Merge pull request #9340 from shirady/iam-fix-get-access-key-last-used
IAM | Fix `GetAccessKeyLastUsed` API
2 parents 112a266 + d606be8 commit 1f497fa

File tree

3 files changed

+93
-4
lines changed

3 files changed

+93
-4
lines changed

src/server/system_services/account_server.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,10 +1394,11 @@ async function update_access_key(req) {
13941394
async function get_access_key_last_used(req) {
13951395
const action = IAM_ACTIONS.GET_ACCESS_KEY_LAST_USED;
13961396
const requesting_account = req.account;
1397-
const requested_account = account_util.validate_and_return_requested_account(req.rpc_params, action, requesting_account);
1397+
const access_key_id = req.rpc_params.access_key;
1398+
const requested_account = account_util._check_if_iam_user_belongs_to_account_owner_by_access_key(
1399+
action, requesting_account, access_key_id);
13981400
const dummy_region = 'us-west-2';
13991401
const dummy_service_name = 's3';
1400-
account_util._check_access_key_belongs_to_account(action, requesting_account, req.rpc_params.access_key);
14011402
// TODO: Need to return valid last_used_date date, Low priority.
14021403
return {
14031404
region: dummy_region, // GAP

src/test/integration_tests/api/iam/test_iam_basic_integration.js

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,6 @@ mocha.describe('IAM integration tests', async function() {
217217
});
218218

219219
mocha.it('get access key (last used)', async function() {
220-
// Skipping for containerized noobaa
221-
if (!is_nc_coretest) this.skip(); // eslint-disable-line no-invalid-this
222220
const input = {
223221
AccessKeyId: access_key_id
224222
};
@@ -1057,6 +1055,39 @@ mocha.describe('IAM integration tests', async function() {
10571055
});
10581056

10591057
});
1058+
1059+
mocha.describe('IAM Access Keys API', async function() {
1060+
const username2 = 'Alejandro';
1061+
let access_key_id;
1062+
1063+
mocha.describe('IAM GetAccessKeyLastUsed API', async function() {
1064+
mocha.before(async () => {
1065+
await create_iam_user(username2);
1066+
const res = await create_access_key_iam_user(username2);
1067+
access_key_id = res.access_key_id;
1068+
});
1069+
1070+
mocha.after(async () => {
1071+
await delete_access_key_iam_user(access_key_id, username2);
1072+
await delete_iam_user(username2);
1073+
});
1074+
1075+
mocha.it('get access key last used with invalid access key ID should fail', async function() {
1076+
const access_key_id_invalid = access_key_id + '0';
1077+
try {
1078+
const input = {
1079+
AccessKeyId: access_key_id_invalid
1080+
};
1081+
const command = new GetAccessKeyLastUsedCommand(input);
1082+
await iam_account.send(command);
1083+
assert.fail('get access key last used with invalid access key ID - should throw an error');
1084+
} catch (err) {
1085+
const err_code = err.Error.Code;
1086+
assert.equal(err_code, IamError.NoSuchEntity.code);
1087+
}
1088+
});
1089+
});
1090+
});
10601091
});
10611092
});
10621093

@@ -1095,3 +1126,36 @@ async function delete_iam_user(username_to_delete) {
10951126
const response = await iam_account.send(command);
10961127
_check_status_code_ok(response);
10971128
}
1129+
1130+
1131+
/**
1132+
* Create an IAM user's access key with the given username.
1133+
* use this function for before/after hooks to avoid code duplication
1134+
* @param {string} username
1135+
*/
1136+
async function create_access_key_iam_user(username) {
1137+
const input = {
1138+
UserName: username
1139+
};
1140+
const command = new CreateAccessKeyCommand(input);
1141+
const response = await iam_account.send(command);
1142+
_check_status_code_ok(response);
1143+
return { access_key_id: response.AccessKey.AccessKeyId, secret_access_key: response.AccessKey.SecretAccessKey };
1144+
}
1145+
1146+
1147+
/**
1148+
* Delete an IAM user's access key with the given access key ID and username.
1149+
* use this function for before/after hooks to avoid code duplication
1150+
* @param {string} access_key_to_delete
1151+
* @param {string} username
1152+
*/
1153+
async function delete_access_key_iam_user(access_key_to_delete, username) {
1154+
const input = {
1155+
UserName: username,
1156+
AccessKeyId: access_key_to_delete
1157+
};
1158+
const command = new DeleteAccessKeyCommand(input);
1159+
const response = await iam_account.send(command);
1160+
_check_status_code_ok(response);
1161+
}

src/util/account_util.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,29 @@ function _check_number_of_access_key_array(action, requested_account) {
479479
}
480480
}
481481

482+
function _check_if_iam_user_belongs_to_account_owner_by_access_key(action, requesting_account, access_key_id) {
483+
const access_key_id_wrapped = new SensitiveString(access_key_id);
484+
const requested_account = system_store.get_account_by_access_key(access_key_id_wrapped);
485+
if (!requested_account) {
486+
_throw_error_no_such_entity_access_key(action, access_key_id);
487+
}
488+
const is_account_on_himself = String(requesting_account._id) === String(requested_account._id);
489+
if (is_account_on_himself) {
490+
// didn't block an account from running action on itself since it not editing anything here
491+
return requested_account;
492+
} else {
493+
const is_root_account = _check_root_account(requesting_account);
494+
if (!is_root_account) {
495+
_throw_access_denied_error(action, requesting_account, { access_key: access_key_id }, "ACCESS_KEY");
496+
}
497+
const is_requested_account_owned_by_root_account = _check_root_account_owns_user(requesting_account, requested_account);
498+
if (!is_requested_account_owned_by_root_account) {
499+
_throw_error_no_such_entity_access_key(action, access_key_id);
500+
}
501+
return requested_account;
502+
}
503+
}
504+
482505
function _check_access_key_belongs_to_account(action, requested_account, access_key_id) {
483506
const is_access_key_belongs_to_account = _check_specific_access_key_exists(requested_account.access_keys, access_key_id);
484507
if (!is_access_key_belongs_to_account) {
@@ -777,3 +800,4 @@ exports.validate_and_return_requested_account = validate_and_return_requested_ac
777800
exports.return_list_member = return_list_member;
778801
exports.get_owner_account_id = get_owner_account_id;
779802
exports.get_sorted_list_tags_for_user = get_sorted_list_tags_for_user;
803+
exports._check_if_iam_user_belongs_to_account_owner_by_access_key = _check_if_iam_user_belongs_to_account_owner_by_access_key;

0 commit comments

Comments
 (0)