Getting Started with Cedarling Go Bindings#
Go bindings for the Jans Cedarling authorization engine, providing policy-based access control.
Installation#
Build with dynamic linking#
-
Download the appropriate pre-built binary for your platform from the Jans releases page or build it from source as described above.
-
Specify linker flags in your main.go file to link against the Cedarling library.
// #cgo LDFLAGS: -L. -lcedarling_go import "C"
And make sure that the Cedarling library files are located in the same directory as your main package.
-
Use
go get
to fetch the Cedarling Go packagego get github.com/JanssenProject/jans/jans-cedarling/bindings/cedarling_go
-
Build your Go application
go build .
-
Run the application
-
Windows
- Place the Rust artifacts (
cedarling_go.dll
andcedarling_go.lib
) alongside the Go binary. - Windows searches libraries in directories below in the
following order
- The directory containing your Go executable (recommended location)
- Windows system directories (e.g.,
C:\Windows\System32
) - The
PATH
environment variable directories
- Place the Rust artifacts (
-
Linux
Add the library directory that contains
libcedarling_go.so
to theLD_LIBRARY_PATH
environment variableexport LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
-
MacOS
Add the library directory that contains
libcedarling_go.dylib
to theLD_LIBRARY_PATH
environment variableexport DYLD_LIBRARY_PATH=$(pwd):$DYLD_LIBRARY_PATH
-
Build from Source#
Follow these instructions to build from source.
Prerequisites#
- Go 1.20+
- Rust tool-chain
Steps to build from source#
-
Build the Rust library
Clone the Janssen repository:
git clone --depth 1 https://github.com/JanssenProject/jans.git
We use
--depth 1
to avoid cloning unnecessary history and minimalize the download size.Navigate to the Cedarling Go bindings directory:
cd jans/jans-cedarling/bindings/cedarling_go
cargo build --release -p cedarling_go
-
Copy the built artifacts to your application directory
# Windows cp target/release/cedarling_go.dll . cp target/release/cedarling_go.dll.lib cedarling_go.lib # Linux cp target/release/libcedarling_go.so . # macOS cp target/release/libcedarling_go.dylib .
or use scripts provided in the repository to automate this process:
sh build_and_copy_artifacts.sh
Run go test to ensure everything is working correctly:
go test .
Usage#
Initialization#
import "github.com/JanssenProject/jans/jans-cedarling/bindings/cedarling_go"
// Example configuration (populate dynamically in production)
config := map[string]any{
"CEDARLING_APPLICATION_NAME": "MyApp",
"CEDARLING_POLICY_STORE_ID": "your-policy-store-id",
"CEDARLING_USER_AUTHZ": "enabled",
"CEDARLING_WORKLOAD_AUTHZ": "enabled",
"CEDARLING_LOG_LEVEL": "INFO",
"CEDARLING_LOG_TYPE": "std_out",
"CEDARLING_POLICY_STORE_LOCAL_FN": "/path/to/policy-store.json",
}
instance, err := cedarling_go.NewCedarling(config)
if err != nil {
panic(err)
}
Authorization#
Cedarling provides two main interfaces for performing authorization checks: Token-Based Authorization and Unsigned Authorization. Both methods involve evaluating access requests based on various factors, including principals (entities), actions, resources, and context. The difference lies in how the Principals are provided.
- Token-Based Authorization is the standard method where principals are extracted from JSON Web Tokens (JWTs), typically used in scenarios where you have existing user authentication and authorization data encapsulated in tokens.
- Unsigned Authorization allows you to pass principals directly, bypassing tokens entirely. This is useful when you need to authorize based on internal application data, or when tokens are not available.
Token-Based Authorization#
1. Define the resource:
resource := cedarling_go.EntityData{
CedarMapping: cedarling_go.CedarMapping{
EntityType: "Jans::Issue",
ID: "random_id",
},
Payload: map[string]any{
"org_id": "some_long_id",
"country": "US",
},
}
2. Define the action:
action := `Jans::Action::"Update"`
3. Build the request with tokens:
request := cedarling_go.Request{
Tokens: map[string]string{
"access_token": "your.jwt.token",
"id_token": "your.id.token",
"userinfo_token": "your.userinfo.token",
},
Action: action,
Resource: resource,
}
4. Authorize:
result, err := instance.Authorize(request)
if err != nil {
// Handle error
}
if result.Decision {
fmt.Println("Access granted")
} else {
fmt.Println("Access denied")
}
Unsigned Authorization#
In unsigned authorization, you pass a set of Principals directly, without relying on tokens. This can be useful when the application needs to perform authorization based on internal data, or when token-based data is not available.
1. Define the principals:
principals := []cedarling_go.EntityData{
{
CedarMapping: cedarling_go.CedarMapping{
EntityType: "Jans::User",
ID: "random_id",
},
Payload: map[string]any{
"role": []string{"admin"},
"country": "US",
"sub": "random_sub",
},
},
}
2. Build the request:
request := cedarling_go.RequestUnsigned{
Principals: principals,
Action: `Jans::Action::"Update"`,
Resource: resource, // From previous example
}
3. Authorize:
result, err := instance.AuthorizeUnsigned(request)
if err != nil {
// Handle error
}
if result.Decision {
fmt.Println("Access granted")
} else {
fmt.Println("Access denied")
}
Logging#
Retrieve logs stored in memory:
// Get all logs and clear the buffer
logs := instance.PopLogs()
// Get a specific log by ID
log := instance.GetLogById("log123")
// Get logs by tag (e.g., "info")
logs := instance.GetLogsByTag("info")
Defined API#
Auto-generated documentation is available on pkg.go.dev.