Skip to content

alexcardell/abac4s

Repository files navigation

abac4s

release version

Access Based Access Control for Scala.

Provides composable attribute rules to build policies, and utilities for securing effectful operations behind policies.

Very WIP.

Installing

libraryDependencies += "io.cardell" %% "abac4s-core" % "@VERSION@"

Usage

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()

License

This software is licensed under the MIT license. See LICENSE

Developing

To set up development dependencies use Nix >2.4 with flakes enabled, and use the nix develop command.