Library / SDK
ory/ladon avatar
ory/ladon

ory/ladon: AWS IAM-style policy authorization as a Go library

A SDK for access control policies: authorization for the microservice and IoT age. Inspired by AWS IAM policies. Written for Go.

2,459 stars224 forksGoApache-2.0

At a glance

What is it?
Ladon is a Go SDK that answers whether a subject may perform an action on a resource, using JSON policy documents modeled on AWS IAM. It ships an in-memory store and leaves the HTTP layer to you.
Who is it for?
Adopt ory/ladon if you are writing Go services that need policy evaluation decoupled from transport, and you accept that you supply the storage, the HTTP layer and the audit sink. Do not adopt it if you want a running authorization server with an admin API out of the box.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Ladon solves, and who it is for

Most applications start with role checks hardcoded in handlers: if user.Role == "admin". That works until the rules become conditional. The README frames Ladon's scope as answering the question "Who is able to do what on something given some context", and the contrast it draws is with ACL and RBAC. Those two models answer yes or no about a subject and a resource; they do not naturally express a rule that depends on the caller's IP range, the resource owner, or a request-time attribute. Ladon is for Go teams whose authorization decisions need that context, and whose rules change often enough that shipping a new binary to change them is unattractive.

The intended audience is narrow. Ladon is a library, not a service. The README states that it does not come with an HTTP or server implementation and that it does not restrict JSON either, leaving the choice of Protobuf, RESTful, HTTP or AMQP to the reader. If you are looking for something to deploy and point a browser at, this is the wrong shape. If you are building a service mesh, a multi-tenant SaaS backend, or an IoT control plane where device identities need scoped permissions, the library form is the point: policy evaluation runs in your process, with no network hop and no separate availability dependency.

Policy documents, conditions and the Warden

A policy is a JSON document with five fields that matter: description, subjects, actions, effect, resources, and optionally conditions. The README's example policy allows the effect "allow" for subjects matching users:<peter|ken>, users:maria and groups:admins, over actions delete and <create|update>, on resources matching resources:articles:<.*> and resources:printer. The angle brackets are not decoration: Ladon compiles these strings into regular expressions, which is how one policy covers a family of subjects or resources without enumerating them.

Conditions attach to a policy and are evaluated against the request context. The README documents CIDRCondition, StringEqualCondition, BooleanCondition, StringMatchCondition, SubjectCondition, StringPairsEqualCondition and ResourceContainsCondition, plus a documented path for adding custom ones. In the example, a remoteIP condition of type CIDRCondition with options cidr set to 192.168.0.1/16 gates the whole policy on the caller's address.

The evaluation entry point is the Warden. The repository layout shows warden.go, manager.go, matcher.go and matcher_regexp.go at the top level, with a compiler/ directory and a manager/ directory holding the storage implementations. The data flow is therefore: a manager supplies policies, the compiler turns their pattern strings into matchers, and the Warden combines the matching policies into an allow or deny answer for a given request. The README also documents an audit log interface on the Warden, with audit_logger.go, audit_logger_info.go and audit_logger_noop.go present in the repository, so decisions can be recorded or deliberately discarded depending on which logger you construct the Warden with.

Installing Ladon and making a first decision

The README's installation section is two lines. It states the library works with Go 1.11+, and the go.mod in the repository declares go 1.19, so treat the module file as the more current floor. The commands are:

bash
export GO111MODULE=on
go get github.com/ory/ladon

After that, the README's own REST example is illustrative rather than runnable: it POSTs a policy to https://my-ladon-implementation.localhost/policies, an endpoint that does not exist in this repository. That is the clearest signal of Ladon's boundary. You write the server. In-process, the shape is a manager holding policies and a Warden evaluating requests against them. The repository ships a manager/ directory and the README says Ladon officially ships an exemplary in-memory storage implementation, so the in-memory manager is what you get without adding an adapter. A community-supported adapter for CockroachDB is linked from the README at github.com/wehco/ladon-crdb.

The README's request JSON shows the shape of what you evaluate: a subject of users:peter, an action of delete, a resource of resources:articles:ladon-introduction, and a context object carrying remoteIP as 192.168.0.5. Against the example policy above, that request falls inside the 192.168.0.1/16 CIDR and matches the subject and resource patterns, so the expected answer is allow. What you should verify yourself is the deny path: a request from an address outside that CIDR should not be allowed by that policy, and the README does not spell out the default when no policy matches. Read the Warden's behaviour in the source before you rely on a default in production.

One more installation detail worth knowing: the README says Ladon utilizes ory-am/dockertest for tests and points readers at that project for setting up the testing environment. If you plan to run the library's own test suite, expect Docker to be involved.

Where Ladon stops: no server, and a regex engine you did not choose

The README has a Limitations section with one entry, titled Regular expressions. It does not elaborate in the text available here, but the go.mod explains why the topic exists: Ladon depends on github.com/dlclark/regexp2 rather than Go's standard regexp package. regexp2 exists to support regex features the stdlib deliberately omits. The practical consequence is that policy patterns are interpreted by a different engine with different syntax support and different performance characteristics than the regexes you write elsewhere in a Go program. If your team assumes RE2 semantics in policy strings, that assumption needs checking against the library's documentation and source, not against habit.

