You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2021/05/28 02:56:48 UTC

[GitHub] [openwhisk] ningyougang commented on a change in pull request #4058: Add protect feature to avoid update or delete actions by mistake

ningyougang commented on a change in pull request #4058:
URL: https://github.com/apache/openwhisk/pull/4058#discussion_r641184253



##########
File path: core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/Entitlement.scala
##########
@@ -231,6 +234,157 @@ protected[core] abstract class EntitlementProvider(
       .getOrElse(Future.successful(()))
   }
 
+  /**
+   * Checks if action operation(get/write/execute) whether feasible
+   *
+   * @param operation the action operation, e.g. get/write/execute
+   * @param user the user who get/write/execute the action
+   * @param entityStore  store to write the action to
+   * @param entityName entityName
+   * @param permissions the passed permission code
+   * @return a promise that completes with success iff action operation is feasible
+   */
+  protected[core] def checkActionPermissions(
+    operation: String,
+    user: Identity,
+    entityStore: ArtifactStore[WhiskEntity],
+    entityName: FullyQualifiedEntityName,
+    get: (ArtifactStore[WhiskEntity], DocId, DocRevision, Boolean) => Future[WhiskAction],
+    permissions: Option[String] = None)(implicit transid: TransactionId): Future[Unit] = {
+    if (operation == "create") {
+      permissions
+        .map { value =>
+          if (WhiskAction.permissionList.contains(value)) {
+            Future.successful(())
+          } else {
+            val errorInfo =
+              s"give error permission code: ${value}, available permission is in ${WhiskAction.permissionList}"
+            Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+          }
+        }
+        .getOrElse(Future.successful(()))
+    } else if (operation == "update") {
+      get(entityStore, entityName.toDocId, DocRevision.empty, true)
+        .flatMap { whiskAction =>
+          val currentPermissions = whiskAction.annotations
+            .get(WhiskAction.permissionsFieldName)
+            .map(value => value.convertTo[String])
+            .getOrElse(WhiskAction.defaultPermissions)
+
+          val errorInfo = s"have no permission to ${operation} this action"
+          permissions match {
+            case Some(value) =>
+              if (!WhiskAction.permissionList.contains(value)) {
+                val errorInfo =
+                  s"give error permission code: ${value}, available permission is in ${WhiskAction.permissionList}"
+                Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+              } else {
+                val passedUpdatePermission = value.charAt(1)
+                if (passedUpdatePermission == 'w') { // make it to modifiable
+                  Future.successful(())
+                } else {
+                  val currentUpdatePermission = currentPermissions.charAt(1)
+                  if (currentUpdatePermission == '-') {
+                    Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+                  } else {
+                    Future.successful(())
+                  }
+                }
+              }
+            case None =>
+              val currentUpdatePermission = currentPermissions.charAt(1)
+              if (currentUpdatePermission == '-') {
+                Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+              } else {
+                Future.successful(())
+              }
+          }
+        }
+        .recoverWith {
+          case t: RejectRequest =>
+            Future.failed(t)
+          case _ =>
+            Future.successful(())
+        }
+    } else if (operation == "remove") {
+      get(entityStore, entityName.toDocId, DocRevision.empty, true)
+        .flatMap { whiskAction =>
+          val currentPermissions = whiskAction.annotations
+            .get(WhiskAction.permissionsFieldName)
+            .map(value => value.convertTo[String])
+            .getOrElse(WhiskAction.defaultPermissions)
+
+          val currentUpdatePermission = currentPermissions.charAt(1)
+          if (currentUpdatePermission == '-') {
+            val errorInfo = s"have no permission to ${operation} this action"
+            Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+          } else {
+            Future.successful(())
+          }
+        }
+        .recoverWith {
+          case t: RejectRequest =>
+            Future.failed(t)
+          case _ =>
+            Future.successful(())
+        }
+    } else if (operation == "invoke") {
+      get(entityStore, entityName.toDocId, DocRevision.empty, true)
+        .flatMap { whiskAction =>
+          val currentPermissions = whiskAction.annotations
+            .get(WhiskAction.permissionsFieldName)
+            .map(value => value.convertTo[String])
+            .getOrElse(WhiskAction.defaultPermissions)
+
+          // the user who is owner by default
+          var currentExecutePermission = currentPermissions.charAt(2)
+          var errorInfo = s"have no permission to ${operation} this action"
+          if (user.namespace.name.asString != entityName.path.root.asString) { // the user who invoke the shared action
+            currentExecutePermission = currentPermissions.charAt(5)
+            errorInfo = s"have no permission to ${operation} this shared action"
+          }
+          if (currentExecutePermission == '-') { //have no permission
+            Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid))))
+          } else {
+            Future.successful(())
+          }
+        }
+        .recoverWith {
+          case t: RejectRequest =>
+            Future.failed(t)
+          case _ =>
+            Future.successful(())
+        }
+    } else { // download the code
+      get(entityStore, entityName.toDocId, DocRevision.empty, true)
+        .flatMap { whiskAction =>
+          val currentPermissions = whiskAction.annotations
+            .get(WhiskAction.permissionsFieldName)
+            .map(value => value.convertTo[String])
+            .getOrElse(WhiskAction.defaultPermissions)
+
+          val errorInfo = s"have no permission to download this shared action"
+          val currentDownloadPermission = currentPermissions.charAt(3)

Review comment:
       It seems it is for `the shared user`
   ![image](https://user-images.githubusercontent.com/11749867/119922929-5f0a0a00-bfa3-11eb-94e8-370e9056f123.png)
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org