You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ch...@apache.org on 2018/09/14 09:27:21 UTC

[incubator-openwhisk] branch master updated: Allow updating auth key for user with wskadmin-next (#4005)

This is an automated email from the ASF dual-hosted git repository.

chetanm 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 2fca6a7  Allow updating auth key for user with wskadmin-next (#4005)
2fca6a7 is described below

commit 2fca6a7ea4580c005588008395f620d046477147
Author: Duy Nguyen <du...@gmail.com>
AuthorDate: Fri Sep 14 11:27:15 2018 +0200

    Allow updating auth key for user with wskadmin-next (#4005)
    
    Enable support for two new flags
    
        --revoke, abbreviated -r: regenerate a new key for the user / namespace, UUID remains the same
        --force, abbreviated -f:
            with --auth uuid:key: the new auth value is updated for the user
            without --auth: an auth of new UUID and key is randomly generated
---
 .../whisk/core/database/UserCommandTests.scala     | 39 ++++++++++++++++++++++
 tools/admin/README-NEXT.md                         |  8 +++++
 .../scala/whisk/core/database/UserCommand.scala    | 21 +++++++++---
 3 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/tests/src/test/scala/whisk/core/database/UserCommandTests.scala b/tests/src/test/scala/whisk/core/database/UserCommandTests.scala
index 69cbb07..ee9c7e8 100644
--- a/tests/src/test/scala/whisk/core/database/UserCommandTests.scala
+++ b/tests/src/test/scala/whisk/core/database/UserCommandTests.scala
@@ -68,6 +68,35 @@ class UserCommandTests extends FlatSpec with WhiskAdminCliTestBase {
     resultOk("user", "get", subject) shouldBe generatedKey
   }
 
+  it should "force update an existing user" in {
+    val subject = newSubject()
+    val oldKey = resultOk("user", "create", "--force", subject)
+    resultOk("user", "get", subject) shouldBe oldKey
+
+    // Force update with provided auth uuid:key
+    val key = BasicAuthenticationAuthKey()
+    val newKey = resultOk("user", "create", "--auth", key.compact, "--force", subject)
+    resultOk("user", "get", subject) shouldBe newKey
+    newKey shouldBe key.compact
+
+    // Force update without auth, uuid:key is randomly generated
+    val generatedKey = resultOk("user", "create", "--force", subject)
+    generatedKey should not be newKey
+    generatedKey should not be oldKey
+  }
+
+  it should "create a user or update an existing user with revoke flag" in {
+    val subject = newSubject()
+    val oldKey = resultOk("user", "create", "--revoke", subject)
+    resultOk("user", "get", subject) shouldBe oldKey
+    val newKey = resultOk("user", "create", "--revoke", subject)
+    resultOk("user", "get", subject) shouldBe newKey
+    val oldAuthKey = BasicAuthenticationAuthKey(oldKey)
+    val newAuthKey = BasicAuthenticationAuthKey(newKey)
+    newAuthKey.uuid shouldBe oldAuthKey.uuid
+    newAuthKey.key should not be oldAuthKey.key
+  }
+
   it should "add namespace to existing user" in {
     val subject = newSubject()
     val key = BasicAuthenticationAuthKey()
@@ -82,10 +111,20 @@ class UserCommandTests extends FlatSpec with WhiskAdminCliTestBase {
     //Adding same namespace should fail
     resultNotOk("user", "create", "--auth", key2.compact, "--namespace", "foo", subject) shouldBe CommandMessages.namespaceExists
 
+    //Adding same namespace with force flag should update the namespace with specified uuid:key
+    val newKey = resultOk("user", "create", "--force", "--auth", key2.compact, "--namespace", "foo", subject)
+    newKey shouldBe key2.compact
+
+    //Adding same namespace with force flag without auth should regenerate random uuid:key
+    val generatedKey = resultOk("user", "create", "--force", "--namespace", "foo", subject)
+    generatedKey should not be key2.compact
+    generatedKey should not be key.compact
+
     //It should be possible to lookup by new namespace
     implicit val tid = transid()
     val i = Identity.get(authStore, EntityName("foo")).futureValue
     i.subject.asString shouldBe subject
+    resultOk("user", "get", "--namespace", "foo", subject) shouldBe generatedKey
   }
 
   it should "not add namespace to a blocked user" in {
diff --git a/tools/admin/README-NEXT.md b/tools/admin/README-NEXT.md
index 30de6c3..f46d442 100644
--- a/tools/admin/README-NEXT.md
+++ b/tools/admin/README-NEXT.md
@@ -80,6 +80,14 @@ $ wskadmin-next user create userA -ns space1
 $ wskadmin-next user create userB -ns space1
 <prints new key specific to userB and space1>
 
+# force update a user with new uuid:key
+$ wskadmin-next user create -f userA
+<prints new UUID and new key>
+
+# revoke auth key of a user and regenerate a new key
+$ wskadmin-next user create -r userA
+<prints old UUID and new key>
+
 # list all users sharing a space
 $ wskadmin-next user list space1 -a
 <key for userA>   userA
diff --git a/tools/admin/src/main/scala/whisk/core/database/UserCommand.scala b/tools/admin/src/main/scala/whisk/core/database/UserCommand.scala
index b491e8f..991b023 100644
--- a/tools/admin/src/main/scala/whisk/core/database/UserCommand.scala
+++ b/tools/admin/src/main/scala/whisk/core/database/UserCommand.scala
@@ -48,6 +48,10 @@ class UserCommand extends Subcommand("user") with WhiskCommand {
         short = 'u')
     val namespace =
       opt[String](descr = "create key for given namespace instead (defaults to subject id)", argName = "NAMESPACE")
+    val revoke =
+      opt[Boolean](descr = "revoke the current authorization key and generate a new key", short = 'r')
+    val force =
+      opt[Boolean](descr = "force update an existing subject authorization uuid:key", short = 'f')
     val subject = trailArg[String](descr = "the subject to create")
 
     validate(subject) { s =>
@@ -164,14 +168,23 @@ class UserCommand extends Subcommand("user") with WhiskCommand {
     authStore
       .get[ExtendedAuth](DocInfo(create.subject()))
       .flatMap { auth =>
+        val nsToUpdate = create.desiredNamespace(authKey).name
+        val existingNS = auth.namespaces.filter(_.namespace.name != nsToUpdate)
         if (auth.isBlocked) {
           Future.successful(Left(IllegalState(CommandMessages.subjectBlocked)))
-        } else if (auth.namespaces.exists(_.namespace.name == create.desiredNamespace(authKey).name)) {
-          Future.successful(Left(IllegalState(CommandMessages.namespaceExists)))
-        } else {
-          val newNS = auth.namespaces + WhiskNamespace(create.desiredNamespace(authKey), authKey)
+        } else if (!auth.namespaces.exists(_.namespace.name == nsToUpdate) || create.force.isSupplied) {
+          val newNS = existingNS + WhiskNamespace(create.desiredNamespace(authKey), authKey)
           val newAuth = WhiskAuth(auth.subject, newNS).revision[WhiskAuth](auth.rev)
           authStore.put(newAuth).map(_ => Right(authKey.compact))
+        } else if (create.revoke.isSupplied) {
+          val updatedAuthKey = auth.namespaces.find(_.namespace.name == nsToUpdate).get.authkey
+          val newAuthKey = new BasicAuthenticationAuthKey(updatedAuthKey.uuid, Secret())
+
+          val newNS = existingNS + WhiskNamespace(create.desiredNamespace(newAuthKey), newAuthKey)
+          val newAuth = WhiskAuth(auth.subject, newNS).revision[WhiskAuth](auth.rev)
+          authStore.put(newAuth).map(_ => Right(newAuthKey.compact))
+        } else {
+          Future.successful(Left(IllegalState(CommandMessages.namespaceExists)))
         }
       }
       .recoverWith {