Conjtest: a new Policy-as-Code tool built with Clojure/Babashka & Go
Introducing conjtest
!
Conjtest is a CLI application that allows you to write policies (= functions) in Clojure and run those policies against structured configuration data using a self-contained binary. Conjtest supports many common configuration file formats such as EDN, JSON, YAML, XML, HCL, Dockerfile, but many others as well.
Conjtest is heavily based on Conftest which is a policy-as-code CLI application made in Go. Where Conftest uses Rego to run policies, Conjtest runs them using Babashka and sci. Conjtest uses a combination of Clojure & Go parsers, allowing it to use more parsers than is available in the Clojure ecosystem while leveraging a robust and practical language for policy creation & validation.
In other words, Conjtest enables you to:
- Define & run policies against your infrastructure as part of your CI pipeline or Git Hooks using a standardized tool.
- Catch problems or security issues before they become incidents & enforce compliance.
- Use Clojure to define your infrastructure policies, which may either support a full-stack Clojure approach or enable gradual introduction of Clojure to a codebase.
- Provide Go/Conftest parsers for compatibility.
Rationale
Why did I make this project?
A few years back, I wanted a tool to validate my cloud configuration files and fail my CI pipeline if my configuration contained any security issues or denylisted values.
A team I was working in chose to go with a more battle-tested tool such as Conftest, even though I would have liked to use Clojure for this. I even made a small hacky proof-of-concept to showcase, which admittedly got shot down for good reason. You know us Clojure developers, we like our tools made with Clojure.
At the same time, I was feeling the pain while adopting Conftest for our team. There was a steep learning curve for the Rego language, despite its Datalog-inspired approach, and adoption rate was low (during my stay in the team). At first I thought it was just a personal skill issue, but I don't seem to be the only one with issues. I've also talked with several DevOps & SRE people at meetups about the steep learning curve.
I'm still a fan of Conftest. I think it's a great OSS tool, and I'm incredibly appreciative of the work that the contributors have put into this tool.
But that lingering thought stayed, I wanted to build a similar tool using Clojure to get better adoption of security policies and to spread Clojure even further. I just couldn't figure out the right approach at the time.
Fast forward to end of 2024 when I finally learned about Babashka pods, I realized I could leverage the Go ecosystem to fill in the final missing piece: wide parser support for different configuration file formats. Something that Conftest had that I could now use from Clojure/Babashka.
What about the name? Well... it's just a wordplay between Conf and conj
, which is one of the core functions in Clojure. Similar to how Clojure is a core functionality in Conjtest :-)
Going forward
Conjtest is now out and in alpha development. As it's early days alpha, expect some breaking changes, but of course we try not to break things.
The current goal is to provide a self-contained binary, but to also provide escape hatches via pod-ilmoraunio-conjtest and conjtest-clj library that you can use from native Babashka (see this example). Linux (amd64) and MacOS (arm64) builds will be supported at first, more may come later.
For discussion, there is now a #conjtest channel in the Clojurians Slack.
Contributions (issues & PRs) are also welcome to the following repositories:
- https://github.com/ilmoraunio/conjtest
- https://github.com/ilmoraunio/conjtest-clj
- https://github.com/ilmoraunio/pod-ilmoraunio-conjtest
- https://github.com/ilmoraunio/pod-ilmoraunio-conftest
To get started quickly, you can install the binary to your /usr/local/bin
directory and then run this quickstart example. You can install the binary using the following commands.
MacOS (arm64):
curl -sLO https://github.com/ilmoraunio/conjtest/releases/download/v0.0.1/conjtest-0.0.1-macos-arm64.zip -o conjtest.zip
unzip conjtest.zip conjtest
sudo mv conjtest /usr/local/bin
Linux (amd64)
curl -sLO https://github.com/ilmoraunio/conjtest/releases/download/v0.0.1/conjtest-0.0.1-linux-x86_64.tar.gz -o conjtest.tar.gz
tar -xvzf conjtest.tar.gz conjtest
sudo mv conjtest /usr/local/bin
For more in-depth documentation, there is also a user guide.
Enjoy!