Skip to content

Commit 0f3d341

Browse files
authored
Merge pull request #8552 from nadavMiz/suplemental-groups
NSFS | NC | add option to set account supplemental groups
2 parents 65b72cb + fff7900 commit 0f3d341

22 files changed

+479
-42
lines changed

docs/NooBaaNonContainerized/AccountsAndBuckets.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ See all available account properties - [NC Account Schema](../../src/server/syst
2929
#### Important properties
3030
- `encrypted_secret_key` - Account's secrets will be kept encrypted in the account's configuration file.
3131

32-
- `uid/gid/user` - An account's access key is mapped to a file system uid/gid (or user). Before performing any file system operation, NooBaa switches to the account's UID/GID, ensuring that accounts access to buckets and objects is enforced by the file system.
32+
- `uid/gid/user` - An account's access key is mapped to a file system uid/gid (or user). Before performing any file system operation, NooBaa switches to the account's UID/GID, ensuring that accounts access to buckets and objects is enforced by the file system.
33+
34+
- `supplemental_groups` - In addition to the account main GID, an account can have supplementary group IDs that are used to determine permissions for accessing files. These GIDs are validated against a files group (GID) permissions.
35+
Note: depending on the file system there may be 'sticky bit' enabled somewhere on the files path. 'sticky bit' is a user ownership access right flag that prevents other users than the file owner and root from deleting or moving files.
36+
In that case some actions will still get access denied regardless of group permissions enabled. sticky bit is denoted by `t` at the end of the permissions list (example: `drwxrwxrwt`). see https://en.wikipedia.org/wiki/Sticky_bit
3337

3438
- `new_buckets_path` - When an account creates a bucket using the S3 protocol, NooBaa will create the underlying file system directory. This directory will be created under new_buckets_path. Note that the account must have read and write access to its `new_buckets_path`. Must be an absolute path.
3539

docs/NooBaaNonContainerized/NooBaaCLI.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ noobaa-cli account add --name <account_name> --uid <uid> --gid <gid> [--user]
8484
- Type: String
8585
- Description: Specifies the File system user representing the account. (user can be replaced by --uid and --gid option)
8686

87+
- `supplemental_groups`
88+
- Type: String
89+
- Description: Specifies additional FS groups (GID) a user can be a part of. Allows access to directories/files having one or more of the provided groups. A String of GIDs separated by commas.
90+
8791
- `new_buckets_path`
8892
- Type: String
8993
- Description: Specifies a file system directory to be used for creating underlying directories that represent buckets created by an account using the S3 API.
@@ -152,6 +156,10 @@ noobaa-cli account update --name <account_name> [--new_name][--uid][--gid][--use
152156
- Type: Number
153157
- Description: Specifies the File system user representing the account. (user can be replaced by --uid and --gid option)
154158

159+
- `supplemental_groups`
160+
- Type: String
161+
- Description: Specifies additional FS groups (GID) a user can be a part of. Allows access to directories/files having one or more of the provided groups. A String of GIDs separated by commas.
162+
155163
- `new_buckets_path`
156164
- Type: String
157165
- Description: Specifies a file system directory to be used for creating underlying directories that represent buckets created by an account using the S3 API.

docs/NooBaaNonContainerized/S3Ops.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ The following lists describe the bucket and object operations available in NooBa
5252
- Bucket policies are an access policy option available to grant permission to buckets and objects (see [bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html) in AWS documentation). You can use bucket policies to add or deny permissions for the objects in a bucket. Bucket policies can allow or deny requests based on the elements in the policy.
5353
- Bucket policies use JSON-based policy language (for more information see [basic elements in bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-policy-language-overview.html) in AWS documentation)
5454
- Bucket policy can be added to a bucket using the S3 API or the noobaa-cli.
55-
- Bucket policy is an additional layer of permissions to the FS permissions (UID and GID), which means that if two accounts do not have the same permissions (UID, GID) just setting bucket policy on the bucket is not enough.
55+
- Bucket policy is an additional layer of permissions to the FS permissions (UID, GID, supplemental GIDs), which means that if two accounts do not have the same permissions (UID, GID, supplemental GIDs) just setting bucket policy on the bucket is not enough.
5656

5757
#### Bucket Policy in NooBaa CLI
5858
1. Adding a bucket policy:

src/api/account_api.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,10 @@ module.exports = {
312312
uid: { type: 'number' },
313313
gid: { type: 'number' },
314314
new_buckets_path: { type: 'string' },
315-
nsfs_only: { type: 'boolean' }
315+
nsfs_only: { type: 'boolean' },
316+
supplemental_groups: {
317+
$ref: 'common_api#/definitions/supplemental_groups'
318+
},
316319
}
317320
},
318321
},

