Skip to content

Commit

Permalink
NC CLI - restrict access keys chars
Browse files Browse the repository at this point in the history
Signed-off-by: Romy <35330373+romayalon@users.noreply.github.com>
  • Loading branch information
romayalon committed May 5, 2024
1 parent ff0007a commit c7a4eb4
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 130 deletions.
12 changes: 6 additions & 6 deletions src/manage_nsfs/manage_nsfs_cli_errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,15 @@ ManageCLIError.MissingAccountAccessKeyFlag = Object.freeze({
http_code: 400,
});

ManageCLIError.AccountSecretKeyFlagComplexity = Object.freeze({
code: 'AccountSecretKeyFlagComplexity',
message: 'Account secret length must be 40, and must contain uppercase, lowercase, numbers and symbols',
ManageCLIError.InvalidAccountSecretKeyFlag = Object.freeze({
code: 'InvalidAccountSecretKeyFlag',
message: 'Account secret length must be 40, and must contain only alpha-numeric chars, "+", "/"',
http_code: 400,
});

ManageCLIError.AccountAccessKeyFlagComplexity = Object.freeze({
code: 'AccountAccessKeyFlagComplexity',
message: 'Account access key length must be 20, and must contain uppercase and numbers',
ManageCLIError.InvalidAccountAccessKeyFlag = Object.freeze({
code: 'InvalidAccountAccessKeyFlag',
message: 'Account access key length must be 20, and must contain only alpha-numeric chars',
http_code: 400,
});

Expand Down
24 changes: 8 additions & 16 deletions src/manage_nsfs/manage_nsfs_validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,23 +316,15 @@ function _validate_access_keys(access_key, secret_key) {
if (!_.isUndefined(secret_key) && _.isUndefined(access_key)) {
throw_cli_error(ManageCLIError.MissingAccountAccessKeyFlag);
}
// checking the complexity of access_key
if (!_.isUndefined(access_key) && !string_utils.validate_complexity(access_key, {
require_length: 20,
check_uppercase: true,
check_lowercase: false,
check_numbers: true,
check_symbols: false,
})) throw_cli_error(ManageCLIError.AccountAccessKeyFlagComplexity);
// checking the complexity of secret_key
if (!_.isUndefined(secret_key) && !string_utils.validate_complexity(secret_key, {
require_length: 40,
check_uppercase: true,
check_lowercase: true,
check_numbers: true,
check_symbols: true,
})) throw_cli_error(ManageCLIError.AccountSecretKeyFlagComplexity);

// checking access_key length=20 and contains only alphanumeric chars
if (access_key && !string_utils.access_key_regexp.test(access_key)) {
throw_cli_error(ManageCLIError.InvalidAccountAccessKeyFlag);
}
// checking secret_key length=40 and contains only alphanumeric chars and +/
if (secret_key && !string_utils.secret_key_regexp.test(secret_key)) {
throw_cli_error(ManageCLIError.InvalidAccountSecretKeyFlag);
}
}

/**
Expand Down
26 changes: 21 additions & 5 deletions src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,36 @@ describe('manage nsfs cli account flow', () => {
assert_account(account_symlink, account_options);
});

it('should fail - cli update account access_key wrong complexity', async () => {
it('should fail - cli update account invalid access_key - invalid size', async () => {
const { type, secret_key, name, new_buckets_path, uid, gid } = defaults;
const account_options = { config_root, access_key: 'abc', secret_key, name, new_buckets_path, uid, gid };
const action = ACTIONS.UPDATE;
const res = await exec_manage_cli(type, action, account_options);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.AccountAccessKeyFlagComplexity.message);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.InvalidAccountAccessKeyFlag.message);
});

it('should fail - cli update account secret_key wrong complexity', async () => {
it('should fail - cli update account invalid access_key - contains "+" ', async () => {
const { type, secret_key, name, new_buckets_path, uid, gid } = defaults;
const account_options = { config_root, access_key: 'abc+abc+abc+abc+abc+', secret_key, name, new_buckets_path, uid, gid };
const action = ACTIONS.UPDATE;
const res = await exec_manage_cli(type, action, account_options);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.InvalidAccountAccessKeyFlag.message);
});

it('should fail - cli update account invalid secret_key - invalid size', async () => {
const { type, access_key, name, new_buckets_path, uid, gid } = defaults;
const account_options = { config_root, access_key, secret_key: 'abc', name, new_buckets_path, uid, gid };
const action = ACTIONS.UPDATE;
const res = await exec_manage_cli(type, action, account_options);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.AccountSecretKeyFlagComplexity.message);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.InvalidAccountSecretKeyFlag.message);
});

it('should fail - cli update account invalid secret_key - contains @', async () => {
const { type, access_key, name, new_buckets_path, uid, gid } = defaults;
const account_options = { config_root, access_key, secret_key: 'abcaabcabcabc@abcabcabc@abcabcabc@abcabc', name, new_buckets_path, uid, gid };
const action = ACTIONS.UPDATE;
const res = await exec_manage_cli(type, action, account_options);
expect(JSON.parse(res.stdout).error.message).toBe(ManageCLIError.InvalidAccountSecretKeyFlag.message);
});

it('should fail - cli create account integer uid and gid', async () => {
Expand Down Expand Up @@ -1137,7 +1153,7 @@ describe('manage nsfs cli account flow', () => {
const command_flags = {config_root, from_file: path_to_option_json_file_name};
// create the account
const res = await exec_manage_cli(type, action, command_flags);
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.AccountAccessKeyFlagComplexity.code);
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InvalidAccountAccessKeyFlag.code);
});

it('should fail - cli create account using from_file with additional flags (name)', async () => {
Expand Down
107 changes: 4 additions & 103 deletions src/util/string_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ const crypto = require('crypto');
const ALPHA_NUMERIC_CHARSET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const email_regexp = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i;
const escape_regexp = /[\\^$.*+?()[\]{}|]/g;
const uppercase_regexp = /[A-Z]/;
const lowercase_regexp = /[a-z]/;
const numbers_regexp = /\d/;
const symbols_regexp = /[!@#$%^&*(),.?":+-{}|<>]/;
const access_key_regexp = /^[a-zA-Z0-9]{20}$/;
const secret_key_regexp = /^[a-zA-Z0-9+/]{40}$/;

function crypto_random_string(len, charset = ALPHA_NUMERIC_CHARSET) {
// In order to not favor any specific chars over others we limit the maximum random value
Expand Down Expand Up @@ -148,99 +146,6 @@ function escape_reg_exp(str) {
return str.replace(escape_regexp, '\\$&');
}

/**
*
* @param {string} string
* @param {number} require_length
*/
function validate_length(string, require_length) {
if (string.length !== require_length) {
return false;
}
return true;
}

/**
* @param {string} string
* @param {boolean} check_uppercase
*/
function validate_uppercase(string, check_uppercase) {
const uppercase_test = uppercase_regexp.test(string);
if (check_uppercase && !uppercase_test) {
return false;
}
return true;
}

/**
* @param {string} string
* @param {boolean} check_lowercase
*/
function validate_lowercase(string, check_lowercase) {
const lowercase_test = lowercase_regexp.test(string);
if (check_lowercase && !lowercase_test) {
return false;
}
return true;
}

/**
* @param {string} string
* @param {boolean} check_numbers
*/
function validate_numbers(string, check_numbers) {
const numbers_test = numbers_regexp.test(string);
if (check_numbers && !numbers_test) {
return false;
}
return true;
}

/**
* @param {string} string
* @param {boolean} check_symbols
*/
function validate_symbols(string, check_symbols) {
const symbols_test = symbols_regexp.test(string);
if (check_symbols && !symbols_test) {
return false;
}
return true;
}


/**
* validate_complexity will validate the complexity of a string
*
* @param {string} string
* @param {{
* require_length?: number,
* check_uppercase?: boolean,
* check_lowercase?: boolean,
* check_numbers?: boolean,
* check_symbols?: boolean,
* }} options - Options for complexity validation.
*
* @returns {boolean}
*/
function validate_complexity(string, options = {}) {
const {
require_length = 20,
check_uppercase = true,
check_lowercase = true,
check_numbers = true,
check_symbols = true,
} = options;

return (
validate_length(string, require_length) &&
validate_uppercase(string, check_uppercase) &&
validate_lowercase(string, check_lowercase) &&
validate_numbers(string, check_numbers) &&
validate_symbols(string, check_symbols)
);
}

exports.ALPHA_NUMERIC_CHARSET = ALPHA_NUMERIC_CHARSET;
exports.crypto_random_string = crypto_random_string;
exports.left_pad_zeros = left_pad_zeros;
Expand All @@ -249,9 +154,5 @@ exports.rolling_hash = rolling_hash;
exports.equal_case_insensitive = equal_case_insensitive;
exports.is_email_address = is_email_address;
exports.escape_reg_exp = escape_reg_exp;
exports.validate_length = validate_length;
exports.validate_uppercase = validate_uppercase;
exports.validate_lowercase = validate_lowercase;
exports.validate_numbers = validate_numbers;
exports.validate_symbols = validate_symbols;
exports.validate_complexity = validate_complexity;
exports.access_key_regexp = access_key_regexp;
exports.secret_key_regexp = secret_key_regexp;

0 comments on commit c7a4eb4

Please sign in to comment.