@@ -19,7 +19,6 @@ package whisk.core.entitlement
1919
2020import scala .collection .concurrent .TrieMap
2121import scala .collection .immutable .Set
22- import scala .collection .mutable .ListBuffer
2322import scala .concurrent .Future
2423import scala .util .Failure
2524import scala .util .Success
@@ -49,7 +48,7 @@ package object types {
4948 * Resource is a type that encapsulates details relevant to identify a specific resource.
5049 * It may be an entire collection, or an element in a collection.
5150 *
52- * @param ns the namespace the resource resides in
51+ * @param namespace the namespace the resource resides in
5352 * @param collection the collection (e.g., actions, triggers) identifying a resource
5453 * @param entity an optional entity name that identifies a specific item in the collection
5554 * @param env an optional environment to bind to the resource during an activation
@@ -59,8 +58,8 @@ protected[core] case class Resource(namespace: EntityPath,
5958 entity : Option [String ],
6059 env : Option [Parameters ] = None ) {
6160 def parent = collection.path + EntityPath .PATHSEP + namespace
62- def id = parent + ( entity map { EntityPath .PATHSEP + _ } getOrElse (" " ) )
63- def fqname = namespace.asString + ( entity map { EntityPath .PATHSEP + _ } getOrElse (" " ) )
61+ def id = parent + entity. map( EntityPath .PATHSEP + _). getOrElse(" " )
62+ def fqname = namespace.asString + entity. map( EntityPath .PATHSEP + _). getOrElse(" " )
6463 override def toString = id
6564}
6665
@@ -186,6 +185,21 @@ protected[core] abstract class EntitlementProvider(config: WhiskConfig, loadBala
186185 protected [core] def check (user : Identity , right : Privilege , resource : Resource )(
187186 implicit transid : TransactionId ): Future [Unit ] = check(user, right, Set (resource))
188187
188+ /**
189+ * Constructs a RejectRequest containing the forbidden resources.
190+ *
191+ * @param resources resources forbidden to access
192+ * @return a RejectRequest with the appropriate message
193+ */
194+ private def unauthorizedOn (resources : Set [Resource ])(implicit transid : TransactionId ) = {
195+ RejectRequest (
196+ Forbidden ,
197+ Some (
198+ ErrorResponse (
199+ Messages .notAuthorizedtoAccessResource(resources.map(_.fqname).toSeq.sorted.toSet.mkString(" , " )),
200+ transid)))
201+ }
202+
189203 /**
190204 * Checks if a subject has the right to access a set of resources. The entitlement may be implicit,
191205 * that is, inferred based on namespaces that a subject belongs to and the namespace of the
@@ -200,58 +214,36 @@ protected[core] abstract class EntitlementProvider(config: WhiskConfig, loadBala
200214 protected [core] def check (user : Identity , right : Privilege , resources : Set [Resource ])(
201215 implicit transid : TransactionId ): Future [Unit ] = {
202216 val subject = user.subject
203- val inaccessibleResources = ListBuffer [Resource ]()
204217
205- val entitlementCheck : Future [Boolean ] = if (user.rights.contains(right)) {
218+ val entitlementCheck : Future [Unit ] = if (user.rights.contains(right)) {
206219 if (resources.nonEmpty) {
207220 logging.info(this , s " checking user ' $subject' has privilege ' $right' for ' ${resources.mkString(" , " )}' " )
208221 checkSystemOverload(right)
209222 .flatMap(_ => checkUserThrottle(user, right, resources))
210223 .flatMap(_ => checkConcurrentUserThrottle(user, right, resources))
211224 .flatMap(_ => checkPrivilege(user, right, resources))
212- .flatMap(resourcePrivSet => {
213- resourcePrivSet.map { resourcePriv =>
214- if (! resourcePriv._2) inaccessibleResources += resourcePriv._1
215- }
216- Future .successful(inaccessibleResources.length == 0 )
225+ .flatMap(checkedResources => {
226+ val failedResources = checkedResources.filterNot(_._2)
227+ if (failedResources.isEmpty) Future .successful(())
228+ else Future .failed(unauthorizedOn(failedResources.map(_._1)))
217229 })
218- } else Future .successful(true )
230+ } else Future .successful(() )
219231 } else if (right != REJECT ) {
220- resources.map(r => inaccessibleResources += r)
221232 logging.info(
222233 this ,
223234 s " supplied authkey for user ' $subject' does not have privilege ' $right' for ' ${resources.mkString(" , " )}' " )
224- Future .failed(
225- RejectRequest (
226- Forbidden ,
227- Some (
228- ErrorResponse (
229- Messages .notAuthorizedtoAccessResource(
230- inaccessibleResources.map(r => r.fqname).sorted.toSet.mkString(" , " )),
231- transid))))
235+ Future .failed(unauthorizedOn(resources))
232236 } else {
233- resources.map(r => inaccessibleResources += r)
234- Future .successful(false )
237+ Future .failed(unauthorizedOn(resources))
235238 }
239+
236240 entitlementCheck andThen {
237- case Success (r) if resources.nonEmpty =>
238- logging.info(this , if (r) " authorized " else " not authorized" )
241+ case Success (rs) =>
242+ logging.info(this , " authorized" )
239243 case Failure (r : RejectRequest ) =>
240244 logging.info(this , s " not authorized: $r" )
241245 case Failure (t) =>
242246 logging.error(this , s " failed while checking entitlement: ${t.getMessage}" )
243- } flatMap { isAuthorized =>
244- if (isAuthorized) Future .successful({})
245- else {
246- Future .failed(
247- RejectRequest (
248- Forbidden ,
249- Some (
250- ErrorResponse (
251- Messages .notAuthorizedtoAccessResource(
252- inaccessibleResources.map(r => r.fqname).sorted.toSet.mkString(" , " )),
253- transid))))
254- }
255247 }
256248 }
257249
@@ -273,9 +265,7 @@ protected[core] abstract class EntitlementProvider(config: WhiskConfig, loadBala
273265 case true => Future .successful(resource -> true )
274266 case false =>
275267 logging.info(this , " checking explicit grants" )
276- entitled(user.subject, right, resource) flatMap {
277- case b => Future .successful(resource -> b)
278- }
268+ entitled(user.subject, right, resource).flatMap(b => Future .successful(resource -> b))
279269 }
280270 }
281271 }
@@ -305,7 +295,7 @@ protected[core] abstract class EntitlementProvider(config: WhiskConfig, loadBala
305295 *
306296 * @param user the subject identity to check rights for
307297 * @param right the privilege, if ACTIVATE then check quota else return None
308- * @param resource the set of resources must contain at least one resource that can be activated else return None
298+ * @param resources the set of resources must contain at least one resource that can be activated else return None
309299 * @return future completing successfully if user is below limits else failing with a rejection
310300 */
311301 private def checkUserThrottle (user : Identity , right : Privilege , resources : Set [Resource ])(
@@ -327,7 +317,7 @@ protected[core] abstract class EntitlementProvider(config: WhiskConfig, loadBala
327317 *
328318 * @param user the subject identity to check rights for
329319 * @param right the privilege, if ACTIVATE then check quota else return None
330- * @param resource the set of resources must contain at least one resource that can be activated else return None
320+ * @param resources the set of resources must contain at least one resource that can be activated else return None
331321 * @return future completing successfully if user is below limits else failing with a rejection
332322 */
333323 private def checkConcurrentUserThrottle (user : Identity , right : Privilege , resources : Set [Resource ])(
0 commit comments