Skip to content

NC | ConfigFS | Create prepare for schema functions and some manage_nsfs refactoring #8297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
339 changes: 161 additions & 178 deletions src/cmd/manage_nsfs.js

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions src/manage_nsfs/manage_nsfs_cli_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,30 @@ function check_root_account_owns_user(root_account, account) {
}


/**
* is_name_update returns true if a new_name flag was provided and it's not equal to
* the current name
* @param {Object} data
* @returns {Boolean}
*/
function is_name_update(data) {
const cur_name = data.name;
const new_name = data.new_name;
return new_name && cur_name && new_name !== cur_name;
}

/**
* is_access_key_update returns true if a new_access_key flag was provided and it's not equal to
* the current access_key at index 0
* @param {Object} data
* @returns {Boolean}
*/
function is_access_key_update(data) {
const cur_access_key = has_access_keys(data.access_keys) ? data.access_keys[0].access_key.unwrap() : undefined;
const new_access_key = data.new_access_key;
return new_access_key && cur_access_key && new_access_key !== cur_access_key;
}

// EXPORTS
exports.throw_cli_error = throw_cli_error;
exports.write_stdout_response = write_stdout_response;
Expand All @@ -144,3 +168,5 @@ exports.has_access_keys = has_access_keys;
exports.generate_id = generate_id;
exports.set_debug_level = set_debug_level;
exports.check_root_account_owns_user = check_root_account_owns_user;
exports.is_name_update = is_name_update;
exports.is_access_key_update = is_access_key_update;
42 changes: 39 additions & 3 deletions src/manage_nsfs/manage_nsfs_validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const string_utils = require('../util/string_utils');
const native_fs_utils = require('../util/native_fs_utils');
const ManageCLIError = require('../manage_nsfs/manage_nsfs_cli_errors').ManageCLIError;
const bucket_policy_utils = require('../endpoint/s3/s3_bucket_policy_utils');
const { throw_cli_error, get_options_from_file, get_boolean_or_string_value,
check_root_account_owns_user, get_bucket_owner_account} = require('../manage_nsfs/manage_nsfs_cli_utils');
const { throw_cli_error, get_bucket_owner_account, get_options_from_file, get_boolean_or_string_value,
check_root_account_owns_user, is_name_update, is_access_key_update } = require('../manage_nsfs/manage_nsfs_cli_utils');
const { TYPES, ACTIONS, VALID_OPTIONS, OPTION_TYPE, FROM_FILE, BOOLEAN_STRING_VALUES, BOOLEAN_STRING_OPTIONS,
GLACIER_ACTIONS, LIST_UNSETABLE_OPTIONS, ANONYMOUS, DIAGNOSE_ACTIONS } = require('../manage_nsfs/manage_nsfs_constants');
const iam_utils = require('../endpoint/iam/iam_utils');
Expand Down Expand Up @@ -300,12 +300,43 @@ function validate_account_name(type, action, input_options_with_data) {
* @param {object} input_options
*/
function validate_bucket_identifier(action, input_options) {
if (action === ACTIONS.STATUS || action === ACTIONS.ADD || action === ACTIONS.UPDATE || action === ACTIONS.DELETE) {
if (action === ACTIONS.STATUS || action === ACTIONS.ADD || action === ACTIONS.UPDATE || action === ACTIONS.DELETE) {
if (input_options.name === undefined) throw_cli_error(ManageCLIError.MissingBucketNameFlag);
}
// in list there is no identifier
}

/**
* check_new_name_exists will validate that a new account/bucket name does not exist
* @param {import('../sdk/config_fs').ConfigFS} config_fs
* @param {string} action
* @param {object} data
*/
async function check_new_name_exists(type, config_fs, action, data) {
const new_name = action === ACTIONS.ADD ? data.name : data.new_name;
if (action === ACTIONS.UPDATE && !is_name_update(data)) return;
if (type === TYPES.BUCKET) {
const exists = await config_fs.is_bucket_exists(new_name);
if (exists) throw_cli_error(ManageCLIError.BucketAlreadyExists, new_name, { bucket: new_name });
} else if (type === TYPES.ACCOUNT) {
const exists = await config_fs.is_account_exists_by_name(new_name);
if (exists) throw_cli_error(ManageCLIError.AccountNameAlreadyExists, new_name, { account: new_name });
}
}

/**
* check_new_access_key_exists will validate that a new access_key does not exist
* @param {import('../sdk/config_fs').ConfigFS} config_fs
* @param {string} action
* @param {object} data
*/
async function check_new_access_key_exists(config_fs, action, data) {
const new_access_key = action === ACTIONS.ADD ? data.access_keys?.[0]?.access_key : data.new_access_key;
if (action === ACTIONS.UPDATE && !is_access_key_update(data)) return;
const exists = await config_fs.is_account_exists_by_access_key(new_access_key);
if (exists) throw_cli_error(ManageCLIError.AccountAccessKeyAlreadyExists, new_access_key, { account: new_access_key });
}

/**
* validate_bucket_args will validate the cli args of the bucket command
* @param {import('../sdk/config_fs').ConfigFS} config_fs
Expand All @@ -322,6 +353,7 @@ async function validate_bucket_args(config_fs, data, action) {
if (data.fs_backend !== undefined && !['GPFS', 'CEPH_FS', 'NFSv4'].includes(data.fs_backend)) {
throw_cli_error(ManageCLIError.InvalidFSBackend);
}
await check_new_name_exists(TYPES.BUCKET, config_fs, action, data);
// in case we have the fs_backend it changes the fs_context that we use for the path
const fs_context_fs_backend = native_fs_utils.get_process_fs_context(data.fs_backend);
const exists = await native_fs_utils.is_path_exists(fs_context_fs_backend, data.path);
Expand Down Expand Up @@ -396,6 +428,10 @@ function validate_account_identifier(action, input_options) {
*/
async function validate_account_args(config_fs, data, action, is_flag_iam_operate_on_root_account_update_action) {
if (action === ACTIONS.ADD || action === ACTIONS.UPDATE) {

await check_new_name_exists(TYPES.ACCOUNT, config_fs, action, data);
await check_new_access_key_exists(config_fs, action, data);

if (data.nsfs_account_config.gid && data.nsfs_account_config.uid === undefined) {
throw_cli_error(ManageCLIError.MissingAccountNSFSConfigUID, data.nsfs_account_config);
}
Expand Down
32 changes: 6 additions & 26 deletions src/sdk/accountspace_fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const native_fs_utils = require('../util/native_fs_utils');
const { create_arn, get_action_message_title, check_iam_path_was_set } = require('../endpoint/iam/iam_utils');
const { IAM_ACTIONS, MAX_NUMBER_OF_ACCESS_KEYS, IAM_DEFAULT_PATH,
ACCESS_KEY_STATUS_ENUM, IDENTITY_ENUM } = require('../endpoint/iam/iam_constants');
const nsfs_schema_utils = require('../manage_nsfs/nsfs_schema_utils');
const IamError = require('../endpoint/iam/iam_errors').IamError;
const cloud_utils = require('../util/cloud_utils');
const SensitiveString = require('../util/sensitive_string');
Expand Down Expand Up @@ -150,10 +149,7 @@ class AccountSpaceFS {
is_username_update);
await this._update_account_config_new_username(action, params, requested_account);
} else {
const requested_account_encrypted = await nc_mkm.encrypt_access_keys(requested_account);
const account_string = JSON.stringify(requested_account_encrypted);
nsfs_schema_utils.validate_account_schema(JSON.parse(account_string));
await this.config_fs.update_account_config_file(JSON.parse(account_string));
await this.config_fs.update_account_config_file(requested_account);
}
this._clean_account_cache(requested_account);
return {
Expand Down Expand Up @@ -265,11 +261,8 @@ class AccountSpaceFS {
deactivated: false,
};
requested_account.access_keys.push(created_access_key_obj);
const requested_account_encrypted = await nc_mkm.encrypt_access_keys(requested_account);
const account_to_create_access_keys_string = JSON.stringify(requested_account_encrypted);
nsfs_schema_utils.validate_account_schema(JSON.parse(account_to_create_access_keys_string));
await this.config_fs.update_account_config_file(
JSON.parse(account_to_create_access_keys_string),
requested_account,
{ new_access_keys_to_link: [created_access_key_obj] }
);
return {
Expand Down Expand Up @@ -355,10 +348,7 @@ class AccountSpaceFS {
return;
}
access_key_obj.deactivated = this._check_access_key_is_deactivated(params.status);
const requested_account_encrypted = await nc_mkm.encrypt_access_keys(requested_account);
const account_string = JSON.stringify(requested_account_encrypted);
nsfs_schema_utils.validate_account_schema(JSON.parse(account_string));
await this.config_fs.update_account_config_file(JSON.parse(account_string));
await this.config_fs.update_account_config_file(requested_account);
this._clean_account_cache(requested_account);
} catch (err) {
dbg.error(`AccountSpaceFS.${action} error`, err);
Expand Down Expand Up @@ -398,11 +388,8 @@ class AccountSpaceFS {
}
requested_account.access_keys = requested_account.access_keys.filter(access_key_obj =>
access_key_obj.access_key !== access_key_id);
const requested_account_encrypted = await nc_mkm.encrypt_access_keys(requested_account);
const account_string = JSON.stringify(requested_account_encrypted);
nsfs_schema_utils.validate_account_schema(JSON.parse(account_string));
await this.config_fs.update_account_config_file(
JSON.parse(account_string),
requested_account,
{ access_keys_to_delete: [{ access_key: access_key_id }] }
);
this._clean_account_cache(requested_account);
Expand Down Expand Up @@ -628,9 +615,7 @@ class AccountSpaceFS {
const master_key_id = await nc_mkm.get_active_master_key_id();
const created_account = this._new_user_defaults(requesting_account, params, master_key_id);
dbg.log1(`AccountSpaceFS.${action} new_account`, created_account);
const new_account_string = JSON.stringify(created_account);
nsfs_schema_utils.validate_account_schema(JSON.parse(new_account_string));
await this.config_fs.create_account_config_file(JSON.parse(new_account_string));
await this.config_fs.create_account_config_file(created_account);
return created_account;
}

Expand Down Expand Up @@ -665,8 +650,6 @@ class AccountSpaceFS {
this._check_if_user_does_not_have_access_keys_before_deletion(action, account_to_delete);
}

// TODO - when we have the structure of config we can check easily which buckets are owned by the root account
// currently, partial copy from verify_account_not_owns_bucket
async _check_if_root_account_does_not_have_buckets_before_deletion(action, account_to_delete) {
const resource_name = 'buckets';
const bucket_names = await this.config_fs.list_buckets();
Expand Down Expand Up @@ -710,10 +693,7 @@ class AccountSpaceFS {
requested_account.name = params.new_username;
requested_account.email = params.new_username; // internally saved
// handle account config creation
const requested_account_encrypted = await nc_mkm.encrypt_access_keys(requested_account);
const account_string = JSON.stringify(requested_account_encrypted);
nsfs_schema_utils.validate_account_schema(JSON.parse(account_string));
await this.config_fs.update_account_config_file(JSON.parse(account_string), { old_name: params.username });
await this.config_fs.update_account_config_file(requested_account, { old_name: params.username });
}

_check_root_account_or_user(requesting_account, username) {
Expand Down
Loading