Skip to content

Commit 20682f4

Browse files
MB-34413 Allow to change user and group's fields separately
Change-Id: I2674b04f5f1eb11adce29ddeabace95cfcabe6fb Reviewed-on: http://review.couchbase.org/111067 Reviewed-by: Carlos Gonzalez <carlos.gonzalez@couchbase.com> Tested-by: Build Bot <build@couchbase.com>
1 parent 2eed768 commit 20682f4

7 files changed

Lines changed: 144 additions & 105 deletions

File tree

cbmgr.py

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3168,7 +3168,7 @@ def __init__(self):
31683168
group.add_argument("--my-roles", dest="my_roles", action="store_true", default=False,
31693169
help="List my roles")
31703170
group.add_argument("--set", dest="set", action="store_true", default=False,
3171-
help="Create a new RBAC user")
3171+
help="Create or edit an RBAC user")
31723172
group.add_argument("--set-group", dest="set_group", action="store_true", default=False,
31733173
help="Create or edit a user group")
31743174
group.add_argument("--delete-group", dest="delete_group", action="store_true", default=False,
@@ -3177,8 +3177,6 @@ def __init__(self):
31773177
help="List all groups")
31783178
group.add_argument("--get-group", dest="get_group", action="store_true", default=False,
31793179
help="Get group")
3180-
group.add_argument("--edit-users-groups", dest="user_add", action="store_true", default=False,
3181-
help="Update the groups of user")
31823180
group.add_argument("--rbac-username", dest="rbac_user", metavar="<username>",
31833181
help="The RBAC username")
31843182
group.add_argument("--rbac-password", dest="rbac_pass", metavar="<password>",
@@ -3203,13 +3201,13 @@ def execute(self, opts):
32033201
check_versions(rest)
32043202

32053203
num_selectors = sum([opts.delete, opts.list, opts.my_roles, opts.set, opts.get, opts.get_group,
3206-
opts.list_group, opts.delete_group, opts.set_group, opts.user_add])
3204+
opts.list_group, opts.delete_group, opts.set_group])
32073205
if num_selectors == 0:
32083206
_exitIfErrors(["Must specify --delete, --list, --my_roles, --set, --get, --get-group, --set-group, " +
3209-
"--list-groups, --edit-users-groups or --delete-group"])
3207+
"--list-groups or --delete-group"])
32103208
elif num_selectors != 1:
32113209
_exitIfErrors(["Only one of the following can be specified:--delete, --list, --my_roles, --set, --get," +
3212-
" --get-group, --set-group, --list-groups, --edit-users-groups or --delete-group"])
3210+
" --get-group, --set-group, --list-groups or --delete-group"])
32133211

32143212
if opts.delete:
32153213
self._delete(rest, opts)
@@ -3225,8 +3223,6 @@ def execute(self, opts):
32253223
self._get_group(rest, opts)
32263224
elif opts.set_group:
32273225
self._set_group(rest, opts)
3228-
elif opts.user_add:
3229-
self._set_users_groups(rest, opts)
32303226
elif opts.list_group:
32313227
self._list_groups(rest)
32323228
elif opts.delete_group:
@@ -3248,27 +3244,13 @@ def _get_group(self, rest, opts):
32483244
_exitIfErrors(errors)
32493245
print(json.dumps(group, indent=2))
32503246

3251-
def _set_users_groups(self, rest, opts):
3252-
if opts.username is None:
3253-
_exitIfErrors(['--rbac-username is required with the --edit-users-groups option'])
3254-
if opts.groups is None:
3255-
_exitIfErrors(['--user-groups is required with the --edit-users-groups option'])
3256-
if opts.auth_domain is None:
3257-
_exitIfErrors(['--auth-domain is required with the --edit-users-groups option'])
3258-
3259-
_, errors = rest.add_user_to_group(opts.rbac_user, opts.groups, opts.auth_domain)
3260-
_exitIfErrors(errors)
3261-
_success(f"User '{opts.rbac_user}' group memberships were updated")
3262-
32633247
def _set_group(self, rest, opts):
32643248
if opts.group is None:
32653249
_exitIfErrors(['--group-name is required with --set-group'])
3266-
if opts.roles is None:
3267-
_exitIfErrors(['--roles is required with --set-group'])
32683250

32693251
_, errors = rest.set_user_group(opts.group, opts.roles, opts.description, opts.ldap_ref)
32703252
_exitIfErrors(errors)
3271-
_success(f"Group '{opts.group}' was created")
3253+
_success(f"Group '{opts.group}' set")
32723254

