@@ -43,6 +43,8 @@ import org.apache.openwhisk.http.Messages._
4343import org .apache .openwhisk .core .entitlement .Resource
4444import org .apache .openwhisk .core .entitlement .Collection
4545import org .apache .openwhisk .core .loadBalancer .LoadBalancerException
46+ import pureconfig ._
47+ import org .apache .openwhisk .core .ConfigKeys
4648
4749/**
4850 * A singleton object which defines the properties that must be present in a configuration
@@ -102,6 +104,10 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
102104 /** Database service to get activations. */
103105 protected val activationStore : ActivationStore
104106
107+ /** Config flag for Execute Only for Actions in Shared Packages */
108+ protected def executeOnly =
109+ loadConfigOrThrow[Boolean ](ConfigKeys .sharedPackageExecuteOnly)
110+
105111 /** Entity normalizer to JSON object. */
106112 import RestApiCommons .emptyEntityToJsObject
107113
@@ -330,6 +336,50 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
330336 deleteEntity(WhiskAction , entityStore, entityName.toDocId, (a : WhiskAction ) => Future .successful({}))
331337 }
332338
339+ /** Checks for package binding case. we don't want to allow get for a package binding in shared package */
340+ private def fetchEntity (entityName : FullyQualifiedEntityName , env : Option [Parameters ], code : Boolean )(
341+ implicit transid : TransactionId ) = {
342+ val resolvedPkg : Future [Either [String , FullyQualifiedEntityName ]] = if (entityName.path.defaultPackage) {
343+ Future .successful(Right (entityName))
344+ } else {
345+ WhiskPackage .resolveBinding(entityStore, entityName.path.toDocId, mergeParameters = true ).map { pkg =>
346+ val originalPackageLocation = pkg.fullyQualifiedName(withVersion = false ).namespace
347+ if (executeOnly && originalPackageLocation != entityName.namespace) {
348+ Left (forbiddenGetActionBinding(entityName.toDocId.asString))
349+ } else {
350+ Right (entityName)
351+ }
352+ }
353+ }
354+ onComplete(resolvedPkg) {
355+ case Success (pkgFuture) =>
356+ pkgFuture match {
357+ case Left (f) => terminate(Forbidden , f)
358+ case Right (_) =>
359+ if (code) {
360+ getEntity(WhiskAction .resolveActionAndMergeParameters(entityStore, entityName), Some {
361+ action : WhiskAction =>
362+ val mergedAction = env map {
363+ action inherit _
364+ } getOrElse action
365+ complete(OK , mergedAction)
366+ })
367+ } else {
368+ getEntity(WhiskActionMetaData .resolveActionAndMergeParameters(entityStore, entityName), Some {
369+ action : WhiskActionMetaData =>
370+ val mergedAction = env map {
371+ action inherit _
372+ } getOrElse action
373+ complete(OK , mergedAction)
374+ })
375+ }
376+ }
377+ case Failure (t : Throwable ) =>
378+ logging.error(this , s " [GET] package ${entityName.path.toDocId} failed: ${t.getMessage}" )
379+ terminate(InternalServerError )
380+ }
381+ }
382+
333383 /**
334384 * Gets action. The action name is prefixed with the namespace to create the primary index key.
335385 *
@@ -341,22 +391,12 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
341391 override def fetch (user : Identity , entityName : FullyQualifiedEntityName , env : Option [Parameters ])(
342392 implicit transid : TransactionId ) = {
343393 parameter(' code ? true ) { code =>
344- code match {
345- case true =>
346- getEntity(WhiskAction .resolveActionAndMergeParameters(entityStore, entityName), Some { action : WhiskAction =>
347- val mergedAction = env map {
348- action inherit _
349- } getOrElse action
350- complete(OK , mergedAction)
351- })
352- case false =>
353- getEntity(WhiskActionMetaData .resolveActionAndMergeParameters(entityStore, entityName), Some {
354- action : WhiskActionMetaData =>
355- val mergedAction = env map {
356- action inherit _
357- } getOrElse action
358- complete(OK , mergedAction)
359- })
394+ // check if execute only is enabled, and if there is a discrepancy between the current user's namespace
395+ // and that of the entity we are trying to fetch
396+ if (executeOnly && user.namespace.name != entityName.namespace) {
397+ terminate(Forbidden , forbiddenGetAction(entityName.path.asString))
398+ } else {
399+ fetchEntity(entityName, env, code)
360400 }
361401 }
362402 }
0 commit comments