https://github.com/determinatesystems/nix-policy
Experiments with Nix and Open Policy Agent
https://github.com/determinatesystems/nix-policy
Last synced: about 1 year ago
JSON representation
Experiments with Nix and Open Policy Agent
- Host: GitHub
- URL: https://github.com/determinatesystems/nix-policy
- Owner: DeterminateSystems
- Created: 2023-03-30T12:19:49.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-11-06T18:15:21.000Z (over 1 year ago)
- Last Synced: 2024-11-06T19:26:24.219Z (over 1 year ago)
- Language: Nix
- Size: 199 KB
- Stars: 27
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Policy-driven Nix
> [!INFO]
> This repo was created as a complement to the [Packaging Open Policy Agent policies with Nix][blog-post] blog post on the [Determinate Systems blog][blog] and fulfilled its purpose.
> It won't be updated further but you're free to use it [as you see fit](./LICENSE)!
An experiment using [Nix] with [Open Policy Agent][opa] (OPA).
## How it works
This project uses [Nix] to create CLI tools that wrap [Rego] policies for [Open Policy Agent][opa]:
- The OPA CLI tool generates a [WebAssembly] (Wasm) binary for the specified Rego policy file and [entrypoint][bundle]
- A [Rust CLI](./eval) wraps the generated Wasm and provides the final user interface.
That CLI is itself a thin wrapper around the [`rust-opa-wasm`][lib] library from the good folks at [Matrix].
You can run the default example for the [`rbac.rego`](./examples/rbac.rego):
```shell
# Generate a Wasm binary from an OPA policy
nix build --print-build-logs
./result/bin/rbac-eval \
--input '{"password":"opensesame"}' \
--data '{"expected":"opensesame"}'
# [{"result":true}]
./result/bin/rbac-eval \
--input '{"password":"somethingelse"}' \
--data '{"expected":"opensesame"}'
# [{"result":false}]
```
That CLI wraps this policy:
```rego
package rbac
default allow := false
allow = true {
expected := data.expected
password := input.password
password == expected
}
```
The magic here is that the generated CLI automatically reads from the Rego-policy-turned-into-Wasm stored in the Nix store, which means that you don't need to specify an entrypoint or a path to the Wasm file on the CLI; that's handled at the Nix level.
## Create your own evaluator
You can create your own using the [`mkPolicyEvaluator`](./nix/evaluator.nix) function provided by this flake.
Here's an example:
```nix
mkPolicyEvaluator {
name = "evaluate-tf-state"; # The name of the CLI
src = ./.; # The local workspace
policy = ./policies/terraform.rego; # The Rego policy that the CLI wraps
entrypoint = "terraform/allow"; # The entrypoint for evaluation
}
```
Here's that function used in the context of a full flake:
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
nix-policy.url = "github:DeterminateSystems/nix-policy";
};
outputs = { self, nix-policy }:
let
systems = [
"aarch64-linux"
"x86_64-linux"
"aarch64-darwin"
"x86_64-darwin"
];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f {
pkgs = import nixpkgs { inherit system; overlays = [ nix-policy-overlays.opa-wasm ]; };
});
in
{
packages = forAllSystems ({ pkgs }: {
default = pkgs.mkPolicyEvaluator {
name = "evaluate-tf-state";
src = ./.;
policy = ./policies/terraform.rego;
entrypoint = "terraform/allow";
};
});
};
}
```
Then you can build and run:
```shell
nix build
./result/bin/evaluate-tf-state \
--input-path terraform.tfstate \
--data-path policy-data.json
```
[blog]: https://determinate.systems/posts
[blog-post]: https://determinate.systems/posts/open-policy-agent
[bundle]: https://www.openpolicyagent.org/docs/latest/management-bundles/#bundle-file-format
[lib]: https://github.com/matrix-org/rust-opa-wasm
[matrix]: https://github.com/matrix-org
[nix]: https://zero-to-nix.com
[opa]: https://open-policy-agent.org
[rego]: https://www.openpolicyagent.org/docs/latest/policy-language
[webassembly]: https://webassembly.org