Skip to content

Commit

Permalink
Blacklist on account level (cont.)
Browse files Browse the repository at this point in the history
  • Loading branch information
steffenrost committed Oct 3, 2023
1 parent 7c9ec1b commit 3876f18
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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}")
}
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ trait ArtifactStoreSubjectQueryBehaviors extends ArtifactStoreBehaviorBase {
}

private class ExtendedAuth(subject: Subject, namespaces: Set[WhiskNamespace], blocked: Boolean)
extends WhiskAuth(subject, namespaces) {
extends WhiskAuth(subject, namespaces) {
override def toJson = JsObject(super.toJson.fields + ("blocked" -> JsBoolean(blocked)))
}
}

0 comments on commit 3876f18

Please sign in to comment.