Access Based Access Control for Scala.
Provides composable attribute rules to build policies, and utilities for securing effectful operations behind policies.
Very WIP.
libraryDependencies += "io.cardell" %% "abac4s-core" % "@VERSION@"
import cats.effect.IO
import io.cardell.abac4s.Attribute
import io.cardell.abac4s.PolicyResult
import io.cardell.abac4s.dsl._
import io.cardell.abac4s.syntax._
type Token = String
// example function extracting attributes
val tokenAttrs: Token => Set[Attribute.Subject] = _ => Set.empty
val token: IO[Token] = IO.pure("token")
val subjectSource = subject[IO, Token](tokenAttrs)(token)
val subjectPolicy = subjectSource.hasKey("key")
val subjectPolicyResult: IO[PolicyResult[Token]] = subjectPolicy.run()
// composing
case class MyResource()
val fetch: IO[MyResource] = IO.pure(MyResource())
val resourceAttrs: MyResource => Set[Attribute.Resource] = _ => Set.empty
val resourceSource = resource[IO, MyResource](resourceAttrs)(fetch)
val resourcePolicy = resourceSource.contains("key", "value")
val resourcePolicyResult: IO[PolicyResult[MyResource]] = resourcePolicy.run()
val combinedResult: IO[PolicyResult[(Token, MyResource)]] =
(subjectPolicy and resourcePolicy).run()
// matching
// checks the two attribute sources share the same value for a key
// `intersect` means that in case of multiple keys, any intersection of values
// passes the policy
val matchPolicy = (subjectSource matches resourceSource).intersect.onKey("key")
// `unique` means both sources must have a single attribute for that key, and
// they must match
val matchPolicy2 = (subjectSource matches resourceSource).unique.onKey("key")
val matchPolicyResult: IO[PolicyResult[(Token, MyResource)]] = matchPolicy.run()
This software is licensed under the MIT license. See LICENSE
To set up development dependencies use Nix >2.4
with flakes enabled, and use the nix develop
command.