32733255
def _list_groups(self, rest):
32743256
groups, errors = rest.list_user_groups()
@@ -3347,29 +3329,23 @@ def _my_roles(self, rest, opts):
33473329
def _set(self, rest, opts):
33483330
if opts.rbac_user is None:
33493331
_exitIfErrors(["--rbac-username is required with the --set option"])
3350-
if opts.rbac_pass is None and opts.auth_domain == "local":
3351-
_exitIfErrors(["--rbac-password is required with the --set option"])
33523332
if opts.rbac_pass is not None and opts.auth_domain == "external":
33533333
_warning("--rbac-password cannot be used with the external auth domain")
33543334
opts.rbac_pass = None
3355-
if opts.roles is None and opts.groups is None:
3356-
_exitIfErrors(["--roles or --user-groups are required with the --set option"])
33573335
if opts.auth_domain is None:
33583336
_exitIfErrors(["--auth-domain is required with the --set option"])
33593337

3360-
_, errors = rest.set_rbac_user(opts.rbac_user, opts.rbac_pass, opts.rbac_name, opts.roles, opts.auth_domain)
3338+
_, errors = rest.set_rbac_user(opts.rbac_user, opts.rbac_pass, \
3339+
opts.rbac_name, opts.roles, \
3340+
opts.auth_domain, opts.groups)
33613341
_exitIfErrors(errors)
33623342

3363-
if opts.groups is not None:
3364-
groups = opts.groups.split(",")
3365-
_, errors = rest.add_user_to_group(opts.rbac_user, groups)
3366-
33673343
if opts.roles is not None and "query_external_access" in opts.roles:
33683344
_warning("Granting the query_external_access role permits execution of the N1QL " +
33693345
"function CURL() and may allow access to other network endpoints in the local " +
33703346
"network and the Internet.")
33713347

3372-
_success(f"User {opts.rbac_user} was created")
3348+
_success(f"User {opts.rbac_user} set")
33733349

33743350
@staticmethod
33753351
def get_man_page_name():

cluster_manager.py

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ def my_roles(self):
999999
url = f'{self.hostname}/whoami'
10001000
return self._get(url)
10011001

1002-
def set_rbac_user(self, username, password, name, roles, auth_domain):
1002+
def set_rbac_user(self, username, password, name, roles, auth_domain, groups):
10031003
if auth_domain is None:
10041004
return None, ["The authentication type is required"]
10051005

@@ -1008,27 +1008,36 @@ def set_rbac_user(self, username, password, name, roles, auth_domain):
10081008

10091009
url = f'{self.hostname}/settings/rbac/users/{auth_domain}/{username}'
10101010

1011+
defaults, errors = self._get(url)
1012+
if errors and errors[0] == '"Unknown user."':
1013+
defaults = {}
1014+
elif errors:
1015+
return None, errors
1016+
10111017
params = {}
10121018
if name is not None:
1013-
params["name"] = name
1019+
params['name'] = name
1020+
elif 'name' in defaults:
1021+
params['name'] = defaults['name']
10141022
if password is not None:
1015-
params["password"] = password
1023+
params['password'] = password
10161024
if roles is not None:
1017-
params["roles"] = roles
1018-
return self._put(url, params)
1025+
params['roles'] = roles;
1026+
elif 'roles' in defaults:
1027+
params['roles'] = self._format_user_roles(defaults['roles'])
1028+
if groups is not None:
1029+
params['groups'] = groups
1030+
elif 'groups' in defaults:
1031+
params['groups'] = ','.join(defaults['groups'])
10191032

1020-
def add_user_to_group(self, user, groups, domain):
1021-
if user is None:
1022-
return None, ['User is required']
1023-
if groups is None:
1024-
return None, ['A list of groups is required']
1025-
if domain is None:
1026-
return None, ['The user domain is required']
1033+
return self._put(url, params)
10271034

1028-
url = f'{self.hostname}/settings/rbac/users/{domain}/{user}'
1035+
def _format_user_roles(self, roles):
1036+
directly_assigned = filter(lambda r: any(o for o in r['origins'] if o['type'] == 'user'), roles)
1037+
return ",".join(self._format_role(r) for r in directly_assigned)
10291038

1030-
params = {'groups': groups}
1031-
return self._put(url, params)
1039+
def _format_role(self, role):
1040+
return f'{role["role"]}' + (f'[{role["bucket_name"]}]' if 'bucket_name' in role else '')
10321041

