From 4af70b8b9405761ca0715dea10051e045feb0d90 Mon Sep 17 00:00:00 2001 From: "ning.yougang" Date: Mon, 8 Jun 2020 15:53:30 +0800 Subject: [PATCH] Make the action's downloadable for the shared user --- .../openwhisk/core/entity/WhiskAction.scala | 44 +++++++++++++------ .../openwhisk/core/controller/Actions.scala | 19 +++++--- .../core/entitlement/Entitlement.scala | 22 +++++++++- docs/actions.md | 16 ++++--- 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala b/common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala index c9214699920..92c9047117d 100644 --- a/common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala +++ b/common/scala/src/main/scala/org/apache/openwhisk/core/entity/WhiskAction.scala @@ -367,23 +367,41 @@ object WhiskAction extends DocumentFactory[WhiskAction] with WhiskEntityQueries[ // notes on users, just have 2 type users, // 1. the action's owner - // 2. the user (not the owner) who used the shared action directly(e.g. get, invoke) + // 2. the user (not the owner) who used the shared action directly(e.g. get, invoke), we call it "the shared user" // // Notes on permission control - // 1. the action's read permission should open forever, because under invoke action or update action and so on, - // need to use `fetch` api to get the action to judge it whether exist. - // 2. the user(not the owner) can't update/delete the action forever. - // 3. the owner's permission can affect other user's permission, e.g - // if the owner is not given execute permission, the user(not the owner) can't have execute permission as well. + // 1. the owner has read(or download) permission on any situation, but for the shared user, + // in spite of has read permission on any situation, but can set it undownloadable or downloadable + // 2. the shared user can't update/delete the action on any situation. + // 3. the owner's permission can affect the shared user's permission, e.g + // if the owner is not given execute permission, the shared user can't have execute permission as well. // // Notes on permission values, include below permission value - // 1. permission code:rwxr-x: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(yes), this is default - // 2. permission code:rwxr--: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(no) - // 3. permission code:r-xr-x: owner:read(yes)/write(no)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(yes) - // 4. permission code:r-xr--: owner:read(yes)/write(no)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(no) - // 5. permission code:r--r--: owner:read(yes)/write(no)/execute(no)|the shared action's user:read(yes)/write(no)/execute(no) - // 6. permission code:rw-r--: owner:read(yes)/write(yes)/execute(no)|the shared action's user:read(yes)/write(no)/execute(no) - val permissionList = List(defaultPermissions, "rwxr--", "r-xr-x", "r-xr--", "r--r--", "rw-r--") + // 1. permission code:rwxr-x: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(yes)/write(no)/execute(yes), this is default + // 2. permission code:rwxr--: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(yes)/write(no)/execute(no) + // 3. permission code:r-xr-x: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(yes)/write(no)/execute(yes) + // 4. permission code:r-xr--: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(yes)/write(no)/execute(no) + // 5. permission code:r--r--: owner:read(yes)/write(no)/execute(no)|the shared action's user:download(yes)/write(no)/execute(no) + // 6. permission code:rw-r--: owner:read(yes)/write(yes)/execute(no)|the shared action's user:download(yes)/write(no)/execute(no) + // 7. permission code:rwx--x: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(no)/write(no)/execute(yes) + // 8. permission code:rwx---: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(no)/write(no)/execute(no) + // 9. permission code:r-x--x: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(no)/write(no)/execute(yes) + // 10. permission code:r-x---: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(no)/write(no)/execute(no) + // 11. permission code:r-----: owner:read(yes)/write(no)/execute(no)|the shared action's user:download(no)/write(no)/execute(no) + // 12. permission code:rw----: owner:read(yes)/write(yes)/execute(no)|the shared action's user:download(no)/write(no)/execute(no) + val permissionList = List( + defaultPermissions, + "rwxr--", + "r-xr-x", + "r-xr--", + "r--r--", + "rw-r--", + "rwx--x", + "rwx---", + "r-x--x", + "r-x---", + "r-----", + "rw----") override val collectionName = "actions" override val cacheEnabled = true diff --git a/core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala b/core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala index 5715687e1fc..6100812a3e9 100644 --- a/core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala +++ b/core/controller/src/main/scala/org/apache/openwhisk/core/controller/Actions.scala @@ -368,12 +368,19 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with parameter('code ? true) { code => code match { case true => - getEntity(WhiskAction.resolveActionAndMergeParameters(entityStore, entityName), Some { action: WhiskAction => - val mergedAction = env map { - action inherit _ - } getOrElse action - complete(OK, mergedAction) - }) + onComplete( + entitlementProvider + .checkActionPermissions("download", user, entityStore, entityName, WhiskAction.get)) { + case Success(_) => + getEntity(WhiskAction.resolveActionAndMergeParameters(entityStore, entityName), Some { + action: WhiskAction => + val mergedAction = env map { + action inherit _ + } getOrElse action + complete(OK, mergedAction) + }) + case Failure(f) => super.handleEntitlementFailure(f) + } case false => getEntity(WhiskActionMetaData.resolveActionAndMergeParameters(entityStore, entityName), Some { action: WhiskActionMetaData => diff --git a/core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/Entitlement.scala b/core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/Entitlement.scala index 2450d14032a..a3d865cd852 100644 --- a/core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/Entitlement.scala +++ b/core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/Entitlement.scala @@ -334,8 +334,26 @@ protected[core] abstract class EntitlementProvider( Future.successful(()) } } - } else { //get - 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) + if (user.namespace.name.asString != entityName.path.root.asString) { // the shared user who download the action + if (currentDownloadPermission == '-') { + Future.failed(RejectRequest(Forbidden, Some(ErrorResponse(errorInfo, transid)))) + } else { + Future.successful(()) + } + } else { + // the owner has download permission on any situation + Future.successful(()) + } + } } } diff --git a/docs/actions.md b/docs/actions.md index 0bc71e448bf..f4973ecb3ab 100644 --- a/docs/actions.md +++ b/docs/actions.md @@ -662,14 +662,14 @@ You can clean up by deleting actions that you do not want to use. * Notes on users, just have 2 type users, - the action's owner - - the user (not the owner) who used the shared action directly(e.g. get, invoke) + - the user (not the owner) who used the shared action directly(e.g. get, invoke), we call it "the shared user" * Notes on permission control - - the action's read permission should open forever, because under invoke action or update action and so on, - need to use `fetch` api to get the action to judge it whether exist. - - the user(not the owner) can't update/delete the action forever. + - the owner has read(or download) permission on any situation, but for the shared user, + in spite of has read permission on any situation, but can set it undownloadable or downloadable + - the shared user can't update/delete the action forever. - the owner's permission can affect other user's permission, e.g - if the owner is not given execute permission, the user(not the owner) can't have execute permission as well. + if the owner is not given execute permission, the shared user can't have execute permission as well. * Notes on permission values, include below permission value - permission code:rwxr-x: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(yes), this is default @@ -678,6 +678,12 @@ You can clean up by deleting actions that you do not want to use. - permission code:r-xr--: owner:read(yes)/write(no)/execute(yes)|the shared action's user:read(yes)/write(no)/execute(no) - permission code:r--r--: owner:read(yes)/write(no)/execute(no)|the shared action's user:read(yes)/write(no)/execute(no) - permission code:rw-r--: owner:read(yes)/write(yes)/execute(no)|the shared action's user:read(yes)/write(no)/execute(no) + - permission code:rwx--x: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(no)/write(no)/execute(yes) + - permission code:rwx---: owner:read(yes)/write(yes)/execute(yes)|the shared action's user:download(no)/write(no)/execute(no) + - permission code:r-x--x: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(no)/write(no)/execute(yes) + - permission code:r-x---: owner:read(yes)/write(no)/execute(yes)|the shared action's user:download(no)/write(no)/execute(no) + - permission code:r-----: owner:read(yes)/write(no)/execute(no)|the shared action's user:download(no)/write(no)/execute(no) + - permission code:rw----: owner:read(yes)/write(yes)/execute(no)|the shared action's user:download(no)/write(no)/execute(no) When create action without permissions annotation, permission control keeps the same as before, e.g. the owner has all permissions(create/update(or delete)/invoke), the user(not owner) doesn't have update/delete permission on the shared action.