in core/controller/src/main/scala/org/apache/openwhisk/core/entitlement/PackageCollection.scala [84:144]
private def checkPackageReadPermission(namespaces: Set[String], isOwner: Boolean, doc: DocId)(
implicit ec: ExecutionContext,
transid: TransactionId): Future[Boolean] = {
val right = Privilege.READ
WhiskPackage.get(entityStore, doc) flatMap {
case wp if wp.binding.isEmpty =>
val allowed = wp.publish || isOwner
logging.debug(this, s"entitlement check on package, '$right' allowed?: $allowed")
Future.successful(allowed)
case wp =>
if (isOwner) {
val binding = wp.binding.get
val pkgOwner = namespaces.contains(binding.namespace.asString)
val pkgDocid = binding.docid
logging.debug(this, s"checking subject has privilege '$right' for bound package '$pkgDocid'")
if (doc == pkgDocid) {
logging.error(this, s"unexpected package binding refers to itself: $doc")
Future.failed(
RejectRequest(
UnprocessableEntity,
Messages.packageBindingCircularReference(binding.fullyQualifiedName.toString)))
} else {
checkPackageReadPermission(namespaces, pkgOwner, pkgDocid)
}
} else {
logging.debug(this, s"entitlement check on package binding, '$right' allowed?: false")
Future.successful(false)
}
} recoverWith {
case t: NoDocumentException =>
logging.debug(this, s"the package does not exist (owner? $isOwner)")
// if owner, reject with not found, otherwise fail the future to reject with
// unauthorized (this prevents information leaks about packages in other namespaces)
if (isOwner) {
Future.failed(RejectRequest(NotFound))
} else {
Future.successful(false)
}
case t: DocumentTypeMismatchException =>
logging.debug(this, s"the requested binding is not a package (owner? $isOwner)")
// if owner, reject with not found, otherwise fail the future to reject with
// unauthorized (this prevents information leaks about packages in other namespaces)
if (isOwner) {
Future.failed(RejectRequest(Conflict, Messages.conformanceMessage))
} else {
Future.successful(false)
}
case t: RejectRequest =>
logging.error(this, s"entitlement check on package failed: $t")
Future.failed(t)
case t =>
logging.error(this, s"entitlement check on package failed: ${t.getMessage}")
if (isOwner) {
Future.failed(RejectRequest(InternalServerError, Messages.corruptedEntity))
} else {
Future.successful(false)
}
}
}