10331042
def get_user_group(self, group):
10341043
if group is None:
@@ -1047,15 +1056,28 @@ def delete_user_group(self, group):
10471056
def set_user_group(self, group, roles, description, ldap_ref):
10481057
if group is None:
10491058
return None, ['Group name is required']
1050-
if roles is None:
1051-
return None, ['roles are required']
10521059

10531060
url = f'{self.hostname}/settings/rbac/groups/{group}'
1054-
params = {'roles': roles}
1061+
1062+
defaults, errors = self._get(url)
1063+
if errors and errors[0] == '"Unknown group."':
1064+
defaults = {}
1065+
elif errors:
1066+
return None, errors
1067+
1068+
params = {}
1069+
if roles is not None:
1070+
params['roles'] = roles
1071+
elif 'roles' in defaults:
1072+
params['roles'] = ",".join(self._format_role(r) for r in defaults['roles'])
10551073
if description is not None:
10561074
params['description'] = description
1075+
elif 'description' in defaults:
1076+
params['description'] = defaults['description']
10571077
if ldap_ref is not None:
10581078
params['ldap_group_ref'] = ldap_ref
1079+
elif 'ldap_group_ref' in defaults:
1080+
params['ldap_group_ref'] = defaults['ldap_group_ref']
10591081

10601082
return self._put(url, params)
10611083

docs/generated/doc/couchbase-cli/couchbase-cli-user-manage.html

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8">
55
<meta http-equiv="X-UA-Compatible" content="IE=edge">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<meta name="generator" content="Asciidoctor 2.0.9">
7+
<meta name="generator" content="Asciidoctor 2.0.10">
88
<meta name="author" content="Couchbase">
99
<title>couchbase-cli-user-manage(1)</title>
1010
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
@@ -241,7 +241,7 @@
241241
pre.pygments .lineno{border-right:1px solid currentColor;opacity:.35;display:inline-block;margin-right:.75em}
242242
pre.pygments .lineno::before{content:"";margin-right:-.125em}
243243
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
244-
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
244+
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
245245
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
246246
.quoteblock blockquote{margin:0;padding:0;border:0}
247247
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
@@ -258,7 +258,8 @@
258258
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
259259
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
260260
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
261-
.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
261+
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
262+
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
262263
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
263264
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
264265
table.tableblock{max-width:100%;border-collapse:separate}
@@ -452,8 +453,8 @@ <h2 id="_synopsis">SYNOPSIS</h2>
452453
<pre class="content"><em>couchbase-cli user-manage</em> [--cluster &lt;url&gt;] [--username &lt;user&gt;]
453454
[--password &lt;password&gt;] [--delete] [--list] [--my-roles] [--set]
454455
[--set-group] [--delete-group] [--list-groups] [--get-group]
455-
[--edit-users-groups] [-- get] [--rbac-username &lt;username&gt;]
456-
[--rbac-password &lt;password&gt;] [--rbac-name &lt;name&gt;] [--roles &lt;roles_list&gt;]
456+
[-- get] [--rbac-username &lt;username&gt;] [--rbac-password &lt;password&gt;]
457+
[--rbac-name &lt;name&gt;] [--roles &lt;roles_list&gt;]
457458
[--auth-domain &lt;domain&gt;] [--user-groups &lt;group&gt;]
458459
[--group-description &lt;text&gt;] [--ldap-ref &lt;ref&gt;]</pre>
459460
</div>
@@ -536,10 +537,6 @@ <h2 id="_options">OPTIONS</h2>
536537
<dd>
537538
<p>Gets the details of a group.</p>
538539
</dd>
539-
<dt class="hdlist1">--edit-users-groups</dt>
540-
<dd>
541-
<p>Updates the groups the given RBAC user is part of.</p>
542-
</dd>
543540
<dt class="hdlist1">--rbac-username &lt;username&gt;</dt>
544541
<dd>
545542
<p>Specifies the username of the RBAC user to modify. This option is used when
@@ -575,7 +572,7 @@ <h2 id="_options">OPTIONS</h2>
575572
<dt class="hdlist1">--user-groups &lt;groups&gt;</dt>
576573
<dd>
577574
<p>Specifies the groups the user should be added to. This is used when creating
578-
a user (--set) or when updating the users group (--edit-user-groups), and
575+
a user (--set) or when updating the users group, and
579576
should be specified as a comma separated list.</p>
580577
</dd>
581578
<dt class="hdlist1">--group-name &lt;group&gt;</dt>

