Skip to content

Commit 504f3b4

Browse files
authored
Merge pull request #8359 from romayalon/romy-check-access-configuration
NC | Change Check Access Behavior
2 parents a3b5ab8 + 61bd3ee commit 504f3b4

12 files changed

+296
-41
lines changed

config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,8 @@ config.NC_MASTER_KEYS_MANAGER_REFRESH_THRESHOLD = -1; // currently we want to di
890890
config.MASTER_KEYS_EXEC_MAX_RETRIES = 3;
891891

892892
config.NC_DISABLE_ACCESS_CHECK = false;
893+
config.NC_DISABLE_HEALTH_ACCESS_CHECK = false;
894+
config.NC_DISABLE_POSIX_MODE_ACCESS_CHECK = true;
893895
config.NC_DISABLE_SCHEMA_CHECK = false;
894896

895897
////////// GPFS //////////

docs/NooBaaNonContainerized/ConfigFileCustomizations.md

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,16 @@ Warning: After setting this configuration, NooBaa will skip schema validations a
356356
```
357357
358358
359-
### 25. Disable Read/Write accessibility check -
359+
### 25. Disable Read accessibility check -
360360
* <u>Key</u>: `NC_DISABLE_ACCESS_CHECK`
361361
* <u>Type</u>: Boolean
362362
* <u>Default</u>: false
363-
* <u>Description</u>: This flag will disable Read/Write accessibility validations in the following flows -
364-
1. Bucket creation/update - NooBaa will not validate that the bucket owner has read/write permissions to the bucket's path.
365-
2. Account creation/update - NooBaa will not validate that the account owner has read/write permissions to the account's new_buckets_path.
366-
Warning - setting this configuration to true might result with unexpected behavior.
363+
* <u>Description</u>: Setting this flag to true will disable Read accessibility validations in the following flows -
364+
1. Bucket creation/update - NooBaa will not validate that the bucket owner has read permissions to the bucket's path.
365+
2. Account creation/update - NooBaa will not validate that the account owner has read permissions to the account's new_buckets_path.
366+
3. Health buckets and accounts accessibility check.
367+
Warning - setting this configuration to true might result with unexpected behavior.
368+
367369
* <u>Steps</u>:
368370
```
369371
1. Open /path/to/config_dir/config.json file.
@@ -372,6 +374,38 @@ Warning: After setting this configuration, NooBaa will skip schema validations a
372374
"NC_DISABLE_ACCESS_CHECK": true
373375
```
374376
377+
### 26. Disable Read accessibility check on the Health CLI -
378+
* <u>Key</u>: `NC_DISABLE_HEALTH_ACCESS_CHECK`
379+
* <u>Type</u>: Boolean
380+
* <u>Default</u>: false
381+
* <u>Description</u>: This flag will disable Read accessibility validations in Health check of buckets and accounts.
382+
383+
* <u>Steps</u>:
384+
```
385+
1. Open /path/to/config_dir/config.json file.
386+
2. Set the config key -
387+
Example:
388+
"NC_DISABLE_HEALTH_ACCESS_CHECK": true
389+
```
390+
391+
### 27. Disable Read/Write POSIX mode bits check -
392+
* <u>Key</u>: `NC_DISABLE_POSIX_MODE_ACCESS_CHECK`
393+
* <u>Type</u>: Boolean
394+
* <u>Default</u>: true
395+
* <u>Description</u>: Setting this flag to false will enable Read/Write mode bits accessibility validations by in the following flows -
396+
1. Bucket creation/update - NooBaa will validate that the bucket owner has read/write permissions to the bucket's path.
397+
2. Account creation/update - NooBaa will validate that the account owner has read/write permissions to the account's new_buckets_path.
398+
3. Health buckets and accounts accessibility check.
399+
Warning - This configuration is disabled by default because it's not supporting ACLs, setting this configuration to false won't support a check of the ACLs and be based only on mode bits check.
400+
401+
* <u>Steps</u>:
402+
```
403+
1. Open /path/to/config_dir/config.json file.
404+
2. Set the config key -
405+
Example:
406+
"NC_DISABLE_POSIX_MODE_ACCESS_CHECK": false
407+
```
408+
375409
376410
### 26. Set Endpoint process title -
377411
* <u>Key</u>: `ENDPOINT_PROCESS_TITLE`

src/manage_nsfs/health.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -474,12 +474,14 @@ async function is_new_buckets_path_valid(config_file_path, config_data, new_buck
474474
}
475475

476476
try {
477-
await nb_native().fs.stat(account_fs_context, new_buckets_path);
478-
const accessible = await native_fs_utils.is_dir_rw_accessible(account_fs_context, new_buckets_path);
479-
if (!accessible) {
480-
const new_err = new Error('ACCESS DENIED');
481-
new_err.code = 'EACCES';
482-
throw new_err;
477+
if (!_should_skip_health_access_check()) {
478+
await nb_native().fs.stat(account_fs_context, new_buckets_path);
479+
const accessible = await native_fs_utils.is_dir_accessible(account_fs_context, new_buckets_path);
480+
if (!accessible) {
481+
const new_err = new Error('ACCESS DENIED');
482+
new_err.code = 'EACCES';
483+
throw new_err;
484+
}
483485
}
484486
res_obj = get_valid_object(config_data.name, undefined, new_buckets_path);
485487
} catch (err) {
@@ -505,7 +507,9 @@ async function is_new_buckets_path_valid(config_file_path, config_data, new_buck
505507
async function is_bucket_storage_path_exists(fs_context, config_data, storage_path) {
506508
let res_obj;
507509
try {
508-
await nb_native().fs.stat(fs_context, storage_path);
510+
if (!_should_skip_health_access_check()) {
511+
await nb_native().fs.stat(fs_context, storage_path);
512+
}
509513
res_obj = get_valid_object(config_data.name, undefined, storage_path);
510514
} catch (err) {
511515
let err_code;
@@ -556,5 +560,13 @@ function get_invalid_object(name, config_path, storage_path, err_code) {
556560
};
557561
}
558562

563+
/**
564+
* _should_skip_access_check returns true if the health CLI should skip access check
565+
* @returns {Boolean}
566+
*/
567+
function _should_skip_health_access_check() {
568+
return config.NC_DISABLE_HEALTH_ACCESS_CHECK || config.NC_DISABLE_ACCESS_CHECK;
569+
}
570+
559571
exports.get_health_status = get_health_status;
560572
exports.NSFSHealth = NSFSHealth;

src/manage_nsfs/manage_nsfs_validations.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,17 +359,19 @@ async function validate_bucket_args(config_fs, data, action) {
359359
await check_new_name_exists(TYPES.BUCKET, config_fs, action, data);
360360
// in case we have the fs_backend it changes the fs_context that we use for the path
361361
const fs_context_fs_backend = native_fs_utils.get_process_fs_context(data.fs_backend);
362-
const exists = await native_fs_utils.is_path_exists(fs_context_fs_backend, data.path);
363-
if (!exists) {
364-
throw_cli_error(ManageCLIError.InvalidStoragePath, data.path);
362+
if (!config.NC_DISABLE_ACCESS_CHECK) {
363+
const exists = await native_fs_utils.is_path_exists(fs_context_fs_backend, data.path);
364+
if (!exists) {
365+
throw_cli_error(ManageCLIError.InvalidStoragePath, data.path);
366+
}
365367
}
366368

367369
// bucket owner account validations
368370
const owner_account_data = await get_bucket_owner_account(config_fs, undefined, data.owner_account);
369371
const account_fs_context = await native_fs_utils.get_fs_context(owner_account_data.nsfs_account_config,
370372
owner_account_data.nsfs_account_config.fs_backend);
371373
if (!config.NC_DISABLE_ACCESS_CHECK) {
372-
const accessible = await native_fs_utils.is_dir_rw_accessible(account_fs_context, data.path);
374+
const accessible = await native_fs_utils.is_dir_accessible(account_fs_context, data.path);
373375
if (!accessible) {
374376
throw_cli_error(ManageCLIError.InaccessibleStoragePath, data.path);
375377
}
@@ -454,13 +456,15 @@ async function validate_account_args(config_fs, data, action, is_flag_iam_operat
454456
}
455457
// in case we have the fs_backend it changes the fs_context that we use for the new_buckets_path
456458
const fs_context_fs_backend = native_fs_utils.get_process_fs_context(data.fs_backend);
457-
const exists = await native_fs_utils.is_path_exists(fs_context_fs_backend, data.nsfs_account_config.new_buckets_path);
458-
if (!exists) {
459-
throw_cli_error(ManageCLIError.InvalidAccountNewBucketsPath, data.nsfs_account_config.new_buckets_path);
459+
if (!config.NC_DISABLE_ACCESS_CHECK) {
460+
const exists = await native_fs_utils.is_path_exists(fs_context_fs_backend, data.nsfs_account_config.new_buckets_path);
461+
if (!exists) {
462+
throw_cli_error(ManageCLIError.InvalidAccountNewBucketsPath, data.nsfs_account_config.new_buckets_path);
463+
}
460464
}
461465
if (!config.NC_DISABLE_ACCESS_CHECK) {
462466
const account_fs_context = await native_fs_utils.get_fs_context(data.nsfs_account_config, data.fs_backend);
463-
const accessible = await native_fs_utils.is_dir_rw_accessible(account_fs_context, data.nsfs_account_config.new_buckets_path);
467+
const accessible = await native_fs_utils.is_dir_accessible(account_fs_context, data.nsfs_account_config.new_buckets_path);
464468
if (!accessible) {
465469
throw_cli_error(ManageCLIError.InaccessibleAccountNewBucketsPath, data.nsfs_account_config.new_buckets_path);
466470
}

src/sdk/config_fs.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class ConfigFS {
161161
}
162162

163163
/**
164-
* create_config_json_file created the config.json file with the configuration data
164+
* create_config_json_file creates the config.json file with the configuration data
165165
* @param {object} data
166166
* @returns {Promise<void>}
167167
*/
@@ -178,6 +178,13 @@ class ConfigFS {
178178
await native_fs_utils.update_config_file(this.fs_context, this.config_root, this.config_json_path, data);
179179
}
180180

181+
/**
182+
* delete_config_json_file deletes the config.json file
183+
* @returns {Promise<void>}
184+
*/
185+
async delete_config_json_file() {
186+
await native_fs_utils.delete_config_file(this.fs_context, this.config_root, this.config_json_path);
187+
}
181188

182189
/**
183190
* get_config_data reads a config file and returns its content

src/server/system_services/schemas/nsfs_config_schema.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,15 @@ const nsfs_node_config_schema = {
124124
},
125125
NC_DISABLE_ACCESS_CHECK: {
126126
type: 'boolean',
127-
doc: 'indicate whether read/write access will be validated on bucket/account creation/update.'
127+
doc: 'indicate whether read access will be validated on bucket/account creation/update and on the health check.'
128+
},
129+
NC_DISABLE_HEALTH_ACCESS_CHECK: {
130+
type: 'boolean',
131+
doc: 'indicate whether read access will be validated on bucket/account health check.'
132+
},
133+
NC_DISABLE_POSIX_MODE_ACCESS_CHECK: {
134+
type: 'boolean',
135+
doc: 'indicate whether posix mode read/write access will be validated on bucket/account creation/update and health check.'
128136
},
129137
ENDPOINT_PROCESS_TITLE: {
130138
type: 'string',

src/test/unit_tests/jest_tests/test_nc_nsfs_account_cli.test.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,7 +1773,9 @@ describe('manage nsfs cli account flow', () => {
17731773
describe('cli account flow distinguished_name - permissions', function() {
17741774
const type = TYPES.ACCOUNT;
17751775
const config_root = path.join(tmp_fs_path, 'config_root_manage_dn');
1776+
const config_fs = new ConfigFS(config_root);
17761777
const new_buckets_path = path.join(tmp_fs_path, 'new_buckets_path_user_dn_test/');
1778+
17771779
const accounts = {
17781780
root: {
17791781
cli_options: {
@@ -1903,56 +1905,77 @@ describe('cli account flow distinguished_name - permissions', function() {
19031905
}, timeout);
19041906

19051907
it('cli account update - should fail - no permissions to new_buckets_path', async function() {
1906-
const no_permissions_new_buckets_path = `${tmp_fs_path}/new_buckets_path_no_perm_to_owner/`;
1908+
const no_permissions_new_buckets_path = `${tmp_fs_path}/new_buckets_path_no_perm_to_owner1/`;
19071909
await fs_utils.create_fresh_path(no_permissions_new_buckets_path);
19081910
await fs_utils.file_must_exist(no_permissions_new_buckets_path);
1909-
await set_path_permissions_and_owner(new_buckets_path, accounts.accessible_user.fs_options, 0o077);
1911+
await set_path_permissions_and_owner(no_permissions_new_buckets_path, accounts.accessible_user.fs_options, 0o000);
19101912
const action = ACTIONS.UPDATE;
19111913
const update_options = {
19121914
config_root,
1913-
name: accounts.root.cli_options.name,
1915+
...accounts.accessible_user.cli_options,
19141916
new_buckets_path: no_permissions_new_buckets_path,
19151917
};
19161918
const res = await exec_manage_cli(type, action, update_options);
19171919
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleAccountNewBucketsPath.code);
19181920
}, timeout);
19191921

1920-
it('cli account update - should fail - no write permissions of new_buckets_path', async function() {
1922+
it('cli account update - should fail - posix mode write permissions of new_buckets_path', async function() {
19211923
const no_permissions_new_buckets_path = `${tmp_fs_path}/new_buckets_path_no_r_perm_to_owner/`;
19221924
await fs_utils.create_fresh_path(no_permissions_new_buckets_path);
19231925
await fs_utils.file_must_exist(no_permissions_new_buckets_path);
1924-
await set_path_permissions_and_owner(new_buckets_path, accounts.accessible_user.fs_options, 0o477);
1926+
await set_path_permissions_and_owner(no_permissions_new_buckets_path, accounts.accessible_user.fs_options, 0o477);
19251927
const action = ACTIONS.UPDATE;
19261928
const update_options = {
19271929
config_root,
1928-
name: accounts.root.cli_options.name,
1930+
...accounts.accessible_user.cli_options,
19291931
new_buckets_path: no_permissions_new_buckets_path,
19301932
};
1933+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_POSIX_MODE_ACCESS_CHECK: false }));
19311934
const res = await exec_manage_cli(type, action, update_options);
1935+
await config_fs.delete_config_json_file();
19321936
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleAccountNewBucketsPath.code);
19331937
}, timeout);
19341938

19351939
it('cli account update - should fail - no read permissions of new_buckets_path', async function() {
19361940
const no_permissions_new_buckets_path = `${tmp_fs_path}/new_buckets_path_no_w_perm_to_owner/`;
19371941
await fs_utils.create_fresh_path(no_permissions_new_buckets_path);
19381942
await fs_utils.file_must_exist(no_permissions_new_buckets_path);
1939-
await set_path_permissions_and_owner(new_buckets_path, accounts.accessible_user.fs_options, 0o277);
1943+
await set_path_permissions_and_owner(no_permissions_new_buckets_path, accounts.accessible_user.fs_options, 0o000);
19401944
const action = ACTIONS.UPDATE;
19411945
const update_options = {
19421946
config_root,
1943-
name: accounts.root.cli_options.name,
1947+
...accounts.accessible_user.cli_options,
19441948
new_buckets_path: no_permissions_new_buckets_path,
19451949
};
19461950
const res = await exec_manage_cli(type, action, update_options);
19471951
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleAccountNewBucketsPath.code);
19481952
});
19491953

1954+
it('cli account update - should succeed - no read permissions of new_buckets_path - NC_DISABLE_ACCESS_CHECK: true', async function() {
1955+
const no_permissions_new_buckets_path = `${tmp_fs_path}/new_buckets_path_no_w_perm_to_owner/`;
1956+
await fs_utils.create_fresh_path(no_permissions_new_buckets_path);
1957+
await fs_utils.file_must_exist(no_permissions_new_buckets_path);
1958+
1959+
await set_path_permissions_and_owner(no_permissions_new_buckets_path, accounts.accessible_user.fs_options, 0o000);
1960+
const action = ACTIONS.UPDATE;
1961+
const update_options = {
1962+
config_root,
1963+
...accounts.accessible_user.cli_options,
1964+
new_buckets_path: no_permissions_new_buckets_path,
1965+
};
1966+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
1967+
const res = await exec_manage_cli(type, action, update_options);
1968+
await config_fs.delete_config_json_file();
1969+
assert_account(JSON.parse(res).response.reply, update_options, false);
1970+
});
1971+
19501972
it('cli account create - account cant access new_bucket_path - NC_DISABLE_ACCESS_CHECK = true', async function() {
19511973
let action = ACTIONS.ADD;
19521974
config.NC_DISABLE_ACCESS_CHECK = true;
19531975
set_nc_config_dir_in_config(config_root);
1954-
await fs.promises.writeFile(path.join(config_root, 'config.json'), JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
1976+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
19551977
const res = await exec_manage_cli(type, action, accounts.inaccessible_user.cli_options);
1978+
await config_fs.delete_config_json_file();
19561979
expect(JSON.parse(res).response.code).toEqual(ManageCLIResponse.AccountCreated.code);
19571980
assert_account(JSON.parse(res).response.reply, { ...accounts.inaccessible_user.cli_options }, false);
19581981
action = ACTIONS.DELETE;

src/test/unit_tests/jest_tests/test_nc_nsfs_bucket_cli.test.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,15 @@ describe('manage nsfs cli bucket flow', () => {
113113
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleStoragePath.code);
114114
});
115115

116-
it('should fail - cli create bucket - owner does not have write permission to path', async () => {
116+
it('should fail - cli create bucket - owner does not have posix write permission to path', async () => {
117117
const action = ACTIONS.ADD;
118118
const bucket_options = { config_root, ...bucket_defaults};
119119
await fs_utils.create_fresh_path(bucket_options.path);
120120
await fs_utils.file_must_exist(bucket_options.path);
121121
await set_path_permissions_and_owner(bucket_options.path, account_defaults, 0o477);
122+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_POSIX_MODE_ACCESS_CHECK: false }));
122123
const res = await exec_manage_cli(TYPES.BUCKET, action, bucket_options);
124+
await config_fs.delete_config_json_file();
123125
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleStoragePath.code);
124126
});
125127

@@ -150,9 +152,10 @@ describe('manage nsfs cli bucket flow', () => {
150152
await fs_utils.create_fresh_path(bucket_options.path);
151153
await fs_utils.file_must_exist(bucket_options.path);
152154
set_nc_config_dir_in_config(config_root);
153-
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
154155
await set_path_permissions_and_owner(bucket_options.path, account_defaults, 0o000);
156+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
155157
const res = await exec_manage_cli(TYPES.BUCKET, action, bucket_options);
158+
await config_fs.delete_config_json_file();
156159
expect(JSON.parse(res).response.code).toEqual(ManageCLIResponse.BucketCreated.code);
157160
});
158161

@@ -532,7 +535,9 @@ describe('manage nsfs cli bucket flow', () => {
532535
await fs_utils.create_fresh_path(bucket_defaults.path);
533536
await fs_utils.file_must_exist(bucket_defaults.path);
534537
await set_path_permissions_and_owner(bucket_defaults.path, account_defaults2, 0o477);
538+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_POSIX_MODE_ACCESS_CHECK: false }));
535539
const res = await exec_manage_cli(TYPES.BUCKET, action, bucket_options);
540+
await config_fs.delete_config_json_file();
536541
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleStoragePath.code);
537542
});
538543

@@ -546,6 +551,18 @@ describe('manage nsfs cli bucket flow', () => {
546551
expect(JSON.parse(res.stdout).error.code).toBe(ManageCLIError.InaccessibleStoragePath.code);
547552
});
548553

554+
it('cli update bucket owner - owner does not have read permission to path - NC_DISABLE_ACCESS_CHECK: true', async () => {
555+
const action = ACTIONS.UPDATE;
556+
const bucket_options = { config_root, name: bucket_defaults.name, owner: account_defaults2.name};
557+
await fs_utils.create_fresh_path(bucket_defaults.path);
558+
await fs_utils.file_must_exist(bucket_defaults.path);
559+
await set_path_permissions_and_owner(bucket_defaults.path, account_defaults2, 0o000);
560+
await config_fs.create_config_json_file(JSON.stringify({ NC_DISABLE_ACCESS_CHECK: true }));
561+
const res = await exec_manage_cli(TYPES.BUCKET, action, bucket_options);
562+
await config_fs.delete_config_json_file();
563+
expect(JSON.parse(res).response.code).toEqual(ManageCLIResponse.BucketUpdated.code);
564+
});
565+
549566
it('cli update bucket owner - account can access path', async () => {
550567
const action = ACTIONS.UPDATE;
551568
const bucket_options = { config_root, name: bucket_defaults.name, owner: account_defaults2.name};

0 commit comments

Comments
 (0)