src/api/common_api.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,13 @@ module.exports = {
13461346
}
13471347
}
13481348
},
1349+
supplemental_groups: {
1350+
type: 'array',
1351+
items: {
1352+
type: 'integer',
1353+
'minimum': 0
1354+
}
1355+
},
13491356
nsfs_account_config: {
13501357
oneOf: [{
13511358
type: 'object',
@@ -1354,7 +1361,10 @@ module.exports = {
13541361
uid: { type: 'number' },
13551362
gid: { type: 'number' },
13561363
new_buckets_path: { type: 'string' },
1357-
nsfs_only: { type: 'boolean' }
1364+
nsfs_only: { type: 'boolean' },
1365+
supplemental_groups: {
1366+
$ref: '#/definitions/supplemental_groups'
1367+
},
13581368
}
13591369
}, {
13601370
type: 'object',

src/cmd/manage_nsfs.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const { print_usage } = require('../manage_nsfs/manage_nsfs_help_utils');
2424
const { TYPES, ACTIONS, LIST_ACCOUNT_FILTERS, LIST_BUCKET_FILTERS, GLACIER_ACTIONS } = require('../manage_nsfs/manage_nsfs_constants');
2525
const { throw_cli_error, get_bucket_owner_account_by_name,
2626
write_stdout_response, get_boolean_or_string_value, has_access_keys, set_debug_level,
27-
is_name_update, is_access_key_update } = require('../manage_nsfs/manage_nsfs_cli_utils');
27+
is_name_update, is_access_key_update, parse_comma_delimited_string } = require('../manage_nsfs/manage_nsfs_cli_utils');
2828
const manage_nsfs_validations = require('../manage_nsfs/manage_nsfs_validations');
2929
const nc_mkm = require('../manage_nsfs/nc_master_key_manager').get_instance();
3030
const notifications_util = require('../util/notifications_util');
@@ -359,6 +359,11 @@ async function fetch_account_data(action, user_input) {
359359
data.access_keys[0].secret_key = data.access_keys[0].secret_key === undefined ? undefined :
360360
new SensitiveString(String(data.access_keys[0].secret_key));
361361
}
362+
//since supplemental_groups is an array, new list will merge with the old one instead of replacing it in fetch_existing_account_data
363+
//so we need to replace this value after merging the data
364+
data.nsfs_account_config.supplemental_groups = user_input.supplemental_groups === undefined ?
365+
data.nsfs_account_config.supplemental_groups : parse_comma_delimited_string(user_input.supplemental_groups);
366+
362367
if (data.new_access_key) data.new_access_key = new SensitiveString(data.new_access_key);
363368
// fs_backend deletion specified with empty string '' (but it is not part of the schema)
364369
data.nsfs_account_config.fs_backend = data.nsfs_account_config.fs_backend || undefined;

src/manage_nsfs/manage_nsfs_cli_errors.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ ManageCLIError.InvalidGlacierOperation = Object.freeze({
346346
message: 'only "migrate", "restore" and "expiry" subcommands are supported',
347347
http_code: 400,
348348
});
349+
ManageCLIError.InvalidSupplementalGroupsList = Object.freeze({
350+
code: 'InvalidSupplementalGroupsList',
351+
message: 'supplemental groups must be a list of group ids (group id is zero or a positive integer)',
352+
http_code: 400,
353+
});
349354

350355

351356
////////////////////////

src/manage_nsfs/manage_nsfs_cli_utils.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,25 @@ function get_boolean_or_string_value(value) {
9191
}
9292

9393
/**
94-
* get_options_from_file will read a JSON file that include key-value of the options
94+
* This function parse a comma delimited string of numbers ('0,212,111') to an array of numbers.
95+
* This function assumes string format was validated before calling the function, wrong string format can
96+
* lead to unexpected output (usually array of NaN)
97+
* 1. if the value is a number return array with this number (3 => [3])
98+
* 2. if the value is a string return an array of numbers ('0,212,111' => [0,212,111])
99+
* 3. for all other types (including object and undefined) return the value itself
100+
*/
101+
function parse_comma_delimited_string(value) {
102+
if (typeof value === 'number') {
103+
return [value];
104+
}
105+
if (typeof value === 'string') {
106+
return value.split(',').map(val => Number(val));
107+
}
108+
return value;
109+
}
110+
111+
/**_
112+
* get_options_fromfile will read a JSON file that include key-value of the options
95113
* (instead of flags) and return its content
96114
* @param {string} file_path
97115
*/
@@ -156,6 +174,7 @@ function is_access_key_update(data) {
156174
exports.throw_cli_error = throw_cli_error;
157175
exports.write_stdout_response = write_stdout_response;
158176
exports.get_boolean_or_string_value = get_boolean_or_string_value;
177+
exports.parse_comma_delimited_string = parse_comma_delimited_string;
159178
exports.get_bucket_owner_account_by_name = get_bucket_owner_account_by_name;
160179
exports.get_bucket_owner_account_by_id = get_bucket_owner_account_by_id;
161180
exports.get_options_from_file = get_options_from_file;

src/manage_nsfs/manage_nsfs_constants.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,16 @@ const FROM_FILE = 'from_file';
4444
const ANONYMOUS = 'anonymous';
4545

4646
const VALID_OPTIONS_ACCOUNT = {
47-
'add': new Set(['name', 'uid', 'gid', 'new_buckets_path', 'user', 'access_key', 'secret_key', 'fs_backend', 'allow_bucket_creation', 'force_md5_etag', 'iam_operate_on_root_account', FROM_FILE, ...CLI_MUTUAL_OPTIONS]),
48-
'update': new Set(['name', 'uid', 'gid', 'new_buckets_path', 'user', 'access_key', 'secret_key', 'fs_backend', 'allow_bucket_creation', 'force_md5_etag', 'iam_operate_on_root_account', 'new_name', 'regenerate', ...CLI_MUTUAL_OPTIONS]),
47+
'add': new Set(['name', 'uid', 'gid', 'supplemental_groups', 'new_buckets_path', 'user', 'access_key', 'secret_key', 'fs_backend', 'allow_bucket_creation', 'force_md5_etag', 'iam_operate_on_root_account', FROM_FILE, ...CLI_MUTUAL_OPTIONS]),
48+
'update': new Set(['name', 'uid', 'gid', 'supplemental_groups', 'new_buckets_path', 'user', 'access_key', 'secret_key', 'fs_backend', 'allow_bucket_creation', 'force_md5_etag', 'iam_operate_on_root_account', 'new_name', 'regenerate', ...CLI_MUTUAL_OPTIONS]),
4949
'delete': new Set(['name', ...CLI_MUTUAL_OPTIONS]),
5050
'list': new Set(['wide', 'show_secrets', 'gid', 'uid', 'user', 'name', 'access_key', ...CLI_MUTUAL_OPTIONS]),
5151
'status': new Set(['name', 'access_key', 'show_secrets', ...CLI_MUTUAL_OPTIONS]),
5252
};
5353

5454
const VALID_OPTIONS_ANONYMOUS_ACCOUNT = {
55-
'add': new Set(['uid', 'gid', 'user', 'anonymous', ...CLI_MUTUAL_OPTIONS]),
56-
'update': new Set(['uid', 'gid', 'user', 'anonymous', ...CLI_MUTUAL_OPTIONS]),
55+
'add': new Set(['uid', 'gid', 'user', 'supplemental_groups', 'anonymous', ...CLI_MUTUAL_OPTIONS]),
56+
'update': new Set(['uid', 'gid', 'user', 'supplemental_groups', 'anonymous', ...CLI_MUTUAL_OPTIONS]),
5757
'delete': new Set(['anonymous', ...CLI_MUTUAL_OPTIONS]),
5858
'status': new Set(['anonymous', ...CLI_MUTUAL_OPTIONS]),
5959
};
@@ -105,6 +105,7 @@ const OPTION_TYPE = {
105105
owner: 'string',
106106
uid: 'number',
107107
gid: 'number',
108+
supplemental_groups: 'string',
108109
new_buckets_path: 'string',
109110
user: 'string',
110111
access_key: 'string',

src/manage_nsfs/manage_nsfs_help_utils.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Help:
88
99
"NSFS" (Namespace FileSystem) is a NooBaa system that runs a local S3 endpoint on top of a filesystem.
1010
Each subdirectory of the root filesystem represents an S3 bucket.
11-
"noobaa-cli" will provide a command line interface (CLI) to create new accounts and map existing directories
11+
"noobaa-cli" will provide a command line interface (CLI) to create new accounts and map existing directories
1212
to NooBaa as buckets. For more information refer to the NooBaa docs.
1313
1414
`;
@@ -111,10 +111,10 @@ Usage:
111111
account add [flags]
112112
113113
Flags:
114-
115114
--name <string> Set the name for the account
116115
--uid <number> Set the User Identifier (UID) (UID and GID can be replaced by --user option)
117116
--gid <number> Set the Group Identifier (GID) (UID and GID can be replaced by --user option)
117+
--supplemental_groups <string> (optional) Set the supplemental group list (List of GIDs) separated by commas (,) example: '212,211,202'
118118
--new_buckets_path <string> (optional) Set the filesystem's root path where each subdirectory is a bucket
119119
--user <string> (optional) Set the OS user name (instead of UID and GID)
120120
--access_key <string> (optional) Set the access key for the account (default is generated)
@@ -124,7 +124,6 @@ Flags:
124124
--force_md5_etag <true | false> (optional) Set the account to force md5 etag calculation. (unset with '') (will override default config.NSFS_NC_STORAGE_BACKEND)
125125
--iam_operate_on_root_account <true | false> (optional) Set the account to create root accounts instead of IAM users in IAM API requests.
126126
--from_file <string> (optional) Use details from the JSON file, there is no need to mention all the properties individually in the CLI
127-
128127
`;
129128

130129
const ACCOUNT_FLAGS_UPDATE = `
@@ -142,6 +141,7 @@ Flags:
142141
--new_name <string> (optional) Update the account name
143142
--uid <number> (optional) Update the User Identifier (UID)
144143
--gid <number> (optional) Update the Group Identifier (GID)
144+
--supplemental_groups <number[]> (optional) Update the list of supplemental groups (List of GID) seperated by comma(,) example: 211,202,23 - it will override existing list
145145
--new_buckets_path <string> (optional) Update the filesystem's root path where each subdirectory is a bucket
146146
--user <string> (optional) Update the OS user name (instead of uid and gid)
147147
--regenerate (optional) Update automatically generated access key and secret key
@@ -151,7 +151,6 @@ Flags:
151151
--allow_bucket_creation <true | false> (optional) Update the account to explicitly allow or block bucket creation
152152
--force_md5_etag <true | false> (optional) Update the account to force md5 etag calculation (unset with '') (will override default config.NSFS_NC_STORAGE_BACKEND)
153153
--iam_operate_on_root_account <true | false> (optional) Update the account to create root accounts instead of IAM users in IAM API requests.
154-
155154
`;
156155

157156
const ACCOUNT_FLAGS_DELETE = `
@@ -334,7 +333,7 @@ List of actions supported:
334333
health
335334
gather-logs
336335
metrics
337-
336+
338337
`;
339338

340339
const DIAGNOSE_HEALTH_OPTIONS = `
@@ -400,7 +399,7 @@ List of actions supported:
400399
start
401400
status
402401
history
403-
402+
404403
`;
405404

406405
const UPGRADE_START_OPTIONS = `
@@ -413,13 +412,13 @@ Help:
413412
'upgrade start' should be executed on one node, the config directory changes will be available for all the nodes of the cluster.
414413
415414
Usage:
416-
415+
417416
noobaa-cli upgrade start [flags]
418417
419418
Flags:
420419
421420
--expected_version <string> The expected target version of the upgrade
422-
--expected_hosts <string> The expected hosts running NooBaa NC, a string of hosts separated by ,
421+
--expected_hosts <string> The expected hosts running NooBaa NC, a string of hosts separated by ,
423422
--skip_verification <boolean> (optional) skip verification of the hosts package version
424423
WARNING: can cause corrupted config dir files created by hosts running old code
425424
--custom_upgrade_scripts_dir <string> (optional) custom upgrade scripts dir, use for running custom config dir upgrade scripts
@@ -453,7 +452,7 @@ Usage:
453452
`;
454453

455454

456-
/**
455+
/**
457456
* print_usage would print the help according to the arguments that were passed
458457
* @param {string} type
459458
* @param {string} action
@@ -489,7 +488,7 @@ function print_usage(type, action) {
489488
process.exit(0);
490489
}
491490

492-
/**
491+
/**
493492
* print_help_account would print the help options for account
494493
* @param {string} action
495494
*/
@@ -516,7 +515,7 @@ function print_help_account(action) {
516515
process.exit(0);
517516
}
518517

519-
/**
518+
/**
520519
* print_help_bucket would print the help options for bucket
521520
* @param {string} action
522521
*/

0 commit comments

Comments
 (0)