This is an automated email from the ASF dual-hosted git repository. markusthoemmes pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push: new 1d79fa3 Move uuid into namespace to decouple it from authkey. (#3752) 1d79fa3 is described below commit 1d79fa395de32c6a774efeb4f53563689e9cbb7e Author: Martin Henke <martin.he...@web.de> AuthorDate: Thu Jun 14 19:51:05 2018 +0200 Move uuid into namespace to decouple it from authkey. (#3752) In many places the uuid stored in the authkey is now used as the unique way to identify a namespace. This behavior entangles the authorization mechanisms with other unrelated parts of the code, making changes and extensions of the authentication mechanism unnecessarily hard. This PR makes the uuid a member of a new namespace object containing the name and the uuid of the namespace. All references to the uuid that are not used on the context of authorization are using the new namespace object as source. --- .../logging/DockerToActivationFileLogStore.scala | 2 +- .../logging/ElasticSearchLogStore.scala | 2 +- .../main/scala/whisk/core/entity/EntityPath.scala | 8 ++ .../main/scala/whisk/core/entity/Identity.scala | 20 ++-- .../main/scala/whisk/core/entity/WhiskAction.scala | 13 ++- .../main/scala/whisk/core/entity/WhiskAuth.scala | 6 +- .../controller/AuthorizedRouteDispatcher.scala | 2 +- .../scala/whisk/core/controller/Namespaces.scala | 2 +- .../scala/whisk/core/controller/Packages.scala | 2 +- .../scala/whisk/core/controller/Triggers.scala | 2 +- .../scala/whisk/core/controller/WebActions.scala | 2 +- .../core/controller/actions/PrimitiveActions.scala | 6 +- .../core/controller/actions/SequenceActions.scala | 2 +- .../core/entitlement/ActivationThrottler.scala | 4 +- .../scala/whisk/core/entitlement/Entitlement.scala | 10 +- .../whisk/core/entitlement/RateThrottler.scala | 2 +- .../core/loadBalancer/InvokerSupervision.scala | 5 +- .../ShardingContainerPoolBalancer.scala | 6 +- .../whisk/core/containerpool/ContainerPool.scala | 4 +- .../whisk/core/containerpool/ContainerProxy.scala | 24 +++-- .../KubernetesInvokerAgentLogStore.scala | 2 +- .../scala/whisk/core/invoker/InvokerReactive.scala | 8 +- .../whisk/core/invoker/NamespaceBlacklist.scala | 2 +- .../logging/ElasticSearchLogStoreTests.scala | 5 +- .../logging/SplunkLogStoreTests.scala | 3 +- .../test/DockerToActivationFileLogStoreTests.scala | 4 +- .../test/DockerToActivationLogStoreTests.scala | 7 +- .../containerpool/test/ContainerPoolTests.scala | 3 +- .../containerpool/test/ContainerProxyTests.scala | 6 +- .../core/controller/test/AuthenticateTests.scala | 11 +- .../controller/test/EntitlementProviderTests.scala | 112 +++++++++++---------- .../core/controller/test/PackagesApiTests.scala | 2 +- .../core/controller/test/WebActionsApiTests.scala | 16 ++- .../core/controller/test/WhiskAuthHelpers.scala | 5 +- .../test/behavior/ArtifactStoreBehaviorBase.scala | 3 +- .../ArtifactStoreSubjectQueryBehaviors.scala | 52 ++++++---- .../scala/whisk/core/entity/test/SchemaTests.scala | 3 + .../invoker/test/NamespaceBlacklistTests.scala | 30 ++++-- .../whisk/core/limits/ActionLimitsTests.scala | 2 +- .../test/InvokerSupervisionTests.scala | 17 +--- 40 files changed, 243 insertions(+), 174 deletions(-) diff --git a/common/scala/src/main/scala/whisk/core/containerpool/logging/DockerToActivationFileLogStore.scala b/common/scala/src/main/scala/whisk/core/containerpool/logging/DockerToActivationFileLogStore.scala index 4be36a7..3368d2a 100644 --- a/common/scala/src/main/scala/whisk/core/containerpool/logging/DockerToActivationFileLogStore.scala +++ b/common/scala/src/main/scala/whisk/core/containerpool/logging/DockerToActivationFileLogStore.scala @@ -101,7 +101,7 @@ class DockerToActivationFileLogStore(system: ActorSystem, destinationDirectory: val logs = container.logs(action.limits.logs.asMegaBytes, action.exec.sentinelledLogs)(transid) // Adding the userId field to every written record, so any background process can properly correlate. - val userIdField = Map("namespaceId" -> user.authkey.uuid.toJson) + val userIdField = Map("namespaceId" -> user.namespace.uuid.toJson) val additionalMetadata = Map( "activationId" -> activation.activationId.asString.toJson, diff --git a/common/scala/src/main/scala/whisk/core/containerpool/logging/ElasticSearchLogStore.scala b/common/scala/src/main/scala/whisk/core/containerpool/logging/ElasticSearchLogStore.scala index 26f0cd3..3340204 100644 --- a/common/scala/src/main/scala/whisk/core/containerpool/logging/ElasticSearchLogStore.scala +++ b/common/scala/src/main/scala/whisk/core/containerpool/logging/ElasticSearchLogStore.scala @@ -97,7 +97,7 @@ class ElasticSearchLogStore( EsQuery(queryString, Some(queryOrder)) } - private def generatePath(user: Identity) = elasticSearchConfig.path.format(user.uuid.asString) + private def generatePath(user: Identity) = elasticSearchConfig.path.format(user.namespace.uuid.asString) override def fetchLogs(user: Identity, activation: WhiskActivation, request: HttpRequest): Future[ActivationLogs] = { val headers = extractRequiredHeaders(request.headers) diff --git a/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala b/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala index 0262f10..5bedddd 100644 --- a/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala +++ b/common/scala/src/main/scala/whisk/core/entity/EntityPath.scala @@ -82,6 +82,14 @@ protected[core] class EntityPath private (private val path: Seq[String]) extends * Replaces root of this path with given namespace iff the root is * the default namespace. */ + def resolveNamespace(newNamespace: Namespace): EntityPath = { + resolveNamespace(newNamespace.name) + } + + /** + * Replaces root of this path with given namespace iff the root is + * the default namespace. + */ def resolveNamespace(newNamespace: EntityName): EntityPath = { // check if namespace is default if (root.toPath == EntityPath.DEFAULT) { diff --git a/common/scala/src/main/scala/whisk/core/entity/Identity.scala b/common/scala/src/main/scala/whisk/core/entity/Identity.scala index e1b2526..f5526f9 100644 --- a/common/scala/src/main/scala/whisk/core/entity/Identity.scala +++ b/common/scala/src/main/scala/whisk/core/entity/Identity.scala @@ -19,7 +19,6 @@ package whisk.core.entity import scala.concurrent.Future import scala.util.Try - import spray.json._ import types.AuthStore import whisk.common.Logging @@ -38,13 +37,17 @@ object UserLimits extends DefaultJsonProtocol { implicit val serdes = jsonFormat3(UserLimits.apply) } +protected[core] case class Namespace(name: EntityName, uuid: UUID) + +protected[core] object Namespace extends DefaultJsonProtocol { + implicit val serdes = jsonFormat2(Namespace.apply) +} + protected[core] case class Identity(subject: Subject, - namespace: EntityName, + namespace: Namespace, authkey: AuthKey, rights: Set[Privilege], - limits: UserLimits = UserLimits()) { - def uuid = authkey.uuid -} + limits: UserLimits = UserLimits()) object Identity extends MultipleReadersSingleWriterCache[Identity, DocInfo] with DefaultJsonProtocol { @@ -126,7 +129,12 @@ object Identity extends MultipleReadersSingleWriterCache[Identity, DocInfo] with val JsString(uuid) = value("uuid") val JsString(secret) = value("key") val JsString(namespace) = value("namespace") - Identity(subject, EntityName(namespace), AuthKey(UUID(uuid), Secret(secret)), Privilege.ALL, limits) + Identity( + subject, + Namespace(EntityName(namespace), UUID(uuid)), + AuthKey(UUID(uuid), Secret(secret)), + Privilege.ALL, + limits) case _ => logger.error(this, s"$viewName[$key] has malformed view '${row.compactPrint}'") throw new IllegalStateException("identities view malformed") diff --git a/common/scala/src/main/scala/whisk/core/entity/WhiskAction.scala b/common/scala/src/main/scala/whisk/core/entity/WhiskAction.scala index ac6b2d0..3617ae0 100644 --- a/common/scala/src/main/scala/whisk/core/entity/WhiskAction.scala +++ b/common/scala/src/main/scala/whisk/core/entity/WhiskAction.scala @@ -59,7 +59,7 @@ case class WhiskActionPut(exec: Option[Exec] = None, /** * Resolves sequence components if they contain default namespace. */ - protected[core] def resolve(userNamespace: EntityName): WhiskActionPut = { + protected[core] def resolve(userNamespace: Namespace): WhiskActionPut = { exec map { case SequenceExec(components) => val newExec = SequenceExec(components map { c => @@ -143,6 +143,13 @@ case class WhiskAction(namespace: EntityPath, /** * Resolves sequence components if they contain default namespace. */ + protected[core] def resolve(userNamespace: Namespace): WhiskAction = { + resolve(userNamespace.name) + } + + /** + * Resolves sequence components if they contain default namespace. + */ protected[core] def resolve(userNamespace: EntityName): WhiskAction = { exec match { case SequenceExec(components) => @@ -202,11 +209,11 @@ case class WhiskActionMetaData(namespace: EntityPath, /** * Resolves sequence components if they contain default namespace. */ - protected[core] def resolve(userNamespace: EntityName): WhiskActionMetaData = { + protected[core] def resolve(userNamespace: Namespace): WhiskActionMetaData = { exec match { case SequenceExecMetaData(components) => val newExec = SequenceExecMetaData(components map { c => - FullyQualifiedEntityName(c.path.resolveNamespace(userNamespace), c.name) + FullyQualifiedEntityName(c.path.resolveNamespace(userNamespace.name), c.name) }) copy(exec = newExec).revision[WhiskActionMetaData](rev) case _ => this diff --git a/common/scala/src/main/scala/whisk/core/entity/WhiskAuth.scala b/common/scala/src/main/scala/whisk/core/entity/WhiskAuth.scala index be83471..2de9a86 100644 --- a/common/scala/src/main/scala/whisk/core/entity/WhiskAuth.scala +++ b/common/scala/src/main/scala/whisk/core/entity/WhiskAuth.scala @@ -25,18 +25,18 @@ import scala.util.Try * database. Each namespace has its own key which is used to determine * the {@ Identity} of the user calling. */ -protected[core] case class WhiskNamespace(name: EntityName, authkey: AuthKey) +protected[core] case class WhiskNamespace(namespace: Namespace, authkey: AuthKey) protected[core] object WhiskNamespace extends DefaultJsonProtocol { implicit val serdes = new RootJsonFormat[WhiskNamespace] { def write(w: WhiskNamespace) = - JsObject("name" -> w.name.toJson, "uuid" -> w.authkey.uuid.toJson, "key" -> w.authkey.key.toJson) + JsObject("name" -> w.namespace.name.toJson, "uuid" -> w.namespace.uuid.toJson, "key" -> w.authkey.key.toJson) def read(value: JsValue) = Try { value.asJsObject.getFields("name", "uuid", "key") match { case Seq(JsString(n), JsString(u), JsString(k)) => - WhiskNamespace(EntityName(n), AuthKey(UUID(u), Secret(k))) + WhiskNamespace(Namespace(EntityName(n), UUID(u)), AuthKey(UUID(u), Secret(k))) } } getOrElse deserializationError("namespace record malformed") } diff --git a/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala b/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala index 9288707..2ed1a94 100644 --- a/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala +++ b/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala @@ -114,7 +114,7 @@ trait BasicAuthorizedRouteProvider extends Directives { } else { Messages.namespaceIllegal } - }) & extract(_ => EntityPath(if (EntityPath(ns) == EntityPath.DEFAULT) user.namespace.asString else ns)) + }) & extract(_ => EntityPath(if (EntityPath(ns) == EntityPath.DEFAULT) user.namespace.name.asString else ns)) } /** Validates entity name from the matched path segment. */ diff --git a/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala b/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala index 0afbb40..f40a909 100644 --- a/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala +++ b/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala @@ -42,7 +42,7 @@ trait WhiskNamespacesApi extends Directives with AuthenticatedRouteProvider { */ override def routes(user: Identity)(implicit transid: TransactionId) = { (pathPrefix(collection.path) & collectionOps) { - complete(OK, List(user.namespace)) + complete(OK, List(user.namespace.name)) } } } diff --git a/core/controller/src/main/scala/whisk/core/controller/Packages.scala b/core/controller/src/main/scala/whisk/core/controller/Packages.scala index 509cc76..8cfbdcf 100644 --- a/core/controller/src/main/scala/whisk/core/controller/Packages.scala +++ b/core/controller/src/main/scala/whisk/core/controller/Packages.scala @@ -172,7 +172,7 @@ trait WhiskPackagesApi extends WhiskCollectionAPI with ReferencedEntities { 'skip.as[ListSkip] ? ListSkip(collection.defaultListSkip), 'limit.as[ListLimit] ? ListLimit(collection.defaultListLimit), 'count ? false) { (skip, limit, count) => - val viewName = if (user.namespace.toPath == namespace) WhiskPackage.view else WhiskPackage.publicPackagesView + val viewName = if (user.namespace.name.toPath == namespace) WhiskPackage.view else WhiskPackage.publicPackagesView if (!count) { listEntities { WhiskPackage diff --git a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala index 67c431c..88010d7 100644 --- a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala +++ b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala @@ -138,7 +138,7 @@ trait WhiskTriggersApi extends WhiskCollectionAPI { val triggerActivationId = activationIdFactory.make() logging.info(this, s"[POST] trigger activation id: ${triggerActivationId}") val triggerActivation = WhiskActivation( - namespace = user.namespace.toPath, // all activations should end up in the one space regardless trigger.namespace, + namespace = user.namespace.name.toPath, // all activations should end up in the one space regardless trigger.namespace, entityName.name, user.subject, triggerActivationId, diff --git a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala index d74815c..2878c66 100644 --- a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala +++ b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala @@ -112,7 +112,7 @@ private case class Context(propertyMap: WebApiDirectives, .toMap .toJson, propertyMap.path -> path.toJson) ++ - user.map(u => propertyMap.namespace -> u.namespace.asString.toJson) + user.map(u => propertyMap.namespace -> u.namespace.name.asString.toJson) } def toActionArgument(user: Option[Identity], boxQueryAndBody: Boolean): Map[String, JsValue] = { diff --git a/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala b/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala index 28dbedf..135bc48 100644 --- a/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala +++ b/core/controller/src/main/scala/whisk/core/controller/actions/PrimitiveActions.scala @@ -344,7 +344,7 @@ protected[actions] trait PrimitiveActions { // no next action, end composition execution, return to caller Future.successful(ActivationResponse(activation.response.statusCode, Some(params.getOrElse(result)))) case Some(next) => - FullyQualifiedEntityName.resolveName(next, user.namespace) match { + FullyQualifiedEntityName.resolveName(next, user.namespace.name) match { case Some(fqn) if session.accounting.components < actionSequenceLimit => tryInvokeNext(user, fqn, params, session) @@ -512,7 +512,7 @@ protected[actions] trait PrimitiveActions { // create the whisk activation val activation = WhiskActivation( - namespace = user.namespace.toPath, + namespace = user.namespace.name.toPath, name = session.action.name, user.subject, activationId = session.activationId, @@ -552,7 +552,7 @@ protected[actions] trait PrimitiveActions { implicit transid: TransactionId): Future[Either[ActivationId, WhiskActivation]] = { val result = Promise[Either[ActivationId, WhiskActivation]] - val docid = new DocId(WhiskEntity.qualifiedName(user.namespace.toPath, activationId)) + val docid = new DocId(WhiskEntity.qualifiedName(user.namespace.name.toPath, activationId)) logging.debug(this, s"action activation will block for result upto $totalWaitTime") // 1. Wait for the active-ack to happen. Either immediately resolve the promise or poll the database quickly diff --git a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala index 4375ee8..75ba2ac 100644 --- a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala +++ b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala @@ -196,7 +196,7 @@ protected[actions] trait SequenceActions { // create the whisk activation WhiskActivation( - namespace = user.namespace.toPath, + namespace = user.namespace.name.toPath, name = action.name, user.subject, activationId = activationId, diff --git a/core/controller/src/main/scala/whisk/core/entitlement/ActivationThrottler.scala b/core/controller/src/main/scala/whisk/core/entitlement/ActivationThrottler.scala index b99385a..92d5434 100644 --- a/core/controller/src/main/scala/whisk/core/entitlement/ActivationThrottler.scala +++ b/core/controller/src/main/scala/whisk/core/entitlement/ActivationThrottler.scala @@ -42,11 +42,11 @@ class ActivationThrottler(loadBalancer: LoadBalancer, concurrencyLimit: Identity * Checks whether the operation should be allowed to proceed. */ def check(user: Identity)(implicit tid: TransactionId): Future[RateLimit] = { - loadBalancer.activeActivationsFor(user.uuid).map { concurrentActivations => + loadBalancer.activeActivationsFor(user.namespace.uuid).map { concurrentActivations => val currentLimit = concurrencyLimit(user) logging.debug( this, - s"namespace = ${user.uuid.asString}, concurrent activations = $concurrentActivations, below limit = $currentLimit") + s"namespace = ${user.namespace.uuid.asString}, concurrent activations = $concurrentActivations, below limit = $currentLimit") ConcurrentRateLimit(concurrentActivations, currentLimit) } } diff --git a/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala b/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala index 031c267..eaf08e9 100644 --- a/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala +++ b/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala @@ -287,7 +287,7 @@ protected[core] abstract class EntitlementProvider( protected def checkPrivilege(user: Identity, right: Privilege, resources: Set[Resource])( implicit transid: TransactionId): Future[Set[(Resource, Boolean)]] = { // check the default namespace first, bypassing additional checks if permitted - val defaultNamespaces = Set(user.namespace.asString) + val defaultNamespaces = Set(user.namespace.name.asString) implicit val es: EntitlementProvider = this Future.sequence { @@ -361,7 +361,7 @@ protected[core] abstract class EntitlementProvider( private def checkThrottleOverload(throttle: Future[RateLimit], user: Identity)( implicit transid: TransactionId): Future[Unit] = { throttle.flatMap { limit => - val userId = user.authkey.uuid + val userId = user.namespace.uuid if (limit.ok) { limit match { case c: ConcurrentRateLimit => { @@ -373,7 +373,7 @@ protected[core] abstract class EntitlementProvider( s"controller${controllerInstance.instance}", metric, user.subject, - user.namespace.toString, + user.namespace.name.toString, userId, metric.typeName)) } @@ -381,7 +381,7 @@ protected[core] abstract class EntitlementProvider( } Future.successful(()) } else { - logging.info(this, s"'${user.namespace}' has exceeded its throttle limit, ${limit.errorMsg}") + logging.info(this, s"'${user.namespace.name}' has exceeded its throttle limit, ${limit.errorMsg}") val metric = Metric(limit.limitName, 1) UserEvents.send( eventProducer, @@ -389,7 +389,7 @@ protected[core] abstract class EntitlementProvider( s"controller${controllerInstance.instance}", metric, user.subject, - user.namespace.toString, + user.namespace.name.toString, userId, metric.typeName)) Future.failed(RejectRequest(TooManyRequests, limit.errorMsg)) diff --git a/core/controller/src/main/scala/whisk/core/entitlement/RateThrottler.scala b/core/controller/src/main/scala/whisk/core/entitlement/RateThrottler.scala index 9ce7216..527b699 100644 --- a/core/controller/src/main/scala/whisk/core/entitlement/RateThrottler.scala +++ b/core/controller/src/main/scala/whisk/core/entitlement/RateThrottler.scala @@ -45,7 +45,7 @@ class RateThrottler(description: String, maxPerMinute: Identity => Int)(implicit * @return true iff subject namespace is below allowed limit */ def check(user: Identity)(implicit transid: TransactionId): RateLimit = { - val uuid = user.uuid // this is namespace identifier + val uuid = user.namespace.uuid // this is namespace identifier val throttle = rateMap.getOrElseUpdate(uuid, new RateInfo) val limit = maxPerMinute(user) val rate = TimedRateLimit(throttle.update(limit), limit) diff --git a/core/controller/src/main/scala/whisk/core/loadBalancer/InvokerSupervision.scala b/core/controller/src/main/scala/whisk/core/loadBalancer/InvokerSupervision.scala index e33845e..152f555 100644 --- a/core/controller/src/main/scala/whisk/core/loadBalancer/InvokerSupervision.scala +++ b/core/controller/src/main/scala/whisk/core/loadBalancer/InvokerSupervision.scala @@ -221,13 +221,14 @@ object InvokerPool { /** A stub identity for invoking the test action. This does not need to be a valid identity. */ val healthActionIdentity = { val whiskSystem = "whisk.system" - Identity(Subject(whiskSystem), EntityName(whiskSystem), AuthKey(UUID(), Secret()), Set[Privilege]()) + val uuid = UUID() + Identity(Subject(whiskSystem), Namespace(EntityName(whiskSystem), uuid), AuthKey(uuid, Secret()), Set[Privilege]()) } /** An action to use for monitoring invoker health. */ def healthAction(i: InstanceId) = ExecManifest.runtimesManifest.resolveDefaultRuntime("nodejs:6").map { manifest => new WhiskAction( - namespace = healthActionIdentity.namespace.toPath, + namespace = healthActionIdentity.namespace.name.toPath, name = EntityName(s"invokerHealthTestAction${i.toInt}"), exec = CodeExecAsString(manifest, """function main(params) { return params; }""", None)) } diff --git a/core/controller/src/main/scala/whisk/core/loadBalancer/ShardingContainerPoolBalancer.scala b/core/controller/src/main/scala/whisk/core/loadBalancer/ShardingContainerPoolBalancer.scala index 7e817e7..eb95936 100644 --- a/core/controller/src/main/scala/whisk/core/loadBalancer/ShardingContainerPoolBalancer.scala +++ b/core/controller/src/main/scala/whisk/core/loadBalancer/ShardingContainerPoolBalancer.scala @@ -138,7 +138,7 @@ class ShardingContainerPoolBalancer(config: WhiskConfig, controllerInstance: Ins if (!action.exec.pull) (schedulingState.managedInvokers, schedulingState.managedStepSizes) else (schedulingState.blackboxInvokers, schedulingState.blackboxStepSizes) val chosen = if (invokersToUse.nonEmpty) { - val hash = ShardingContainerPoolBalancer.generateHash(msg.user.namespace, action.fullyQualifiedName(false)) + val hash = ShardingContainerPoolBalancer.generateHash(msg.user.namespace.name, action.fullyQualifiedName(false)) val homeInvoker = hash % invokersToUse.size val stepSize = stepSizes(hash % stepSizes.size) ShardingContainerPoolBalancer.schedule(invokersToUse, schedulingState.invokerSlots, homeInvoker, stepSize) @@ -162,7 +162,7 @@ class ShardingContainerPoolBalancer(config: WhiskConfig, controllerInstance: Ins instance: InstanceId): ActivationEntry = { totalActivations.increment() - activationsPerNamespace.getOrElseUpdate(msg.user.uuid, new LongAdder()).increment() + activationsPerNamespace.getOrElseUpdate(msg.user.namespace.uuid, new LongAdder()).increment() val timeout = action.limits.timeout.duration.max(TimeLimit.STD_DURATION) + 1.minute // Install a timeout handler for the catastrophic case where an active ack is not received at all @@ -178,7 +178,7 @@ class ShardingContainerPoolBalancer(config: WhiskConfig, controllerInstance: Ins // please note: timeoutHandler.cancel must be called on all non-timeout paths, e.g. Success ActivationEntry( msg.activationId, - msg.user.uuid, + msg.user.namespace.uuid, instance, timeoutHandler, Promise[Either[ActivationId, WhiskActivation]]()) diff --git a/core/invoker/src/main/scala/whisk/core/containerpool/ContainerPool.scala b/core/invoker/src/main/scala/whisk/core/containerpool/ContainerPool.scala index d26ebdc..90f5d73 100644 --- a/core/invoker/src/main/scala/whisk/core/containerpool/ContainerPool.scala +++ b/core/invoker/src/main/scala/whisk/core/containerpool/ContainerPool.scala @@ -95,7 +95,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef, // Schedule a job to a warm container ContainerPool - .schedule(r.action, r.msg.user.namespace, freePool) + .schedule(r.action, r.msg.user.namespace.name, freePool) .map(container => { (container, "warm") }) @@ -141,7 +141,7 @@ class ContainerPool(childFactory: ActorRefFactory => ActorRef, this, s"Rescheduling Run message, too many message in the pool, freePoolSize: ${freePool.size}, " + s"busyPoolSize: ${busyPool.size}, maxActiveContainers ${poolConfig.maxActiveContainers}, " + - s"userNamespace: ${r.msg.user.namespace}, action: ${r.action}")(r.msg.transid) + s"userNamespace: ${r.msg.user.namespace.name}, action: ${r.action}")(r.msg.transid) Some(logMessageInterval.fromNow) } else { r.retryLogDeadline diff --git a/core/invoker/src/main/scala/whisk/core/containerpool/ContainerProxy.scala b/core/invoker/src/main/scala/whisk/core/containerpool/ContainerProxy.scala index b75ad72..0a7c1ac 100644 --- a/core/invoker/src/main/scala/whisk/core/containerpool/ContainerProxy.scala +++ b/core/invoker/src/main/scala/whisk/core/containerpool/ContainerProxy.scala @@ -132,7 +132,7 @@ class ContainerProxy( // create a new container val container = factory( job.msg.transid, - ContainerProxy.containerName(instance, job.msg.user.namespace.name, job.action.name.name), + ContainerProxy.containerName(instance, job.msg.user.namespace.name.asString, job.action.name.asString), job.action.exec.image, job.action.exec.pull, job.action.limits.memory.megabytes.MB, @@ -161,13 +161,18 @@ class ContainerProxy( // implicitly via a FailureMessage which will be processed later when the state // transitions to Running val activation = ContainerProxy.constructWhiskActivation(job, None, Interval.zero, response) - sendActiveAck(transid, activation, job.msg.blocking, job.msg.rootControllerIndex, job.msg.user.authkey.uuid) + sendActiveAck( + transid, + activation, + job.msg.blocking, + job.msg.rootControllerIndex, + job.msg.user.namespace.uuid) storeActivation(transid, activation) } .flatMap { container => // now attempt to inject the user code and run the action initializeAndRun(container, job) - .map(_ => WarmedData(container, job.msg.user.namespace, job.action, Instant.now)) + .map(_ => WarmedData(container, job.msg.user.namespace.name, job.action, Instant.now)) } .pipeTo(self) @@ -192,7 +197,7 @@ class ContainerProxy( case Event(job: Run, data: PreWarmedData) => implicit val transid = job.msg.transid initializeAndRun(data.container, job) - .map(_ => WarmedData(data.container, job.msg.user.namespace, job.action, Instant.now)) + .map(_ => WarmedData(data.container, job.msg.user.namespace.name, job.action, Instant.now)) .pipeTo(self) goto(Running) @@ -228,7 +233,7 @@ class ContainerProxy( case Event(job: Run, data: WarmedData) => implicit val transid = job.msg.transid initializeAndRun(data.container, job) - .map(_ => WarmedData(data.container, job.msg.user.namespace, job.action, Instant.now)) + .map(_ => WarmedData(data.container, job.msg.user.namespace.name, job.action, Instant.now)) .pipeTo(self) goto(Running) @@ -261,7 +266,7 @@ class ContainerProxy( self ! job } .flatMap(_ => initializeAndRun(data.container, job)) - .map(_ => WarmedData(data.container, job.msg.user.namespace, job.action, Instant.now)) + .map(_ => WarmedData(data.container, job.msg.user.namespace.name, job.action, Instant.now)) .pipeTo(self) goto(Running) @@ -351,7 +356,7 @@ class ContainerProxy( val environment = JsObject( "api_key" -> job.msg.user.authkey.compact.toJson, - "namespace" -> job.msg.user.namespace.toJson, + "namespace" -> job.msg.user.namespace.name.toJson, "action_name" -> job.msg.action.qualifiedNameWithLeadingSlash.toJson, "activation_id" -> job.msg.activationId.toString.toJson, // compute deadline on invoker side avoids discrepancies inside container @@ -380,7 +385,8 @@ class ContainerProxy( } // Sending active ack. Entirely asynchronous and not waited upon. - activation.foreach(sendActiveAck(tid, _, job.msg.blocking, job.msg.rootControllerIndex, job.msg.user.authkey.uuid)) + activation.foreach( + sendActiveAck(tid, _, job.msg.blocking, job.msg.rootControllerIndex, job.msg.user.namespace.uuid)) // Adds logs to the raw activation. val activationWithLogs: Future[Either[ActivationLogReadingError, WhiskActivation]] = activation @@ -487,7 +493,7 @@ object ContainerProxy { WhiskActivation( activationId = job.msg.activationId, - namespace = job.msg.user.namespace.toPath, + namespace = job.msg.user.namespace.name.toPath, subject = job.msg.user.subject, cause = job.msg.cause, name = job.action.name, diff --git a/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesInvokerAgentLogStore.scala b/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesInvokerAgentLogStore.scala index 17f8363..ec3d645 100644 --- a/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesInvokerAgentLogStore.scala +++ b/core/invoker/src/main/scala/whisk/core/containerpool/kubernetes/KubernetesInvokerAgentLogStore.scala @@ -51,7 +51,7 @@ class KubernetesInvokerAgentLogStore(system: ActorSystem) extends LogDriverLogSt val sentinelledLogs = action.exec.sentinelledLogs // Add the userId field to every written record, so any background process can properly correlate. - val userIdField = Map("namespaceId" -> user.authkey.uuid.toJson) + val userIdField = Map("namespaceId" -> user.namespace.uuid.toJson) val additionalMetadata = Map( "activationId" -> activation.activationId.asString.toJson, diff --git a/core/invoker/src/main/scala/whisk/core/invoker/InvokerReactive.scala b/core/invoker/src/main/scala/whisk/core/invoker/InvokerReactive.scala index 4d28382..4ad6bbf 100644 --- a/core/invoker/src/main/scala/whisk/core/invoker/InvokerReactive.scala +++ b/core/invoker/src/main/scala/whisk/core/invoker/InvokerReactive.scala @@ -234,7 +234,7 @@ class InvokerReactive( val activation = generateFallbackActivation(msg, response) activationFeed ! MessageFeed.Processed - ack(msg.transid, activation, msg.blocking, msg.rootControllerIndex, msg.user.authkey.uuid) + ack(msg.transid, activation, msg.blocking, msg.rootControllerIndex, msg.user.namespace.uuid) store(msg.transid, activation) Future.successful(()) } @@ -244,8 +244,8 @@ class InvokerReactive( activationFeed ! MessageFeed.Processed val activation = generateFallbackActivation(msg, ActivationResponse.applicationError(Messages.namespacesBlacklisted)) - ack(msg.transid, activation, false, msg.rootControllerIndex, msg.user.authkey.uuid) - logging.warn(this, s"namespace ${msg.user.namespace} was blocked in invoker.") + ack(msg.transid, activation, false, msg.rootControllerIndex, msg.user.namespace.uuid) + logging.warn(this, s"namespace ${msg.user.namespace.name} was blocked in invoker.") Future.successful(()) } } @@ -268,7 +268,7 @@ class InvokerReactive( WhiskActivation( activationId = msg.activationId, - namespace = msg.user.namespace.toPath, + namespace = msg.user.namespace.name.toPath, subject = msg.user.subject, cause = msg.cause, name = msg.action.name, diff --git a/core/invoker/src/main/scala/whisk/core/invoker/NamespaceBlacklist.scala b/core/invoker/src/main/scala/whisk/core/invoker/NamespaceBlacklist.scala index 4f4336e..5da3407 100644 --- a/core/invoker/src/main/scala/whisk/core/invoker/NamespaceBlacklist.scala +++ b/core/invoker/src/main/scala/whisk/core/invoker/NamespaceBlacklist.scala @@ -44,7 +44,7 @@ class NamespaceBlacklist(authStore: AuthStore) { * @param identity which invoked the action. * @return whether or not the current identity is considered blacklisted */ - def isBlacklisted(identity: Identity): Boolean = blacklist.contains(identity.namespace.name) + def isBlacklisted(identity: Identity): Boolean = blacklist.contains(identity.namespace.name.asString) /** Refreshes the current blacklist from the database. */ def refreshBlacklist()(implicit ec: ExecutionContext, tid: TransactionId): Future[Set[String]] = { diff --git a/tests/src/test/scala/whisk/core/containerpool/logging/ElasticSearchLogStoreTests.scala b/tests/src/test/scala/whisk/core/containerpool/logging/ElasticSearchLogStoreTests.scala index ebd8c8c..7ed3910 100644 --- a/tests/src/test/scala/whisk/core/containerpool/logging/ElasticSearchLogStoreTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/logging/ElasticSearchLogStoreTests.scala @@ -52,7 +52,8 @@ class ElasticSearchLogStoreTests implicit val ec: ExecutionContext = system.dispatcher implicit val materializer: ActorMaterializer = ActorMaterializer() - private val user = Identity(Subject(), EntityName("testSpace"), AuthKey(), Set()) + private val uuid = UUID() + private val user = Identity(Subject(), Namespace(EntityName("testSpace"), uuid), AuthKey(uuid, Secret()), Set()) private val activationId = ActivationId.generate() private val defaultLogSchema = @@ -166,7 +167,7 @@ class ElasticSearchLogStoreTests ElasticSearchLogStoreConfig("https", "host", 443, "/elasticsearch/logstash-%s*/_search", defaultLogSchema) val httpRequest = HttpRequest( POST, - Uri(s"/elasticsearch/logstash-${user.uuid.asString}*/_search"), + Uri(s"/elasticsearch/logstash-${user.namespace.uuid.asString}*/_search"), List(Accept(MediaTypes.`application/json`)), HttpEntity(ContentTypes.`application/json`, defaultPayload)) val esLogStore = new ElasticSearchLogStore( diff --git a/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala b/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala index d77f610..a087a86 100644 --- a/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala @@ -68,7 +68,8 @@ class SplunkLogStoreTests val startTime = "2007-12-03T10:15:30Z" val endTime = "2007-12-03T10:15:45Z" val endTimePlus5 = "2007-12-03T10:15:50Z" //queried end time range is endTime+5 - val user = Identity(Subject(), EntityName("testSpace"), AuthKey(), Set()) + val uuid = UUID() + val user = Identity(Subject(), Namespace(EntityName("testSpace"), uuid), AuthKey(uuid, Secret()), Set()) val request = HttpRequest( method = POST, uri = "https://some.url", diff --git a/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationFileLogStoreTests.scala b/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationFileLogStoreTests.scala index 6f80a92..e539eeb 100644 --- a/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationFileLogStoreTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationFileLogStoreTests.scala @@ -57,7 +57,7 @@ class DockerToActivationFileLogStoreTests } def toLoggedActivation(activation: WhiskActivation): String = { - JsObject(activation.toJson.fields ++ Map("namespaceId" -> user.authkey.uuid.asString.toJson)).compactPrint + "\n" + JsObject(activation.toJson.fields ++ Map("namespaceId" -> user.namespace.uuid.asString.toJson)).compactPrint + "\n" } behavior of "DockerCouchDbFileLogStore" @@ -77,7 +77,7 @@ class DockerToActivationFileLogStoreTests await(collected) shouldBe ActivationLogs(logs.map(_.toFormattedString).toVector) logs.foreach { line => testActor.expectMsg( - toLoggedEvent(line, user.authkey.uuid, activation.activationId, action.fullyQualifiedName(false))) + toLoggedEvent(line, user.namespace.uuid, activation.activationId, action.fullyQualifiedName(false))) } // Last message should be the full activation diff --git a/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationLogStoreTests.scala b/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationLogStoreTests.scala index ae5249e..4df8bde 100644 --- a/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationLogStoreTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/logging/test/DockerToActivationLogStoreTests.scala @@ -40,12 +40,13 @@ import scala.concurrent.duration._ class DockerToActivationLogStoreTests extends FlatSpec with Matchers with WskActorSystem with StreamLogging { def await[T](future: Future[T]) = Await.result(future, 1.minute) - val user = Identity(Subject(), EntityName("testSpace"), AuthKey(), Set()) + val uuid = UUID() + val user = Identity(Subject(), Namespace(EntityName("testSpace"), uuid), AuthKey(uuid, Secret()), Set()) val exec = CodeExecAsString(RuntimeManifest("actionKind", ImageName("testImage")), "testCode", None) - val action = ExecutableWhiskAction(user.namespace.toPath, EntityName("actionName"), exec) + val action = ExecutableWhiskAction(user.namespace.name.toPath, EntityName("actionName"), exec) val activation = WhiskActivation( - user.namespace.toPath, + user.namespace.name.toPath, action.name, user.subject, ActivationId.generate(), diff --git a/tests/src/test/scala/whisk/core/containerpool/test/ContainerPoolTests.scala b/tests/src/test/scala/whisk/core/containerpool/test/ContainerPoolTests.scala index 3fe1253..46f4559 100644 --- a/tests/src/test/scala/whisk/core/containerpool/test/ContainerPoolTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/test/ContainerPoolTests.scala @@ -71,11 +71,12 @@ class ContainerPoolTests /** Creates a `Run` message */ def createRunMessage(action: ExecutableWhiskAction, invocationNamespace: EntityName) = { + val uuid = UUID() val message = ActivationMessage( TransactionId.testing, action.fullyQualifiedName(true), action.rev, - Identity(Subject(), invocationNamespace, AuthKey(), Set()), + Identity(Subject(), Namespace(invocationNamespace, uuid), AuthKey(uuid, Secret()), Set()), ActivationId.generate(), InstanceId(0), blocking = false, diff --git a/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala b/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala index 205834e..8bbf806 100644 --- a/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/test/ContainerProxyTests.scala @@ -79,11 +79,13 @@ class ContainerProxyTests Interval(now, now.plusMillis(200)) } + val uuid = UUID() + val message = ActivationMessage( messageTransId, action.fullyQualifiedName(true), action.rev, - Identity(Subject(), invocationNamespace, AuthKey(), Set()), + Identity(Subject(), Namespace(invocationNamespace, uuid), AuthKey(uuid, Secret()), Set()), ActivationId.generate(), InstanceId(0), blocking = false, @@ -760,7 +762,7 @@ class ContainerProxyTests implicit transid: TransactionId): Future[(Interval, ActivationResponse)] = { runCount += 1 environment.fields("api_key") shouldBe message.user.authkey.toJson - environment.fields("namespace") shouldBe invocationNamespace.toJson + environment.fields("namespace") shouldBe invocationNamespace.name.toJson environment.fields("action_name") shouldBe message.action.qualifiedNameWithLeadingSlash.toJson environment.fields("activation_id") shouldBe message.activationId.toJson val deadline = Instant.ofEpochMilli(environment.fields("deadline").convertTo[String].toLong) diff --git a/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala b/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala index 3c4628b..8a6d254 100644 --- a/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala @@ -48,9 +48,12 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate { implicit val tid = transid() val subject = Subject() + val uuid1 = UUID() + val uuid2 = UUID() + val namespaces = Set( - WhiskNamespace(MakeName.next("authenticatev_tests"), AuthKey()), - WhiskNamespace(MakeName.next("authenticatev_tests"), AuthKey())) + WhiskNamespace(Namespace(MakeName.next("authenticatev_tests"), uuid1), AuthKey(uuid1, Secret())), + WhiskNamespace(Namespace(MakeName.next("authenticatev_tests"), uuid2), AuthKey(uuid2, Secret()))) val entry = WhiskAuth(subject, namespaces) put(authStore, entry) // this test entry is reclaimed when the test completes @@ -60,7 +63,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate { waitOnView(authStore, ns.authkey, 1) // wait for the view to be updated val pass = BasicHttpCredentials(ns.authkey.uuid.asString, ns.authkey.key.asString) val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout) - user.get shouldBe Identity(subject, ns.name, ns.authkey, Privilege.ALL) + user.get shouldBe Identity(subject, ns.namespace, ns.authkey, Privilege.ALL) // first lookup should have been from datastore stream.toString should include(s"serving from datastore: ${CacheKey(ns.authkey)}") @@ -68,7 +71,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate { // repeat query, now should be served from cache val cachedUser = Await.result(validateCredentials(Some(pass))(transid()), dbOpTimeout) - cachedUser.get shouldBe Identity(subject, ns.name, ns.authkey, Privilege.ALL) + cachedUser.get shouldBe Identity(subject, ns.namespace, ns.authkey, Privilege.ALL) stream.toString should include(s"serving from cache: ${CacheKey(ns.authkey)}") stream.reset() diff --git a/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala b/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala index 65e810b..f95c5c0 100644 --- a/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala @@ -58,7 +58,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "authorize a user to only read from their collection" in { implicit val tid = transid() val collections = Seq(ACTIONS, RULES, TRIGGERS, PACKAGES, ACTIVATIONS, NAMESPACES) - val resources = collections map { Resource(someUser.namespace.toPath, _, None) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, None) } resources foreach { r => Await.ready(entitlementProvider.check(someUser, READ, r), requestTimeout).eitherValue.get shouldBe Right({}) @@ -78,9 +78,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { val collections = Seq(ACTIONS, RULES, TRIGGERS, PACKAGES, ACTIVATIONS, NAMESPACES) val resources = collections map { c: Collection => c match { - case RULES => Resource(anotherUser.namespace.toPath, c, None) - case NAMESPACES => Resource(anotherUser.namespace.toPath, c, None) - case _ => Resource(someUser.namespace.toPath, c, None) + case RULES => Resource(anotherUser.namespace.name.toPath, c, None) + case NAMESPACES => Resource(anotherUser.namespace.name.toPath, c, None) + case _ => Resource(someUser.namespace.name.toPath, c, None) } } @@ -92,8 +92,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { resourcesSet.map(r => resourcesList += r) val resourceNames = resourcesList.map(r => r.fqname).sorted.toSet.mkString(", ") val resourceOtherNames = Seq( - Resource(anotherUser.namespace.toPath, RULES, None), - Resource(anotherUser.namespace.toPath, NAMESPACES, None)).map(r => r.fqname).toSet.mkString(", ") + Resource(anotherUser.namespace.name.toPath, RULES, None), + Resource(anotherUser.namespace.name.toPath, NAMESPACES, None)).map(r => r.fqname).toSet.mkString(", ") Await.ready(entitlementProvider.check(someUser, READ, resourcesSet), requestTimeout).eitherValue.get shouldBe Left( RejectRequest(Forbidden, Messages.notAuthorizedtoAccessResource(resourceOtherNames))) @@ -116,7 +116,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "not authorize a user to list someone else's collection or access it by other other right" in { implicit val tid = transid() val collections = Seq(ACTIONS, RULES, TRIGGERS, PACKAGES, ACTIVATIONS, NAMESPACES) - val resources = collections map { Resource(someUser.namespace.toPath, _, None) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, None) } resources foreach { r => // it is permissible to list packages in any namespace (provided they are either owned by // the subject requesting access or the packages are public); that is, the entitlement is more @@ -143,7 +143,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() // packages are tested separately val collections = Seq(ACTIONS, RULES, TRIGGERS) - val resources = collections map { Resource(someUser.namespace.toPath, _, Some("xyz")) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, Some("xyz")) } resources foreach { r => Await.ready(entitlementProvider.check(someUser, READ, r), requestTimeout).eitherValue.get shouldBe Right({}) Await.ready(entitlementProvider.check(someUser, PUT, r), requestTimeout).eitherValue.get shouldBe Right({}) @@ -155,9 +155,11 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "not authorize a user to CRUD an entity in a collection if authkey has no CRUD rights" in { implicit val tid = transid() val subject = Subject() - val someUser = Identity(subject, EntityName(subject.asString), AuthKey(), Set(Privilege.ACTIVATE)) + val uuid = UUID() + val someUser = + Identity(subject, Namespace(EntityName(subject.asString), uuid), AuthKey(uuid, Secret()), Set(Privilege.ACTIVATE)) val collections = Seq(ACTIONS, RULES, TRIGGERS) - val resources = collections map { Resource(someUser.namespace.toPath, _, Some("xyz")) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, Some("xyz")) } resources foreach { r => Await.ready(entitlementProvider.check(someUser, READ, r), requestTimeout).eitherValue.get shouldBe Left( RejectRequest(Forbidden, Messages.notAuthorizedtoAccessResource(r.fqname))) @@ -172,7 +174,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "not authorize a user to CRUD or activate an entity in a collection that does not support CRUD or activate" in { implicit val tid = transid() val collections = Seq(NAMESPACES, ACTIVATIONS) - val resources = collections map { Resource(someUser.namespace.toPath, _, Some("xyz")) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, Some("xyz")) } resources foreach { r => Await.ready(entitlementProvider.check(someUser, READ, r), requestTimeout).eitherValue.get shouldBe Right({}) Await.ready(entitlementProvider.check(someUser, PUT, r), requestTimeout).eitherValue.get shouldBe Left( @@ -187,7 +189,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "not authorize a user to CRUD or activate an entity in someone else's collection" in { implicit val tid = transid() val collections = Seq(ACTIONS, RULES, TRIGGERS, PACKAGES) - val resources = collections map { Resource(someUser.namespace.toPath, _, Some("xyz")) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, Some("xyz")) } resources foreach { r => Await.ready(entitlementProvider.check(guestUser, READ, r), requestTimeout).eitherValue.get shouldBe Left( RejectRequest(Forbidden, Messages.notAuthorizedtoAccessResource(r.fqname))) @@ -203,7 +205,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "authorize a user to list, create/update/delete a package" in { implicit val tid = transid() val collections = Seq(PACKAGES) - val resources = collections map { Resource(someUser.namespace.toPath, _, Some("xyz")) } + val resources = collections map { Resource(someUser.namespace.name.toPath, _, Some("xyz")) } resources foreach { r => // read should fail because the lookup for the package will fail Await.ready(entitlementProvider.check(someUser, READ, r), requestTimeout).eitherValue.get shouldBe Left( @@ -219,8 +221,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "grant access to entire collection to another user" in { implicit val tid = transid() - val all = Resource(someUser.namespace.toPath, ACTIONS, None) - val one = Resource(someUser.namespace.toPath, ACTIONS, Some("xyz")) + val all = Resource(someUser.namespace.name.toPath, ACTIONS, None) + val one = Resource(someUser.namespace.name.toPath, ACTIONS, Some("xyz")) Await.ready(entitlementProvider.check(adminUser, READ, all), requestTimeout).eitherValue.get should not be Right({}) Await.ready(entitlementProvider.check(adminUser, READ, one), requestTimeout).eitherValue.get should not be Right({}) Await.result(entitlementProvider.grant(adminUser.subject, READ, all), requestTimeout) // granted @@ -231,8 +233,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { it should "grant access to specific resource to a user" in { implicit val tid = transid() - val all = Resource(someUser.namespace.toPath, ACTIONS, None) - val one = Resource(someUser.namespace.toPath, ACTIONS, Some("xyz")) + val all = Resource(someUser.namespace.name.toPath, ACTIONS, None) + val one = Resource(someUser.namespace.name.toPath, ACTIONS, Some("xyz")) Await.ready(entitlementProvider.check(adminUser, READ, all), requestTimeout).eitherValue.get should not be Right({}) Await.ready(entitlementProvider.check(adminUser, READ, one), requestTimeout).eitherValue.get should not be Right({}) Await @@ -271,11 +273,11 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, // any user can list any namespace packages // (because this performs a db view lookup which is later filtered) - Resource(someUser.namespace.toPath, PACKAGES, None)) + Resource(someUser.namespace.name.toPath, PACKAGES, None)) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -300,9 +302,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(someUser.namespace.toPath, PACKAGES, Some("xyz"))) + Resource(someUser.namespace.name.toPath, PACKAGES, Some("xyz"))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -324,15 +326,15 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { (REJECT, guestUser, Right(false))) // this forces a doc mismatch error - val action = WhiskAction(someUser.namespace.toPath, MakeName.next(), jsDefault("")) + val action = WhiskAction(someUser.namespace.name.toPath, MakeName.next(), jsDefault("")) put(entityStore, action) paths foreach { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(someUser.namespace.toPath, PACKAGES, Some(action.name.asString))) + Resource(someUser.namespace.name.toPath, PACKAGES, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -341,7 +343,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() implicit val ep = entitlementProvider - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next()) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next()) put(entityStore, provider) val paths = Seq( @@ -360,9 +362,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(someUser.namespace.toPath, PACKAGES, Some(provider.name.asString))) + Resource(someUser.namespace.name.toPath, PACKAGES, Some(provider.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -372,8 +374,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val ep = entitlementProvider // simulate entitlement change on package for which binding was once entitled - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next()) - val binding = WhiskPackage(guestUser.namespace.toPath, MakeName.next(), provider.bind) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next()) + val binding = WhiskPackage(guestUser.namespace.name.toPath, MakeName.next(), provider.bind) put(entityStore, provider, false) put(entityStore, binding) @@ -393,9 +395,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(guestUser.namespace.toPath, PACKAGES, Some(binding.name.asString))) + Resource(guestUser.namespace.name.toPath, PACKAGES, Some(binding.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } @@ -405,9 +407,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(guestUser.namespace.toPath, PACKAGES, Some(binding.name.asString))) + Resource(guestUser.namespace.name.toPath, PACKAGES, Some(binding.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -417,8 +419,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val ep = entitlementProvider // simulate entitlement change on package for which binding was once entitled - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = true) - val binding = WhiskPackage(guestUser.namespace.toPath, MakeName.next(), provider.bind, publish = true) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = true) + val binding = WhiskPackage(guestUser.namespace.name.toPath, MakeName.next(), provider.bind, publish = true) put(entityStore, provider) put(entityStore, binding) @@ -438,9 +440,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(guestUser.namespace.toPath, PACKAGES, Some(binding.name.asString))) + Resource(guestUser.namespace.name.toPath, PACKAGES, Some(binding.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -449,8 +451,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() implicit val ep = entitlementProvider - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = true) - val binding = WhiskPackage(guestUser.namespace.toPath, MakeName.next(), provider.bind) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = true) + val binding = WhiskPackage(guestUser.namespace.name.toPath, MakeName.next(), provider.bind) put(entityStore, provider) put(entityStore, binding) @@ -470,9 +472,9 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new PackageCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, - Resource(guestUser.namespace.toPath, PACKAGES, Some(binding.name.asString))) + Resource(guestUser.namespace.name.toPath, PACKAGES, Some(binding.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -499,11 +501,11 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, // any user can list any namespace packages // (because this performs a db view lookup which is later filtered) - Resource(someUser.namespace.toPath, ACTIONS, None)) + Resource(someUser.namespace.name.toPath, ACTIONS, None)) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected } } @@ -524,7 +526,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { (ACTIVATE, guestUser, Right(true)), (REJECT, guestUser, Right(false))) - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = true) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = true) val action = WhiskAction(provider.fullPath, MakeName.next(), jsDefault("")) put(entityStore, provider) put(entityStore, action) @@ -533,7 +535,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, Resource(action.namespace, ACTIONS, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected @@ -544,7 +546,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() implicit val ep = entitlementProvider - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = false) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = false) val action = WhiskAction(provider.fullPath, MakeName.next(), jsDefault("")) put(entityStore, provider) put(entityStore, action) @@ -567,7 +569,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, Resource(action.namespace, ACTIONS, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected @@ -578,8 +580,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() implicit val ep = entitlementProvider - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = true) - val binding = WhiskPackage(guestUser.namespace.toPath, MakeName.next(), provider.bind) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = true) + val binding = WhiskPackage(guestUser.namespace.name.toPath, MakeName.next(), provider.bind) val action = WhiskAction(binding.fullPath, MakeName.next(), jsDefault("")) put(entityStore, provider) put(entityStore, binding) @@ -603,7 +605,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, Resource(action.namespace, ACTIONS, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected @@ -614,8 +616,8 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { implicit val tid = transid() implicit val ep = entitlementProvider - val provider = WhiskPackage(someUser.namespace.toPath, MakeName.next(), None, publish = false) - val binding = WhiskPackage(guestUser.namespace.toPath, MakeName.next(), provider.bind) + val provider = WhiskPackage(someUser.namespace.name.toPath, MakeName.next(), None, publish = false) + val binding = WhiskPackage(guestUser.namespace.name.toPath, MakeName.next(), provider.bind) val action = WhiskAction(binding.fullPath, MakeName.next(), jsDefault("")) put(entityStore, provider) put(entityStore, binding) @@ -639,7 +641,7 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, Resource(action.namespace, ACTIONS, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected @@ -662,14 +664,14 @@ class EntitlementProviderTests extends ControllerTestCommon with ScalaFutures { (ACTIVATE, guestUser, Right(false)), (REJECT, guestUser, Right(false))) - val action = WhiskAction(someUser.namespace.toPath, MakeName.next(), jsDefault("")) + val action = WhiskAction(someUser.namespace.name.toPath, MakeName.next(), jsDefault("")) put(entityStore, action) paths foreach { case (priv, who, expected) => val check = new ActionCollection(entityStore).implicitRights( who, - Set(who.namespace.asString), + Set(who.namespace.name.asString), priv, Resource(action.namespace, ACTIONS, Some(action.name.asString))) Await.ready(check, requestTimeout).eitherValue.get shouldBe expected diff --git a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala index 9e48eed..890cee7 100644 --- a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala @@ -264,7 +264,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi { waitOnView(entityStore, WhiskPackage, namespaces(0), 1) waitOnView(entityStore, WhiskPackage, namespaces(1), 1) waitOnView(entityStore, WhiskPackage, namespaces(2), 1) - val expected = providers filter (_.namespace == creds.namespace.toPath) + val expected = providers filter (_.namespace == creds.namespace.name.toPath) Get(s"$collectionPath?public=true") ~> Route.seal(routes(creds)) ~> check { status should be(OK) diff --git a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala index 7f8cde0..c54797b 100644 --- a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala +++ b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala @@ -121,9 +121,11 @@ class WebActionsApiTests extends FlatSpec with Matchers with WebActionsApiBaseTe } trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEach with WhiskWebActionsApi { + val uuid = UUID() val systemId = Subject() - val systemKey = AuthKey() - val systemIdentity = Future.successful(Identity(systemId, EntityName(systemId.asString), systemKey, Privilege.ALL)) + val systemKey = AuthKey(uuid, Secret()) + val systemIdentity = + Future.successful(Identity(systemId, Namespace(EntityName(systemId.asString), uuid), systemKey, Privilege.ALL)) override lazy val entitlementProvider = new TestingEntitlementProvider(whiskConfig, loadBalancer) protected val testRoutePath = webInvokePathSegments.mkString("/", "/", "") @@ -404,7 +406,10 @@ trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEac "pkg" -> s"$systemId/proxy".toJson, "action" -> "export_auth".toJson, "content" -> metaPayload(m.method.name.toLowerCase, JsObject(), creds, pkgName = "proxy")) - response.fields("content").asJsObject.fields(webApiDirectives.namespace) shouldBe user.namespace.toJson + response + .fields("content") + .asJsObject + .fields(webApiDirectives.namespace) shouldBe user.namespace.name.toJson } } else { m(s"$testRoutePath/${path}.json") ~> Route.seal(routes(creds)) ~> check { @@ -429,7 +434,10 @@ trait WebActionsApiBaseTests extends ControllerTestCommon with BeforeAndAfterEac creds, pkgName = "proxy", headers = List(RawHeader("X-Require-Whisk-Auth", requireAuthenticationKey)))) - response.fields("content").asJsObject.fields(webApiDirectives.namespace) shouldBe user.namespace.toJson + response + .fields("content") + .asJsObject + .fields(webApiDirectives.namespace) shouldBe user.namespace.name.toJson } // web action require-whisk-auth is set, but the header X-Require-Whisk-Auth value does not match diff --git a/tests/src/test/scala/whisk/core/controller/test/WhiskAuthHelpers.scala b/tests/src/test/scala/whisk/core/controller/test/WhiskAuthHelpers.scala index 1c356bf..7d21aee 100644 --- a/tests/src/test/scala/whisk/core/controller/test/WhiskAuthHelpers.scala +++ b/tests/src/test/scala/whisk/core/controller/test/WhiskAuthHelpers.scala @@ -24,13 +24,14 @@ import whisk.core.entity.WhiskAuth import whisk.core.entity.Subject import whisk.core.entitlement.Privilege import whisk.core.entity.Identity +import whisk.core.entity.Namespace object WhiskAuthHelpers { def newAuth(s: Subject = Subject(), k: AuthKey = AuthKey()) = { - WhiskAuth(s, Set(WhiskNamespace(EntityName(s.asString), k))) + WhiskAuth(s, Set(WhiskNamespace(Namespace(EntityName(s.asString), k.uuid), k))) } def newIdentity(s: Subject = Subject(), k: AuthKey = AuthKey()) = { - Identity(s, EntityName(s.asString), k, Privilege.ALL) + Identity(s, Namespace(EntityName(s.asString), k.uuid), k, Privilege.ALL) } } diff --git a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala index 239bbfc..96824ea 100644 --- a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala +++ b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreBehaviorBase.scala @@ -108,7 +108,8 @@ trait ArtifactStoreBehaviorBase } protected def wskNS(name: String) = { - WhiskNamespace(EntityName(name), AuthKey()) + val uuid = UUID() + WhiskNamespace(Namespace(EntityName(name), uuid), AuthKey(uuid, Secret())) } private val exec = BlackBoxExec(ExecManifest.ImageName("image"), None, None, native = false) diff --git a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala index ce78397..ace1955 100644 --- a/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala +++ b/tests/src/test/scala/whisk/core/database/test/behavior/ArtifactStoreSubjectQueryBehaviors.scala @@ -33,10 +33,12 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { it should "find subject by namespace" in { implicit val tid: TransactionId = transid() - val ak1 = AuthKey() - val ak2 = AuthKey() - val ns1 = aname() - val ns2 = aname() + val uuid1 = UUID() + val uuid2 = UUID() + val ak1 = AuthKey(uuid1, Secret()) + val ak2 = AuthKey(uuid2, Secret()) + val ns1 = Namespace(aname(), uuid1) + val ns2 = Namespace(aname(), uuid2) val subs = Array(WhiskAuth(Subject(), Set(WhiskNamespace(ns1, ak1))), WhiskAuth(Subject(), Set(WhiskNamespace(ns2, ak2)))) subs foreach (put(authStore, _)) @@ -44,7 +46,7 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { waitOnView(authStore, ak1, 1) waitOnView(authStore, ak2, 1) - val s1 = Identity.get(authStore, ns1).futureValue + val s1 = Identity.get(authStore, ns1.name).futureValue s1.subject shouldBe subs(0).subject val s2 = Identity.get(authStore, ak2).futureValue @@ -53,20 +55,23 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { it should "not get blocked subject" in { implicit val tid: TransactionId = transid() - val ns1 = aname() + val uuid1 = UUID() + val ns1 = Namespace(aname(), uuid1) val ak1 = AuthKey() val auth = new ExtendedAuth(Subject(), Set(WhiskNamespace(ns1, ak1)), blocked = true) put(authStore, auth) - Identity.get(authStore, ns1).failed.futureValue shouldBe a[NoDocumentException] + Identity.get(authStore, ns1.name).failed.futureValue shouldBe a[NoDocumentException] } it should "not find subject when authKey matches partially" in { implicit val tid: TransactionId = transid() - val ak1 = AuthKey() - val ak2 = AuthKey() - val ns1 = aname() - val ns2 = aname() + val uuid1 = UUID() + val uuid2 = UUID() + val ak1 = AuthKey(uuid1, Secret()) + val ak2 = AuthKey(uuid2, Secret()) + val ns1 = Namespace(aname(), uuid1) + val ns2 = Namespace(aname(), uuid2) val auth = WhiskAuth( Subject(), @@ -80,10 +85,12 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { it should "find subject by namespace with limits" in { implicit val tid: TransactionId = transid() - val ak1 = AuthKey() - val ak2 = AuthKey() - val name1 = aname() - val name2 = aname() + val uuid1 = UUID() + val uuid2 = UUID() + val ak1 = AuthKey(uuid1, Secret()) + val ak2 = AuthKey(uuid2, Secret()) + val name1 = Namespace(aname(), uuid1) + val name2 = Namespace(aname(), uuid2) val subs = Array( WhiskAuth(Subject(), Set(WhiskNamespace(name1, ak1))), WhiskAuth(Subject(), Set(WhiskNamespace(name2, ak2)))) @@ -93,9 +100,9 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { waitOnView(authStore, ak2, 1) val limits = UserLimits(invocationsPerMinute = Some(7), firesPerMinute = Some(31)) - put(authStore, new LimitEntity(name1, limits)) + put(authStore, new LimitEntity(name1.name, limits)) - val i = Identity.get(authStore, name1).futureValue + val i = Identity.get(authStore, name1.name).futureValue i.subject shouldBe subs(0).subject i.limits shouldBe limits } @@ -109,8 +116,10 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { val n4 = aname() val n5 = aname() - val ak1 = AuthKey() - val ak2 = AuthKey() + val uuid1 = UUID() + val uuid2 = UUID() + val ak1 = AuthKey(uuid1, Secret()) + val ak2 = AuthKey(uuid2, Secret()) //Create 3 limits entry where one has limits > 0 thus non blacklisted //And one blocked subject with 2 namespaces @@ -118,7 +127,10 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase { new LimitEntity(n1, UserLimits(invocationsPerMinute = Some(0))), new LimitEntity(n2, UserLimits(concurrentInvocations = Some(0))), new LimitEntity(n3, UserLimits(invocationsPerMinute = Some(7), concurrentInvocations = Some(7))), - new ExtendedAuth(Subject(), Set(WhiskNamespace(n4, ak1), WhiskNamespace(n5, ak2)), blocked = true)) + new ExtendedAuth( + Subject(), + Set(WhiskNamespace(Namespace(n4, uuid1), ak1), WhiskNamespace(Namespace(n5, uuid2), ak2)), + blocked = true)) limitsAndAuths foreach (put(authStore, _)) diff --git a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala index 6ee2b24..05e2f8d 100644 --- a/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala +++ b/tests/src/test/scala/whisk/core/entity/test/SchemaTests.scala @@ -187,6 +187,9 @@ class SchemaTests extends FlatSpec with BeforeAndAfter with ExecHelpers with Mat EntityPath.DEFAULT.resolveNamespace(EntityName("a")) shouldBe EntityPath("a") EntityPath("a").resolveNamespace(EntityName("b")) shouldBe EntityPath("a") + EntityPath.DEFAULT.resolveNamespace(Namespace(EntityName("a"), UUID())) shouldBe EntityPath("a") + EntityPath("a").resolveNamespace(Namespace(EntityName("b"), UUID())) shouldBe EntityPath("a") + EntityPath("a").defaultPackage shouldBe true EntityPath("a/b").defaultPackage shouldBe false diff --git a/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala b/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala index e3bfd85..eb5f74d 100644 --- a/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala +++ b/tests/src/test/scala/whisk/core/invoker/test/NamespaceBlacklistTests.scala @@ -62,32 +62,44 @@ class NamespaceBlacklistTests dbConfig.databaseFor[WhiskAuth]) /* Identities needed for the first test */ + val uuid1 = UUID() + val uuid2 = UUID() + val uuid3 = UUID() val identities = Seq( - Identity(Subject(), EntityName("testnamespace1"), AuthKey(), Set.empty, UserLimits(invocationsPerMinute = Some(0))), Identity( Subject(), - EntityName("testnamespace2"), - AuthKey(), + Namespace(EntityName("testnamespace1"), uuid1), + AuthKey(uuid1, Secret()), + Set.empty, + UserLimits(invocationsPerMinute = Some(0))), + Identity( + Subject(), + Namespace(EntityName("testnamespace2"), uuid2), + AuthKey(uuid2, Secret()), Set.empty, UserLimits(concurrentInvocations = Some(0))), Identity( Subject(), - EntityName("testnamespace3"), - AuthKey(), + Namespace(EntityName("testnamespace3"), uuid3), + AuthKey(uuid3, Secret()), Set.empty, UserLimits(invocationsPerMinute = Some(1), concurrentInvocations = Some(1)))) /* Subject document needed for the second test */ - val subject = WhiskAuth( - Subject(), - Set(WhiskNamespace(EntityName("different1"), AuthKey()), WhiskNamespace(EntityName("different2"), AuthKey()))) + val uuid4 = UUID() + val uuid5 = UUID() + val ak4 = AuthKey(uuid4, Secret()) + val ak5 = AuthKey(uuid5, Secret()) + val ns4 = Namespace(EntityName("different1"), uuid4) + val ns5 = Namespace(EntityName("different2"), uuid5) + val subject = WhiskAuth(Subject(), Set(WhiskNamespace(ns4, ak4), WhiskNamespace(ns5, ak5))) val blockedSubject = JsObject(subject.toJson.fields + ("blocked" -> true.toJson)) val blockedNamespacesCount = 2 + subject.namespaces.size def authToIdentities(auth: WhiskAuth): Set[Identity] = { auth.namespaces.map { ns => - Identity(auth.subject, ns.name, ns.authkey, Set(), UserLimits()) + Identity(auth.subject, ns.namespace, ns.authkey, Set(), UserLimits()) } } diff --git a/tests/src/test/scala/whisk/core/limits/ActionLimitsTests.scala b/tests/src/test/scala/whisk/core/limits/ActionLimitsTests.scala index aa3caf8..77999fb 100644 --- a/tests/src/test/scala/whisk/core/limits/ActionLimitsTests.scala +++ b/tests/src/test/scala/whisk/core/limits/ActionLimitsTests.scala @@ -245,7 +245,7 @@ class ActionLimitsTests extends TestHelpers with WskTestHelpers { val allowedSize = ActivationEntityLimit.MAX_ACTIVATION_ENTITY_LIMIT.toBytes // Needs some bytes grace since activation message is not only the payload. - val args = Map("p" -> ("a" * (allowedSize - 700).toInt).toJson) + val args = Map("p" -> ("a" * (allowedSize - 750).toInt).toJson) val rr = wsk.action.invoke(name, args, blocking = true, expectedExitCode = TestUtils.SUCCESS_EXIT) val activation = wsk.parseJsonString(rr.respData).convertTo[ActivationResult] diff --git a/tests/src/test/scala/whisk/core/loadBalancer/test/InvokerSupervisionTests.scala b/tests/src/test/scala/whisk/core/loadBalancer/test/InvokerSupervisionTests.scala index 6f0d05c..bf0da86 100644 --- a/tests/src/test/scala/whisk/core/loadBalancer/test/InvokerSupervisionTests.scala +++ b/tests/src/test/scala/whisk/core/loadBalancer/test/InvokerSupervisionTests.scala @@ -48,17 +48,7 @@ import whisk.core.WhiskConfig import whisk.core.connector.ActivationMessage import whisk.core.connector.PingMessage import whisk.core.entity.ActivationId.ActivationIdGenerator -import whisk.core.entity.AuthKey -import whisk.core.entity.DocRevision -import whisk.core.entity.EntityName -import whisk.core.entity.EntityPath -import whisk.core.entity.ExecManifest -import whisk.core.entity.FullyQualifiedEntityName -import whisk.core.entity.Identity -import whisk.core.entity.InstanceId -import whisk.core.entity.Secret -import whisk.core.entity.Subject -import whisk.core.entity.UUID +import whisk.core.entity._ import whisk.core.loadBalancer.ActivationRequest import whisk.core.loadBalancer.GetStatus import whisk.core.loadBalancer.Healthy @@ -189,14 +179,15 @@ class InvokerSupervisionTests val supervisor = system.actorOf(InvokerPool.props(childFactory, sendActivationToInvoker, pC)) // Send ActivationMessage to InvokerPool + val uuid = UUID() val activationMessage = ActivationMessage( transid = TransactionId.invokerHealth, action = FullyQualifiedEntityName(EntityPath("whisk.system/utils"), EntityName("date")), revision = DocRevision.empty, user = Identity( Subject("unhealthyInvokerCheck"), - EntityName("unhealthyInvokerCheck"), - AuthKey(UUID(), Secret()), + Namespace(EntityName("unhealthyInvokerCheck"), uuid), + AuthKey(uuid, Secret()), Set[Privilege]()), activationId = new ActivationIdGenerator {}.make(), rootControllerIndex = InstanceId(0), -- To stop receiving notification emails like this one, please contact markusthoem...@apache.org.