Skip to content

Repository files navigation

Cerbos Java SDK

Maven Central

Java client library for the Cerbos open source access control solution. This library includes RPC clients for accessing the Cerbos PDP and test utilities for testing your code locally using Testcontainers.

Find out more about Cerbos at https://cerbos.dev and read the documentation at https://docs.cerbos.dev.

Installation

Artifacts are available from Maven Central.

Example: Gradle (Kotlin DSL)

dependencies {
implementation("dev.cerbos:cerbos-sdk-java:0.+")
implementation("io.grpc:grpc-core:1.+")
}
repositories {
mavenCentral()
}

Examples

Note

Connecting to Unix domain sockets using this SDK is only supported on Linux, which is a limitation inherited from the underlying grpc-java library.

Creating a client without TLS

CerbosBlockingClientclient=newCerbosClientBuilder("localhost:3593").withPlaintext().buildBlockingClient();

Check a single principal and resource

CheckResultresult=client.check(
Principal.newInstance("john","employee")
.withPolicyVersion("20210210")
.withAttribute("department",stringValue("marketing"))
.withAttribute("geography",stringValue("GB")),
Resource.newInstance("leave_request","xx125")
.withPolicyVersion("20210210")
.withAttribute("department",stringValue("marketing"))
.withAttribute("geography",stringValue("GB"))
.withAttribute("owner",stringValue("john")),
"view:public","approve");
if(result.isAllowed("approve")){ // returns true if `approve` action is allowed
...
}

Check a batch

CheckResourcesResultresult=client.batch(
Principal.newInstance("john","employee")
.withPolicyVersion("20210210")
.withAttribute("department",stringValue("marketing"))
.withAttribute("geography",stringValue("GB"))
)
.addResources(
ResourceAction.newInstance("leave_request","XX125")
.withPolicyVersion("20210210")
.withAttributes(
Map.of(
"department", stringValue("marketing"),
"geography", stringValue("GB"),
"owner", stringValue("john")
)
)
.withActions("view:public","approve","defer"),
ResourceAction.newInstance("leave_request","XX225")
.withPolicyVersion("20210210")
.withAttributes(
Map.of(
"department", stringValue("marketing"),
"geography", stringValue("GB"),
"owner", stringValue("martha")
)
)
.withActions("view:public","approve"),
ResourceAction.newInstance("leave_request","XX325")
.withPolicyVersion("20210210")
.withAttributes(
Map.of(
"department", stringValue("marketing"),
"geography", stringValue("US"),
"owner", stringValue("peggy")
)
)
.withActions("view:public","approve")
)
.check();
result.find("XX125").map(r->r.isAllowed("view:public")).orElse(false);

Create a query plan

PlanResourcesResultresult = client.plan(
Principal.newInstance("maggie","manager")
.withAttribute("department",stringValue("marketing"))
.withAttribute("geography",stringValue("GB"))
.withAttribute("team",stringValue("design")),
Resource.newInstance("leave_request").withPolicyVersion("20210210"),
"approve"
);
if(result.isAlwaysAllowed()) {
returntrue;
} elseif(result.isAlwaysDenied()) {
returnfalse;
} else {
returnexecuteQuery(result.getCondition());
}

Test with Testcontainers

@ContainerprivatestaticfinalCerbosContainercerbosContainer=newCerbosContainer()
.withClasspathResourceMapping("policies","/policies",BindMode.READ_ONLY)
.withLogConsumer(newSlf4jLogConsumer(LOG));
@BeforeAllprivatevoidinitClient() throwsCerbosClientBuilder.InvalidClientConfigurationException{
Stringtarget=cerbosContainer.getTarget();
this.client=newCerbosClientBuilder(target).withPlaintext().buildBlockingClient();
}

Accessing the Admin API

// Username and password can be specified using CERBOS_USER and CERBOS_PASSWORD environment variables as wellCerbosBlockingAdminClientadminClient = newCerbosClientBuilder(target).withPlaintext().buildBlockingAdminClient("username", "password");
adminClient.addOrUpdatePolicy().with(newFileReader(fileObjectContainingPolicyJSON)).addOrUpdate();

See CerbosBlockingAdminClientTest test class for more examples of Admin API usage including how to convert YAML policies to the JSON format required by the API.

Common issues

java.lang.IllegalArgumentException: cannot find a NameResolver for ...: The gRPC library relies on Java SPI to register name resolvers and client-side load balancing strategies for clients. The defaults are defined in the io.grpc:grpc-core library. Some packaging methods could overwrite or strip out the META-INF/services directory, which would cause the above exception on Cerbos client initialisation. If that's the case, eithertry to recreate the default service bindings in your own jar OR explicitly register the services as follows:

importio.grpc.LoadBalancerRegistry;
importio.grpc.NameResolverRegistry;
publicclassCerbos {
publicstaticvoidmain(String[] args) throwsCerbosClientBuilder.InvalidClientConfigurationException {
LoadBalancerRegistry.getDefaultRegistry().register(newio.grpc.internal.PickFirstLoadBalancerProvider());
NameResolverRegistry.getDefaultRegistry().register(newio.grpc.internal.DnsNameResolverProvider());
CerbosBlockingClientclient = newCerbosClientBuilder("dns:///cerbos.my-ns.svc.cluster.local:3593").withInsecure().buildBlockingClient();
...
}
}

About

Java SDK for interacting with the Cerbos PDP.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages