Skip to content

Commit c11ab71

Browse files
committed
IAM | Change bucket owner for IAM user to account and more
Signed-off-by: Naveen Paul <[email protected]>
1 parent 69e29e1 commit c11ab71

File tree

5 files changed

+48
-37
lines changed

5 files changed

+48
-37
lines changed

src/sdk/accountspace_nb.js

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
'use strict';
33

44
const _ = require('lodash');
5-
const SensitiveString = require('../util/sensitive_string');
65
const account_util = require('../util/account_util');
76
const iam_utils = require('../endpoint/iam/iam_utils');
87
const dbg = require('../util/debug_module')(__filename);
@@ -48,7 +47,7 @@ class AccountSpaceNB {
4847
{ username: params.username, path: params.iam_path });
4948
account_util._check_username_already_exists(action, params, requesting_account);
5049
const iam_arn = iam_utils.create_arn_for_user(requesting_account._id.toString(), params.username, params.iam_path);
51-
const account_name = account_util.get_account_name_from_username(params.username, requesting_account.name.unwrap());
50+
const account_name = account_util.get_account_name_from_username(params.username, requesting_account._id);
5251
const req = {
5352
rpc_params: {
5453
name: account_name,
@@ -60,16 +59,14 @@ class AccountSpaceNB {
6059
is_iam: true,
6160
iam_arn: iam_arn,
6261
iam_path: params.iam_path,
63-
role: 'iam_user',
62+
role: 'admin',
6463

6564
// TODO: default_resource remove
6665
default_resource: 'noobaa-default-backing-store',
6766
},
6867
account: requesting_account,
6968
};
70-
// CORE CHANGES PENDING - START
7169
const iam_account = await account_util.create_account(req);
72-
// CORE CHANGES PENDING - END
7370

7471
// TODO : Clean account cache
7572
// TODO : Send Event
@@ -87,19 +84,19 @@ class AccountSpaceNB {
8784
async get_user(params, account_sdk) {
8885
const action = IAM_ACTIONS.GET_USER;
8986
const requesting_account = system_store.get_account_by_email(account_sdk.requesting_account.email);
90-
const account_name = account_util.get_account_name_from_username(params.username, requesting_account.name.unwrap());
87+
const account_name = account_util.get_account_name_from_username(params.username, requesting_account._id);
9188
const requested_account = system_store.get_account_by_email(account_name);
9289
account_util._check_if_requesting_account_is_root_account(action, requesting_account,
9390
{ username: params.username, iam_path: params.iam_path });
9491
account_util._check_if_account_exists(action, account_name);
9592
account_util._check_if_requested_account_is_root_account_or_IAM_user(action, requesting_account, requested_account);
9693
account_util._check_if_requested_is_owned_by_root_account(action, requesting_account, requested_account);
94+
const iam_arn = iam_utils.create_arn_for_user(requesting_account._id.toString(), params.username, requested_account.iam_path);
9795
const reply = {
9896
user_id: requested_account._id.toString(),
99-
// TODO : IAM PATH
10097
iam_path: requested_account.iam_path || IAM_DEFAULT_PATH,
10198
username: account_util.get_iam_username(requested_account.name.unwrap()),
102-
arn: requested_account.iam_arn,
99+
arn: iam_arn,
103100
// TODO: GAP Need to save created date
104101
create_date: Date.now(),
105102
// TODO: Dates missing : GAP
@@ -111,7 +108,7 @@ class AccountSpaceNB {
111108
async update_user(params, account_sdk) {
112109
const action = IAM_ACTIONS.UPDATE_USER;
113110
const requesting_account = system_store.get_account_by_email(account_sdk.requesting_account.email);
114-
const username = account_util.get_account_name_from_username(params.username, requesting_account.name.unwrap());
111+
const username = account_util.get_account_name_from_username(params.username, requesting_account._id);
115112
account_util._check_if_requesting_account_is_root_account(action, requesting_account,
116113
{ username: params.username, iam_path: params.iam_path });
117114
account_util._check_if_account_exists(action, username);
@@ -124,14 +121,12 @@ class AccountSpaceNB {
124121
if (params.new_iam_path !== undefined) iam_path = params.new_iam_path;
125122
if (params.new_username !== undefined) user_name = params.new_username;
126123
const iam_arn = iam_utils.create_arn_for_user(requested_account._id.toString(), user_name, iam_path);
127-
const new_account_name = new SensitiveString(`${params.new_username}:${requesting_account.name.unwrap()}`);
124+
const new_account_name = account_util.get_account_name_from_username(params.new_username, requesting_account._id);
128125
const updates = {
129126
name: new_account_name,
130127
email: new_account_name,
131-
iam_arn: iam_arn,
132128
iam_path: iam_path,
133129
};
134-
// CORE CHANGES PENDING - START
135130
await system_store.make_changes({
136131
update: {
137132
accounts: [{
@@ -140,11 +135,9 @@ class AccountSpaceNB {
140135
}]
141136
}
142137
});
143-
// CORE CHANGES PENDING - END
144138
// TODO : Clean account cache
145139
// TODO : Send Event
146140
return {
147-
// TODO: IAM path needs to be saved
148141
iam_path: iam_path || IAM_DEFAULT_PATH,
149142
username: user_name,
150143
user_id: requested_account._id.toString(),
@@ -156,14 +149,15 @@ class AccountSpaceNB {
156149
async delete_user(params, account_sdk) {
157150
const action = IAM_ACTIONS.DELETE_USER;
158151
const requesting_account = system_store.get_account_by_email(account_sdk.requesting_account.email);
159-
const username = account_util.get_account_name_from_username(params.username, requesting_account.name.unwrap());
152+
const username = account_util.get_account_name_from_username(params.username, requesting_account._id);
160153
account_util._check_if_requesting_account_is_root_account(action, requesting_account, { username: params.username });
161154
account_util._check_if_account_exists(action, username);
162155
const requested_account = system_store.get_account_by_email(username);
163156
account_util._check_if_requested_account_is_root_account_or_IAM_user(action, requesting_account, requested_account);
164157
account_util._check_if_requested_is_owned_by_root_account(action, requesting_account, requested_account);
158+
// Need to delete all accesskeys before deleting user
159+
account_util._check_if_user_does_not_have_access_keys_before_deletion(action, requested_account);
165160
// TODO: DELETE INLINE POLICY : Manually
166-
// TODO: DELETE ACCESS KEY : manually
167161
const req = {
168162
system: system_store.data.systems[0],
169163
account: requested_account,
@@ -181,28 +175,28 @@ class AccountSpaceNB {
181175
account_util._check_if_requesting_account_is_root_account(action, requesting_account, { });
182176
const is_truncated = false; // GAP - no pagination at this point
183177

184-
const root_name = requesting_account.name.unwrap();
185-
// CORE CHANGES PENDING - START
178+
186179
const requesting_account_iam_users = _.filter(system_store.data.accounts, function(acc) {
187180
if (!acc.name.unwrap().includes(IAM_SPLIT_CHARACTERS)) {
188181
return false;
189182
}
190-
return acc.name.unwrap().split(IAM_SPLIT_CHARACTERS)[1] === root_name;
183+
return acc.name.unwrap().split(IAM_SPLIT_CHARACTERS)[1] === requesting_account._id.toString();
191184
});
192185
let members = _.map(requesting_account_iam_users, function(iam_user) {
186+
const iam_username = account_util.get_iam_username(iam_user.name.unwrap());
187+
const iam_path = iam_user.iam_path || IAM_DEFAULT_PATH;
193188
const member = {
194189
user_id: iam_user._id.toString(),
195-
iam_path: iam_user.iam_path || IAM_DEFAULT_PATH,
196-
username: iam_user.name.unwrap().split(IAM_SPLIT_CHARACTERS)[0],
197-
arn: iam_user.iam_arn,
190+
iam_path: iam_path,
191+
username: iam_username,
192+
arn: iam_utils.create_arn_for_user(iam_user._id.toString(), iam_username, iam_path),
198193
// TODO: GAP Need to save created date
199194
create_date: Date.now(),
200195
// TODO: GAP missing password_last_used
201196
password_last_used: Date.now(), // GAP
202197
};
203198
return member;
204199
});
205-
// CORE CHANGES PENDING - END
206200
members = members.sort((a, b) => a.username.localeCompare(b.username));
207201
return { members, is_truncated };
208202
}
@@ -215,7 +209,7 @@ class AccountSpaceNB {
215209
const action = IAM_ACTIONS.CREATE_ACCESS_KEY;
216210
const requesting_account = system_store.get_account_by_email(account_sdk.requesting_account.email);
217211
const requested_account = validate_and_return_requested_account(params, action, requesting_account, account_sdk);
218-
const account_email = params.username ? new SensitiveString(`${params.username}:${requesting_account.name.unwrap()}`) :
212+
const account_email = params.username ? account_util.get_account_name_from_username(params.username, requesting_account._id) :
219213
account_sdk.requesting_account.email;
220214
account_util._check_number_of_access_key_array(action, requested_account);
221215
const req = {
@@ -225,7 +219,6 @@ class AccountSpaceNB {
225219
},
226220
account: requesting_account,
227221
};
228-
// CORE CHANGES PENDING - START
229222
let iam_access_key;
230223
try {
231224
iam_access_key = await account_util.generate_account_keys(req);
@@ -236,8 +229,6 @@ class AccountSpaceNB {
236229
throw new IamError({ code, message: message_with_details, http_code, type });
237230
}
238231

239-
// CORE CHANGES PENDING - STOP
240-
241232
return {
242233
username: params.username,
243234
access_key: iam_access_key.access_key.unwrap(),
@@ -362,7 +353,7 @@ function validate_and_return_requested_account(params, action, requesting_accoun
362353
// So in that case requesting account and requested account is same.
363354
requested_account = requesting_account;
364355
} else {
365-
const account_email = account_util.get_account_name_from_username(params.username, requesting_account.name.unwrap());
356+
const account_email = account_util.get_account_name_from_username(params.username, requesting_account._id);
366357
account_util._check_if_account_exists(action, account_email);
367358
requested_account = system_store.get_account_by_email(account_email);
368359
account_util._check_if_requesting_account_is_root_account(action, requesting_account, { username: params.username });

src/server/system_services/bucket_server.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,14 @@ async function create_bucket(req) {
241241

242242
validate_non_nsfs_bucket_creation(req);
243243
validate_nsfs_bucket(req);
244-
244+
// Buckets created by IAM users are owned by the IAM account the user belongs to.
245+
let account_id = req.account._id;
246+
// Only IAM user will have owner.
247+
if (req.account.owner) {
248+
account_id = req.account.owner._id;
249+
}
245250
const bucket = new_bucket_defaults(req.rpc_params.name, req.system._id,
246-
tiering_policy && tiering_policy._id, req.account._id, req.rpc_params.tag, req.rpc_params.lock_enabled);
251+
tiering_policy && tiering_policy._id, account_id, req.rpc_params.tag, req.rpc_params.lock_enabled);
247252

248253
const bucket_m_key = system_store.master_key_manager.new_master_key({
249254
description: `master key of ${bucket._id} bucket`,

src/server/system_services/schemas/account_schema.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ module.exports = {
3131
tagging: {
3232
$ref: 'common_api#/definitions/tagging',
3333
},
34-
iam_arn: { type: 'string' },
3534
iam_path: { type: 'string' },
3635
// default policy for new buckets
3736
default_resource: { objectid: true },

src/server/system_services/schemas/role_schema.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = {
2525
},
2626
role: {
2727
type: 'string',
28-
enum: ['admin', 'user', 'operator', 'iam_user']
28+
enum: ['admin', 'user', 'operator']
2929
},
3030
}
3131
};

src/util/account_util.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ async function create_account(req) {
113113
// TODO : remove rpc_params
114114
if (req.rpc_params.is_iam) {
115115
account.owner = req.rpc_params.owner;
116-
account.iam_arn = req.rpc_params.iam_arn;
117116
account.iam_path = req.rpc_params.iam_path;
118117
}
119118

@@ -318,9 +317,9 @@ function validate_assume_role_policy(policy) {
318317
}
319318

320319
// User name is first part is user provided name, and second part
321-
// is root account name, This will make the user name uniq accross system.
322-
function get_account_name_from_username(username, requesting_account_name) {
323-
return new SensitiveString(`${username}:${requesting_account_name}`);
320+
// is root account id, This will make the user name uniq accross system.
321+
function get_account_name_from_username(username, requesting_account_id) {
322+
return new SensitiveString(`${username}:${requesting_account_id}`);
324323
}
325324

326325
function get_iam_username(requested_account_name) {
@@ -367,7 +366,7 @@ function _check_if_requesting_account_is_root_account(action, requesting_account
367366
}
368367

369368
function _check_username_already_exists(action, params, requesting_account) {
370-
const username = get_account_name_from_username(params.username, requesting_account.name.unwrap());
369+
const username = get_account_name_from_username(params.username, requesting_account._id);
371370
const account = system_store.get_account_by_email(username);
372371
if (account) {
373372
dbg.error(`AccountSpaceNB.${action} username already exists`, params.username);
@@ -406,6 +405,14 @@ function _check_if_requested_is_owned_by_root_account(action, requesting_account
406405
}
407406
}
408407

408+
function _check_if_user_does_not_have_access_keys_before_deletion(action, account_to_delete) {
409+
const resource_name = 'access keys';
410+
const is_access_keys_exists = account_to_delete.access_keys && account_to_delete.access_keys.length > 0;
411+
if (is_access_keys_exists) {
412+
_throw_error_delete_conflict(action, account_to_delete, resource_name);
413+
}
414+
}
415+
409416
/**
410417
* _returned_username would return the username of IAM Access key API:
411418
* 1. undefined - for root accounts manager on root account (no username, only account name)
@@ -423,6 +430,14 @@ function _returned_username(requesting_account, username, on_itself) {
423430
return username instanceof SensitiveString ? username.unwrap() : username;
424431
}
425432

433+
function _throw_error_delete_conflict(action, account_to_delete, resource_name) {
434+
dbg.error(`AccountSpaceFS.${action} requested account ` +
435+
`${account_to_delete.name} ${account_to_delete._id} has ${resource_name}`);
436+
const message_with_details = `Cannot delete entity, must delete ${resource_name} first.`;
437+
const { code, http_code, type } = IamError.DeleteConflict;
438+
throw new IamError({ code, message: message_with_details, http_code, type });
439+
}
440+
426441
function _throw_error_perform_action_from_root_accounts_manager_on_iam_user(action, requesting_account, requested_account) {
427442
dbg.error(`AccountSpaceNB.${action} root accounts manager cannot perform actions on IAM users`,
428443
requesting_account, requested_account);
@@ -656,6 +671,7 @@ exports._check_if_requesting_account_is_root_account = _check_if_requesting_acco
656671
exports._check_username_already_exists = _check_username_already_exists;
657672
exports._check_number_of_access_key_array = _check_number_of_access_key_array;
658673
exports._check_access_key_belongs_to_account = _check_access_key_belongs_to_account;
674+
exports._check_if_user_does_not_have_access_keys_before_deletion = _check_if_user_does_not_have_access_keys_before_deletion;
659675
exports._get_access_key_status = _get_access_key_status;
660676
exports._check_access_key_is_deactivated = _check_access_key_is_deactivated;
661677
exports._list_access_keys_from_account = _list_access_keys_from_account;

0 commit comments

Comments
 (0)