From d32e048a07e0de527b3fa2bec552bb136fcd9752 Mon Sep 17 00:00:00 2001 From: srost Date: Tue, 26 Sep 2023 15:09:44 +0200 Subject: [PATCH] Blacklist on account level (cont.) --- .../BasicAuthenticationDirective.scala | 48 ++++++++++++++++--- .../core/invoker/NamespaceBlacklist.scala | 3 ++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/core/controller/src/main/scala/org/apache/openwhisk/core/controller/BasicAuthenticationDirective.scala b/core/controller/src/main/scala/org/apache/openwhisk/core/controller/BasicAuthenticationDirective.scala index e666b7fd945..5827aa8a885 100644 --- a/core/controller/src/main/scala/org/apache/openwhisk/core/controller/BasicAuthenticationDirective.scala +++ b/core/controller/src/main/scala/org/apache/openwhisk/core/controller/BasicAuthenticationDirective.scala @@ -37,7 +37,12 @@ import spray.json.JsString object BasicAuthenticationDirective extends AuthenticationDirectiveProvider { + private val allAccounts = sys.env.getOrElse("ALL_ACCOUNTS", "") + private val wlAccountPfx = sys.env.getOrElse("WL_ACCOUNT_PFX", "??") + private val iamNamespaceRegEx = sys.env.getOrElse("IAM_NAMESPACE_REGEX", "") + private val systemUsers = sys.env.getOrElse("SYSTEM_USERS", "").split(",").toList var namespaceBlacklist: Option[NamespaceBlacklist] = None + def getOrCreateBlacklist()(implicit transid: TransactionId, system: ActorSystem, ec: ExecutionContext, @@ -51,14 +56,16 @@ object BasicAuthenticationDirective extends AuthenticationDirectiveProvider { val namespaceBlacklist = new NamespaceBlacklist(authStore) if (!sys.env.get("CONTROLLER_NAME").getOrElse("").equals("crudcontroller")) { logging.info(this, "create background job to update blacklist..") + logging.info( + this, + s"systemUsers: $systemUsers, allAccounts: $allAccounts, wlAccountPfx: $wlAccountPfx, iamNamespaceRegEx: $iamNamespaceRegEx") Scheduler.scheduleWaitAtMost(loadConfigOrThrow[NamespaceBlacklistConfig](ConfigKeys.blacklist).pollInterval) { () => logging.debug(this, "running background job to update blacklist") namespaceBlacklist.refreshBlacklist()(authStore.executionContext, transid).andThen { case Success(set) => { - logging.info( - this, - s"updated blacklist to ${set.size} items (accounts: ${set.filter(i => i matches "[0-9a-z]{32}")})") + logging.info(this, s"updated blacklist to ${set.size} items (accounts: ${set.filter(i => + (i matches "[0-9a-z]{32}") || (i matches wlAccountPfx + ".*"))})") } case Failure(t) => logging.error(this, s"error on updating the blacklist: ${t.getMessage}") } @@ -81,10 +88,23 @@ object BasicAuthenticationDirective extends AuthenticationDirectiveProvider { val authkey = BasicAuthenticationAuthKey(UUID(pw.username), Secret(pw.password)) logging.info(this, s"authenticate: ${authkey.uuid}") val future = Identity.get(authStore, authkey) map { result => + val account = Try(result.authkey.asInstanceOf[BasicAuthenticationAuthKey].account).getOrElse("") val blacklist = getOrCreateBlacklist + val isSystemUser = systemUsers.exists(_.equals(result.subject.asString)) + logging.info( + this, + s"@StR authenticate: account: $account, blacklist: $blacklist, isSystemUser: $isSystemUser, result: ${result.toString}") val identity = - if (!blacklist.isEmpty && blacklist.isBlacklisted( - Try(result.authkey.asInstanceOf[BasicAuthenticationAuthKey].account).getOrElse(""))) { + if (!isSystemUser && blacklist.isBlacklisted(allAccounts) && !blacklist.isBlacklisted( + wlAccountPfx + account)) { + Identity( + subject = result.subject, + namespace = result.namespace, + authkey = result.authkey, + rights = result.rights, + limits = + UserLimits(invocationsPerMinute = Some(0), concurrentInvocations = Some(0), firesPerMinute = Some(0))) + } else if (blacklist.isBlacklisted(account)) { Identity( subject = result.subject, namespace = result.namespace, @@ -142,10 +162,24 @@ object BasicAuthenticationDirective extends AuthenticationDirectiveProvider { //Identity.get(authStore, namespace) implicit val ec = authStore.executionContext implicit val logging = authStore.logging + logging.info(this, s"identify by namespace: $namespace") Identity.get(authStore, namespace) map { result => + val account = Try(result.authkey.asInstanceOf[BasicAuthenticationAuthKey].account).getOrElse("") val blacklist = getOrCreateBlacklist - if (!blacklist.isEmpty && blacklist.isBlacklisted( - Try(result.authkey.asInstanceOf[BasicAuthenticationAuthKey].account).getOrElse(""))) { + val isSystemUser = systemUsers.exists(_.equals(result.subject.asString)) + val isCfNamespace = isSystemUser || !namespace.name.matches(iamNamespaceRegEx) + logging.info( + this, + s"@StR identify by namespace: account: $account, blacklist: ${blacklist.toString}, isSystemUser: $isSystemUser, isCfNamespace: $isCfNamespace, namespace: $namespace, result: $result") + if (!isSystemUser && isCfNamespace && blacklist.isBlacklisted(allAccounts) && !blacklist + .isBlacklisted(wlAccountPfx + account)) { + Identity( + subject = result.subject, + namespace = result.namespace, + authkey = result.authkey, + rights = result.rights, + limits = UserLimits(invocationsPerMinute = Some(0), concurrentInvocations = Some(0), firesPerMinute = Some(0))) + } else if (blacklist.isBlacklisted(account)) { Identity( subject = result.subject, namespace = result.namespace, diff --git a/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/NamespaceBlacklist.scala b/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/NamespaceBlacklist.scala index f650c4f12cd..9b98aed9703 100644 --- a/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/NamespaceBlacklist.scala +++ b/core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/NamespaceBlacklist.scala @@ -81,6 +81,9 @@ class NamespaceBlacklist(authStore: AuthStore) { newBlacklist } } + + /** This is so that we can easily log the blacklist for debugging. */ + override def toString() = blacklist.toString() } object NamespaceBlacklist {