docs/generated/man/man1/couchbase-cli-user-manage.1

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
'\" t
22
.\" Title: couchbase-cli-user-manage
33
.\" Author: Couchbase
4-
.\" Generator: Asciidoctor 2.0.9
5-
.\" Date: 2019-06-19
4+
.\" Generator: Asciidoctor 2.0.10
5+
.\" Date: 2019-07-03
66
.\" Manual: Couchbase CLI Manual
77
.\" Source: Couchbase CLI 1.0.0
88
.\" Language: English
99
.\"
10-
.TH "COUCHBASE\-CLI\-USER\-MANAGE" "1" "2019-06-24" "Couchbase CLI 1.0.0" "Couchbase CLI Manual"
10+
.TH "COUCHBASE\-CLI\-USER\-MANAGE" "1" "2019-07-03" "Couchbase CLI 1.0.0" "Couchbase CLI Manual"
1111
.ie \n(.g .ds Aq \(aq
1212
.el .ds Aq '
1313
.ss \n[.ss] 0
@@ -36,8 +36,8 @@ couchbase\-cli\-user\-manage \- Manage RBAC users
3636
\fIcouchbase\-cli user\-manage\fP [\-\-cluster <url>] [\-\-username <user>]
3737
[\-\-password <password>] [\-\-delete] [\-\-list] [\-\-my\-roles] [\-\-set]
3838
[\-\-set\-group] [\-\-delete\-group] [\-\-list\-groups] [\-\-get\-group]
39-
[\-\-edit\-users\-groups] [\-\- get] [\-\-rbac\-username <username>]
40-
[\-\-rbac\-password <password>] [\-\-rbac\-name <name>] [\-\-roles <roles_list>]
39+
[\-\- get] [\-\-rbac\-username <username>] [\-\-rbac\-password <password>]
40+
[\-\-rbac\-name <name>] [\-\-roles <roles_list>]
4141
[\-\-auth\-domain <domain>] [\-\-user\-groups <group>]
4242
[\-\-group\-description <text>] [\-\-ldap\-ref <ref>]
4343
.fi
@@ -120,11 +120,6 @@ List all groups.
120120
Gets the details of a group.
121121
.RE
122122
.sp
123-
\-\-edit\-users\-groups
124-
.RS 4
125-
Updates the groups the given RBAC user is part of.
126-
.RE
127-
.sp
128123
\-\-rbac\-username <username>
129124
.RS 4
130125
Specifies the username of the RBAC user to modify. This option is used when
@@ -165,7 +160,7 @@ managed by an external source suchas LDAP.
165160
\-\-user\-groups <groups>
166161
.RS 4
167162
Specifies the groups the user should be added to. This is used when creating
168-
a user (\-\-set) or when updating the users group (\-\-edit\-user\-groups), and
163+
a user (\-\-set) or when updating the users group, and
169164
should be specified as a comma separated list.
170165
.RE
171166
.sp
@@ -565,4 +560,4 @@ password are not cached in their command line history.
565560
Part of the \fBcouchbase\-cli\fP(1) suite
566561
.SH "AUTHOR"
567562
.sp
568-
Couchbase
563+
Couchbase

docs/modules/cli/pages/cbcli/couchbase-cli-user-manage.adoc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Manage RBAC users
1414
_couchbase-cli user-manage_ [--cluster <url>] [--username <user>]
1515
[--password <password>] [--delete] [--list] [--my-roles] [--set]
1616
[--set-group] [--delete-group] [--list-groups] [--get-group]
17-
[--edit-users-groups] [-- get] [--rbac-username <username>]
18-
[--rbac-password <password>] [--rbac-name <name>] [--roles <roles_list>]
17+
[-- get] [--rbac-username <username>] [--rbac-password <password>]
18+
[--rbac-name <name>] [--roles <roles_list>]
1919
[--auth-domain <domain>] [--user-groups <group>]
2020
[--group-description <text>] [--ldap-ref <ref>]
2121

@@ -59,9 +59,6 @@ include::{partialsdir}/cbcli/part-common-options.adoc[]
5959
--get-group::
6060
Gets the details of a group.
6161

62-
--edit-users-groups::
63-
Updates the groups the given RBAC user is part of.
64-
6562
--rbac-username <username>::
6663
Specifies the username of the RBAC user to modify. This option is used when
6764
deleting, creating, or updating an RBAC user profile.
@@ -91,7 +88,7 @@ include::{partialsdir}/cbcli/part-common-options.adoc[]
9188

9289
--user-groups <groups>::
9390
Specifies the groups the user should be added to. This is used when creating
94-
a user (--set) or when updating the users group (--edit-user-groups), and
91+
a user (--set) or when updating the users group, and
9592
should be specified as a comma separated list.
9693

9794
--group-name <group>::

0 commit comments

Comments
 (0)