You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ra...@apache.org on 2017/07/28 13:59:42 UTC
[incubator-openwhisk] branch master updated: Add a database flag to
completely block a given subject. (#2530)
This is an automated email from the ASF dual-hosted git repository.
rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new 470130b Add a database flag to completely block a given subject. (#2530)
470130b is described below
commit 470130b7b5db50e2349dc56cb7e9abb0f9cdb0b1
Author: Markus Thömmes <ma...@me.com>
AuthorDate: Fri Jul 28 15:59:40 2017 +0200
Add a database flag to completely block a given subject. (#2530)
There was no preservative way of blocking a user from the system temporarily before. This adds the functionality to provide a flag in the user's subject entry to block its keys from further usage.
---
ansible/files/auth_index.json | 2 +-
.../scala/whisk/core/admin/WskAdminTests.scala | 62 ++++++++++++++++++++++
tools/admin/wskadmin | 60 ++++++++++++++++++---
3 files changed, 115 insertions(+), 9 deletions(-)
diff --git a/ansible/files/auth_index.json b/ansible/files/auth_index.json
index c9950b1..b1c4711 100644
--- a/ansible/files/auth_index.json
+++ b/ansible/files/auth_index.json
@@ -2,7 +2,7 @@
"_id":"_design/subjects",
"views": {
"identities": {
- "map": "function (doc) {\n if(doc.uuid && doc.key) {\n var v = {namespace: doc.subject, uuid: doc.uuid, key: doc.key};\n emit([doc.subject], v);\n emit([doc.uuid, doc.key], v);\n }\n if(doc.namespaces) {\n doc.namespaces.forEach(function(namespace) {\n var v = {namespace: namespace.name, uuid: namespace.uuid, key: namespace.key};\n emit([namespace.name], v);\n emit([namespace.uuid, namespace.key], v);\n });\n }\n}"
+ "map": "function (doc) {\n if(doc.uuid && doc.key && !doc.blocked) {\n var v = {namespace: doc.subject, uuid: doc.uuid, key: doc.key};\n emit([doc.subject], v);\n emit([doc.uuid, doc.key], v);\n }\n if(doc.namespaces && !doc.blocked) {\n doc.namespaces.forEach(function(namespace) {\n var v = {namespace: namespace.name, uuid: namespace.uuid, key: namespace.key};\n emit([namespace.name], v);\n emit([namespace.uuid, namespace.key], v);\n });\n }\n}"
}
},
"language":"javascript",
diff --git a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
index ec4cf59..0d31758 100644
--- a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
+++ b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
@@ -30,6 +30,7 @@ import common.WskAdmin
import common.WskProps
import whisk.core.entity.AuthKey
import whisk.core.entity.Subject
+import common.TestUtils
@RunWith(classOf[JUnitRunner])
class WskAdminTests
@@ -91,4 +92,65 @@ class WskAdminTests
val ns = wsk.namespace.whois()
wskadmin.cli(Seq("user", "get", ns)).stdout.trim should be(wskprops.authKey)
}
+
+ it should "block and unblock a user respectively" in {
+ val wskadmin = new RunWskAdminCmd {}
+ val auth = AuthKey()
+ val subject1 = Subject().asString
+ val subject2 = Subject().asString
+ val commonNamespace = "testspace"
+ try {
+ wskadmin.cli(Seq("user", "create", subject1, "-ns", commonNamespace, "-u", auth.compact))
+ wskadmin.cli(Seq("user", "create", subject2, "-ns", commonNamespace))
+
+ whisk.utils.retry({
+ // reverse lookup by namespace
+ val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
+ out should include(auth.compact)
+ out.lines should have size 2
+ }, 10, Some(1.second))
+
+ // block the user
+ wskadmin.cli(Seq("user", "block", subject1))
+
+ // wait until the user can no longer be found
+ whisk.utils.retry({
+ wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim.lines should have size 1
+ }, 10, Some(1.second))
+
+ // unblock the user
+ wskadmin.cli(Seq("user", "unblock", subject1))
+
+ // wait until the user can be found again
+ whisk.utils.retry({
+ val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
+ out should include(auth.compact)
+ out.lines should have size 2
+ }, 10, Some(1.second))
+ } finally {
+ wskadmin.cli(Seq("user", "delete", subject1)).stdout should include("Subject deleted")
+ wskadmin.cli(Seq("user", "delete", subject2)).stdout should include("Subject deleted")
+ }
+ }
+
+ it should "not allow edits on a blocked subject" in {
+ val wskadmin = new RunWskAdminCmd {}
+ val subject = Subject().asString
+ try {
+ // initially create the subject
+ wskadmin.cli(Seq("user", "create", subject))
+ // editing works
+ wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace1"))
+ // block it
+ wskadmin.cli(Seq("user", "block", subject))
+ // Try to add a namespace, doesn't work
+ wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"), expectedExitCode = TestUtils.ERROR_EXIT)
+ // Unblock the user
+ wskadmin.cli(Seq("user", "unblock", subject))
+ // Adding a namespace works
+ wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"))
+ } finally {
+ wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
+ }
+ }
}
diff --git a/tools/admin/wskadmin b/tools/admin/wskadmin
index 0e98c43..c149f04 100755
--- a/tools/admin/wskadmin
+++ b/tools/admin/wskadmin
@@ -105,6 +105,12 @@ def parseArgs():
subcmd = subparser.add_parser('whois', help='identify user from an authorization key')
subcmd.add_argument('authkey', help='the credentials to look up')
+ subcmd = subparser.add_parser('block', help='block a user')
+ subcmd.add_argument('subject', help='the user to block')
+
+ subcmd = subparser.add_parser('unblock', help='unblock a user')
+ subcmd.add_argument('subject', help='the user to unblock')
+
subcmd = subparser.add_parser('list', help='list authorization keys associated with a namespace')
subcmd.add_argument('namespace', help='the namespace to lookup')
subcmd.add_argument('-p', '--pick', metavar='N', help='show no more than N identities', type=int, default=1)
@@ -141,6 +147,10 @@ def userCmd(args, props):
return whoisUserCmd(args, props)
elif args.subcmd == 'list':
return listUserCmd(args, props)
+ elif args.subcmd == 'block':
+ return blockUserCmd(args, props)
+ elif args.subcmd == 'unblock':
+ return unblockUserCmd(args, props)
else:
print('unknown command')
return 2
@@ -205,15 +215,19 @@ def createUserCmd(args, props):
]
}
else:
- namespaces = filter(lambda ns: ns['name'] == desiredNamespace, doc['namespaces'])
- if len(namespaces) == 0:
- doc['namespaces'].append({
- 'name': desiredNamespace,
- 'uuid': uid,
- 'key': key
- })
+ if not doc.get('blocked'):
+ namespaces = filter(lambda ns: ns['name'] == desiredNamespace, doc['namespaces'])
+ if len(namespaces) == 0:
+ doc['namespaces'].append({
+ 'name': desiredNamespace,
+ 'uuid': uid,
+ 'key': key
+ })
+ else:
+ print('Namespace already exists')
+ return 1
else:
- print('Namespace already exists')
+ print('The subject you want to edit is blocked')
return 1
res = insertIntoDatabase(props, doc, args.verbose)
@@ -415,6 +429,36 @@ def whoisUserCmd(args, props):
print('Failed to get subject (%s)' % res.read().strip())
return 1
+def blockUserCmd(args, props):
+ (doc, res) = getSubjectFromDb(args, props)
+
+ if doc is not None:
+ doc['blocked'] = True
+ insertRes = insertIntoDatabase(props, doc, args.verbose)
+ if insertRes.status in [201, 202]:
+ print('"%s" blocked successfully' % args.subject)
+ else:
+ print('Failed to block subject (%s)' % res.read().strip())
+ return 1
+ else:
+ print('Failed to get subject (%s)' % res.read().strip())
+ return 1
+
+def unblockUserCmd(args, props):
+ (doc, res) = getSubjectFromDb(args, props)
+
+ if doc is not None:
+ doc['blocked'] = False
+ insertRes = insertIntoDatabase(props, doc, args.verbose)
+ if insertRes.status in [201, 202]:
+ print('"%s" unblocked successfully' % args.subject)
+ else:
+ print('Failed to unblock subject (%s)' % res.read().strip())
+ return 1
+ else:
+ print('Failed to get subject (%s)' % res.read().strip())
+ return 1
+
def getDbCmd(args, props):
protocol = props[DB_PROTOCOL]
host = props[DB_HOST]
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].