There is a second, larger boundary. Ladon does not ship a server, an admin UI, or a policy distribution mechanism. The README is explicit that it is your job to decide on the protocol and write the server. That means you also own the hard parts that a policy service would normally hand you: how policies reach every instance, how a policy change propagates without a restart, how you avoid evaluating against a stale in-memory set, and how you authenticate the callers who write policies in the first place. None of that is in the repository layout. The manager/ directory gives you storage abstractions, not a control plane.

Ladon is also the wrong tool when your authorization model is genuinely simple. If you have three roles and no conditions, a role field on the user record is less code, fewer dependencies and nothing to operate. Ladon earns its place when rules are conditional and numerous, not when they are few.

Ladon against Open Policy Agent

The obvious comparison is Open Policy Agent, which Ladon's own README does not name. The difference in approach is structural. OPA evaluates policies written in Rego, a purpose-built declarative language, and runs as a separate process or sidecar that your services query over HTTP. Ladon evaluates JSON policy documents inside your Go process through a library call. OPA gives you a language expressive enough to compute derived facts and combine rules; Ladon gives you subject, action, resource and condition matching with regex patterns, which is a much smaller surface.

That trade favors Ladon in two situations. First, when the decision is on a hot path and you do not want a network call or a sidecar in the request flow. Second, when your team is already fluent in the AWS IAM policy model, because Ladon's documents are modeled on it and the mental transfer is small. It favors OPA when policies need logic that pattern matching cannot express, when you want one policy engine shared across services in several languages, or when you want the engine deployed and upgraded independently of your application binaries. Ladon's Go-only nature is a real constraint: a polyglot organization will end up with two authorization systems or a rewrite.

Maintenance, licensing and what an upgrade actually costs

The repository is not archived, and its last push was on 2026-08-28. The most recent tagged release listed is v1.3.0 from 2024-03-06, preceded by v1.2.0 in 2020 and v1.1.0 in 2020. That gap between commit activity and tagged releases is the thing to weigh: the code is being touched, but the release cadence is slow, so pinning to a tag means you may be running code older than the branch. The README states that Ladon uses semantic versioning and that versions beginning with zero might introduce backwards compatibility breaks with each minor version. Since the project is past 1.0, the README's own framing suggests the 1.x line is the stable one.

Upgrade cost is mostly your responsibility. Because Ladon is a library, a new version arrives through go.mod and your build, not through a container restart. The dependencies listed in go.mod are few and mostly stable, which keeps the transitive surface small, but any change to the regex engine or the matcher affects policy interpretation, and policy interpretation changes are the kind that fail silently by allowing something they should not. The repository contains benchmark_warden_test.go and a full test suite, which is what you would run against your own policies after a version bump.

Licensing is Apache-2.0, a permissive licence that permits commercial use and modification with the usual notice and attribution conditions. That is a summary of the licence identifier from the repository, not legal advice; if you redistribute Ladon or a modified version, read the LICENSE file in the repository and get your own counsel on the notice obligations.

Editorial conclusion

Adopt ory/ladon if you are writing Go services that need policy evaluation decoupled from transport, and you accept that you supply the storage, the HTTP layer and the audit sink. Do not adopt it if you want a running authorization server with an admin API out of the box. Before committing, verify three things in your own codebase: that the in-memory manager is replaced by a persistent one for production policies, that your policy regexes behave as expected under the regexp2 engine rather than Go's stdlib matcher, and that the audit logger you pass to NewWarden actually persists the records you need for compliance. The repository's own README states plainly that Ladon does not come with an HTTP or server implementation, and that sentence should be the deciding input, not the feature list.

Frequently asked questions

Does ory/ladon include an HTTP server or admin API?

No. The README states that Ladon does not come with an HTTP or server implementation and that it does not restrict JSON, leaving the choice of protocol to the reader. The REST example in the README posts to an artificial endpoint that is not part of this repository.

What storage does ory/ladon ship with?

The README says Ladon officially ships with an exemplary in-memory storage implementation, and that a community-supported adapter is available for CockroachDB. The repository layout includes a manager/ directory for storage implementations.

Which Go version does ory/ladon require?

The README's installation section says the library works with Go 1.11+, while the repository's go.mod declares go 1.19. Treat the module file as the more current requirement.

What kinds of conditions can an ory/ladon policy use?

The README documents CIDRCondition, StringEqualCondition, BooleanCondition, StringMatchCondition, SubjectCondition, StringPairsEqualCondition and ResourceContainsCondition, and describes how to add custom conditions. Conditions are evaluated against the request context, such as remoteIP in the README's example.

Official sources

  1. License: Apache-2.0
  2. ory/ladon on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ory-ladon.svg)](https://hysenlabs.com/projects/ory-ladon)