Skip to content

Commit 9adb264

Browse files
committed
IAM | Fix GetAccessKeyLastUsed API
Signed-off-by: shirady <57721533+shirady@users.noreply.github.com>
1 parent c74f48a commit 9adb264

File tree

3 files changed

+111
-5
lines changed

3 files changed

+111
-5
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: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const { rpc_client, EMAIL, get_current_setup_options, stop_nsfs_process, start_n
4141
let iam_account;
4242
let account_res;
4343
let config_root;
44+
let coretest_endpoint_iam;
4445

4546
mocha.describe('IAM integration tests', async function() {
4647
this.timeout(50000); // eslint-disable-line no-invalid-this
@@ -68,7 +69,7 @@ mocha.describe('IAM integration tests', async function() {
6869
}
6970

7071
// needed details for creating the account (and then the client)
71-
const coretest_endpoint_iam = coretest.get_https_address_iam();
72+
coretest_endpoint_iam = coretest.get_https_address_iam();
7273
const access_key = account_res.access_key instanceof SensitiveString ?
7374
account_res.access_key.unwrap() :
7475
account_res.access_key;
@@ -217,8 +218,6 @@ mocha.describe('IAM integration tests', async function() {
217218
});
218219

219220
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
222221
const input = {
223222
AccessKeyId: access_key_id
224223
};
@@ -1057,6 +1056,55 @@ mocha.describe('IAM integration tests', async function() {
10571056
});
10581057

10591058
});
1059+
1060+
mocha.describe('IAM Access Keys API', async function() {
1061+
const username2 = 'Alejandro';
1062+
let access_key_id;
1063+
let secret_access_key;
1064+
1065+
mocha.describe('IAM GetAccessKeyLastUsed API', async function() {
1066+
mocha.before(async () => {
1067+
await create_iam_user(username2);
1068+
const res = await create_access_key_iam_user(username2);
1069+
access_key_id = res.access_key_id;
1070+
secret_access_key = res.secret_access_key;
1071+
});
1072+
1073+
mocha.after(async () => {
1074+
await delete_access_key_iam_user(access_key_id, username2);
1075+
await delete_iam_user(username2);
1076+
});
1077+
1078+
mocha.it('get access key last used with invalid access key ID should fail', async function() {
1079+
const access_key_id_invalid = access_key_id + '0';
1080+
try {
1081+
const input = {
1082+
AccessKeyId: access_key_id_invalid
1083+
};
1084+
const command = new GetAccessKeyLastUsedCommand(input);
1085+
await iam_account.send(command);
1086+
assert.fail('get access key last used with invalid access key ID - should throw an error');
1087+
} catch (err) {
1088+
const err_code = err.Error.Code;
1089+
assert.equal(err_code, IamError.NoSuchEntity.code);
1090+
}
1091+
});
1092+
1093+
mocha.it('get access key last used with by IAM user should succeed', async function() {
1094+
const iam_user_account = generate_iam_client(access_key_id, secret_access_key, coretest_endpoint_iam);
1095+
const input = {
1096+
AccessKeyId: access_key_id
1097+
};
1098+
const command = new GetAccessKeyLastUsedCommand(input);
1099+
const response = await iam_user_account.send(command);
1100+
_check_status_code_ok(response);
1101+
assert.equal(response.UserName, username2);
1102+
assert(response.AccessKeyLastUsed.LastUsedDate !== undefined);
1103+
assert(response.AccessKeyLastUsed.ServiceName !== undefined);
1104+
assert(response.AccessKeyLastUsed.Region !== undefined);
1105+
});
1106+
});
1107+
});
10601108
});
10611109
});
10621110

@@ -1095,3 +1143,36 @@ async function delete_iam_user(username_to_delete) {
10951143
const response = await iam_account.send(command);
10961144
_check_status_code_ok(response);
10971145
}
1146+
1147+
1148+
/**
1149+
* Create an IAM user's access key with the given username.
1150+
* use this function for before/after hooks to avoid code duplication
1151+
* @param {string} username
1152+
*/
1153+
async function create_access_key_iam_user(username) {
1154+
const input = {
1155+
UserName: username
1156+
};
1157+
const command = new CreateAccessKeyCommand(input);
1158+
const response = await iam_account.send(command);
1159+
_check_status_code_ok(response);
1160+
return { access_key_id: response.AccessKey.AccessKeyId, secret_access_key: response.AccessKey.SecretAccessKey };
1161+
}
1162+
1163+
1164+
/**
1165+
* Delete an IAM user's access key with the given access key ID and username.
1166+
* use this function for before/after hooks to avoid code duplication
1167+
* @param {string} access_key_to_delete
1168+
* @param {string} username
1169+
*/
1170+
async function delete_access_key_iam_user(access_key_to_delete, username) {
1171+
const input = {
1172+
UserName: username,
1173+
AccessKeyId: access_key_to_delete
1174+
};
1175+
const command = new DeleteAccessKeyCommand(input);
1176+
const response = await iam_account.send(command);
1177+
_check_status_code_ok(response);
1178+
}

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)