CLI tool
flosell/iam-policy-json-to-terraform avatar
flosell/iam-policy-json-to-terraform

Converting AWS IAM policy JSON into Terraform HCL with iam-policy-json-to-terraform

Small tool to convert an IAM Policy in JSON format into a Terraform aws_iam_policy_document

816 stars58 forksJavaScriptApache-2.0

At a glance

What is it?
iam-policy-json-to-terraform reads an AWS IAM policy in JSON and prints a Terraform aws_iam_policy_document block, available as a Go binary, a Homebrew formula and a browser app. It converts one direction only and leaves the surrounding Terraform configuration to you.
Who is it for?
iam-policy-json-to-terraform is worth adding to a workflow where IAM policies arrive as JSON from an audit, a customer onboarding file or a console export, and the target state is Terraform. It is not a policy authoring tool, and it does not generate the surrounding configuration.
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 5 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

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

Editorial analysis

One JSON policy in, one aws_iam_policy_document block out

The problem this solves is narrow and real. IAM policies are handed to people as JSON all the time: an auditor exports one, a colleague pastes one from the console, a customer sends a baseline policy. Once the policy lands in a Terraform-managed account, the JSON has to be rewritten by hand into an `aws_iam_policy_document` data source, and that rewriting is where transcription errors creep in. The project describes itself as a small tool to convert an IAM Policy in JSON format into a Terraform `aws_iam_policy_document`.

The transformation visible in the usage example is field level and predictable. An `Effect` of `Allow` becomes `effect = "Allow"`, the `Action` array becomes `actions`, the `Resource` value becomes `resources`, and a missing statement identifier comes out as `sid = ""`. The result is HCL that can be pasted straight into a `.tf` file. The JSON in the example is deliberately minimal, one statement with a wildcard action and a wildcard resource, which is exactly the kind of shape that is tedious to reformat by hand and easy to get subtly wrong.

The tool prints to standard output and nothing else, which makes it composable rather than a project file format. It does not read a Terraform file, does not manage state, and does not talk to AWS. It is a formatter with a specific input and output contract.

A Go binary with a separate JavaScript converter behind the web UI

The command line tool is written in Go. The module path in `go.mod` is `github.com/flosell/iam-policy-json-to-terraform`, it declares `go 1.25.11`, and the entry point at the root is `iam-policy-json-to-terraform.go`. The web frontend, by contrast, is plain HTML, JavaScript and CSS kept together in `web/index.html`.

The bridge between the two is a compiled artifact. Running the web build compiles the JavaScript version of the converter into a `web.js` file, and including that file exposes a `convert(policyName,jsonString)` function in the global namespace. So the browser app and the command line tool are two front ends over the same conversion logic, one shipped as a native binary and one shipped as a JavaScript bundle.

That split explains a detail in the dependency list. `go.mod` requires `github.com/flosell/hclencoder` for HCL generation, plus `github.com/mattn/go-isatty` for terminal detection and `github.com/stretchr/testify` for tests. The `hclencoder` module is the Go side of the encoder, and the JavaScript port carries the same responsibility in the web build. The dependency list also pulls in a long indirect tail, cloud libraries and tooling such as `gosec` and `revive`, which come from the development scripts rather than from the conversion itself.

The practical upshot: if you only want the CLI, you need the Go binary and none of that web toolchain. If you want to self-host the browser tool, you are taking on a JavaScript build step.

Installing the binary with brew, asdf, or a release download

There are three documented install paths for command line use. On macOS, Homebrew is the shortest:

bash
$ brew install iam-policy-json-to-terraform

For teams that standardise on asdf, a community plugin is registered with:

bash
$ asdf plugin add iam-policy-json-to-terraform https://github.com/carlduevel/asdf-iam-policy-json-to-terraform.git

That plugin lives in a different repository from the tool itself, which is worth knowing if you pin versions or run a mirror. The third path is the simplest and the most explicit: download the latest binary from the releases page and put it into your `PATH` under the name `iam-policy-json-to-terraform`.

For contributors, the project documents a Go install for anyone with a defined `GOPATH` and `$GOPATH/bin` on the path:

```bash testcase=usage $ go install github.com/flosell/iam-policy-json-to-terraform@latest ```

Install the binary under exactly that name, since every usage example pipes into the command by that name and a different file name would break the examples. A browser version is also published at the project homepage, which covers the case where you want to convert a policy without installing anything at all.

One operational detail to keep in mind for CI: because the tool only writes to standard output, a conversion in a pipeline produces text that has to be redirected into a file or piped into another step. There is no documented flag for writing directly to a named output file.

Piping raw JSON or redirecting a policy file into stdin

The usage section covers two input shapes. The first passes a policy inline on standard input:

```bash testcase=usage $ echo '{"Statement":[{"Effect":"Allow","Action":["ec2:Describe*"],"Resource":"*"}]}' | iam-policy-json-to-terraform data "aws_iam_policy_document" "policy" { statement { sid = "" effect = "Allow" resources = ["*"] actions = ["ec2:Describe*"] } }

code

The second reads a policy file by redirecting it:

bash $ iam-policy-json-to-terraform < some-policy.json ```

Both routes end at standard input, so the tool itself has no arguments to learn. That is a clean design for scripting: the same command works for a one line policy during a chat and for a several kilobyte policy file from an audit archive.

What the output does not contain is as important as what it does. The generated block is a data source named `aws_iam_policy_document` with a `statement` block inside it, and the example shows exactly the fields `sid`, `effect`, `resources` and `actions`. There is no `version` element, no `condition` block, no `principals` block, and no `aws_iam_policy` resource that would attach the document to a role. The converter handles the standard statement shape and stops there.

A policy that uses conditions, principal blocks, a `NotAction` or `NotResource` element, or multiple statements with meaningful sids, needs checking against the Terraform AWS provider documentation by hand after conversion. Treat the output as a first draft, not as a verified translation.

The ./go script is the single entry point for builds, tests and the web bundle

Development is driven by a script named `go` at the repository root, described as the primary point of entry for any development activity. Running it without arguments prints the list of available tasks:

```bash testcase=building $ ./go help build Test and build the whole application clean Remove build artifacts fmt Format code fmtcheck Run linter seccheck Run security checks test Run all tests test-readme Run the commands mentioned in the README for sanity-checking tools Install additional required tooling tools-main Install additional required tooling for the main version tools-web Install additional required tooling for the web version web-build Build the web version web-deploy Deploy the web version to GitHub pages web-e2e Run end to end tests for web version (requires web-build) web-e2e-live Run end to end tests for web version in live mode for development (requires web-build) web-serve Serve the web version on a local development server web-visual-regression-approve Accept changes in Web UI visuals web-visual-regression-test Test for changes in Web UI visuals

code

Two of those tasks matter more than the rest. `test-readme` runs the commands mentioned in the README for sanity checking, which means the usage examples are treated as tests rather than as prose, so a change in output format breaks the build. `web-visual-regression-test` and its approve counterpart guard the browser interface with visual regression checks, and the end to end tests are written with TestCafe in `web_test.js` and run through `./go web-e2e`.

Setting up locally means cloning the repository and running `./go tools_web` from inside the clone, which installs the dependencies and tools needed for the web build, with the Go tooling installed automatically when used.

bash testcase=building $ cd iam-policy-json-to-terraform $ ./go tools_web ```

The presence of `seccheck` and a `revive.toml` linter configuration shows the project takes its own security and style checks seriously, which matters more than usual for a tool whose output lands in infrastructure code.

Web version versus hand written HCL versus the console

The same conversion is available in three places, and they differ in more than packaging.

The command line tool prints to standard output, which makes it scriptable but means someone has to paste the result into a `.tf` file. The web version at the project homepage does the conversion in the browser through the `convert(policyName,jsonString)` function, so the policy name can be chosen interactively and the output can be copied without touching a terminal. Neither one writes a Terraform file or talks to your cloud account.

The real alternative, however, is writing the `aws_iam_policy_document` block by hand. Terraform's data source is documented by HashiCorp with its own statement types, including the ones this converter does not emit, so for a policy with conditions or principals, hand writing against the provider documentation produces a more complete result than converting. The converter wins on the boring case, where a policy has been authored in JSON and only needs to be moved into Terraform form.

A third path is to stay in JSON. IAM policies attached to roles can be referenced as JSON files from Terraform rather than converted at all. That approach avoids translation entirely, at the cost of losing the provider level checks that come from using the data source.

There is also a no-code conversion in the opposite direction that this tool does not offer. The output is one-way: JSON goes in, HCL comes out, and there is no documented command that turns an `aws_iam_policy_document` block back into a policy JSON. If you need round tripping, this is the wrong tool.

Apache-2.0 terms and a Go 1.25 baseline for contributors

The project is licensed under Apache-2.0, which permits use, modification and redistribution including in commercial products, and which carries the standard patent grant and NOTICE obligations. The repository carries a `LICENSE` file and a `CODE_OF_CONDUCT.md` alongside a `CONTRIBUTING.md`.

On maintenance, the last push to the repository was on 2026-10-18, five days before this review, and the repository is not archived. The tagged releases include 1.9.2 on 2025-10-19, 1.9.1 on 2025-03-16 and 1.9.0 on 2025-03-01. Commits have continued past the 1.9.2 tag without a new release number, which is a pattern worth noticing if you consume the binary: the release page and the default branch can differ.

For contributors the dependency baseline matters more than the licence. `go.mod` declares `go 1.25.11`, and the repository includes a `.tool-versions` file, so the Go toolchain is pinned to a specific patch level. The toolchain has moved with the project, since the module path has stayed constant while the go directive tracks recent Go releases.

The upstream dependencies are small and focused: `flosell/hclencoder` for the HCL output, `go-isatty` for terminal detection and `testify` for assertions, with the long indirect list coming from the development and security tooling invoked through the `./go` script rather than from the shipped binary. That keeps the runtime footprint of the command line tool narrow, which is a good sign for a utility that is meant to sit in a CI pipeline.

Editorial conclusion

iam-policy-json-to-terraform is worth adding to a workflow where IAM policies arrive as JSON from an audit, a customer onboarding file or a console export, and the target state is Terraform. It is not a policy authoring tool, and it does not generate the surrounding configuration. Before adopting, run the documented pipe of a single policy through the binary and compare the emitted statement blocks against the source JSON by hand, since the converter only emits the aws_iam_policy_document data source and every action, resource and condition that is not part of the standard statement shape has to be checked against the Terraform provider documentation yourself.

Frequently asked questions

How do I install iam-policy-json-to-terraform?

On macOS you can run brew install iam-policy-json-to-terraform, register the community asdf plugin, or download the latest binary from the releases page and put it into your PATH under the name iam-policy-json-to-terraform. A browser version is also published on the project homepage.

How do I convert an AWS IAM policy JSON file to Terraform?

Redirect the file into the binary with iam-policy-json-to-terraform < some-policy.json, or pipe a policy inline through standard input. The tool prints a Terraform aws_iam_policy_document data source block on standard output.

Does the converter handle IAM conditions and principals?

The usage example shows only the standard statement fields sid, effect, resources and actions, and the write up does not document condition or principal handling. Policies using those elements need to be checked against the Terraform AWS provider documentation by hand.

What language is iam-policy-json-to-terraform written in?

The command line tool is written in Go, with the module path github.com/flosell/iam-policy-json-to-terraform and a go directive of 1.25.11. The web frontend is plain HTML, JavaScript and CSS, with a JavaScript version of the converter compiled into a web.js file that exposes a convert(policyName,jsonString) function.

Official sources

  1. flosell/iam-policy-json-to-terraform on GitHub
  2. License: Apache-2.0
  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/flosell-iam-policy-json-to-terraform.svg)](https://hysenlabs.com/projects/flosell-iam-policy-json-to-terraform)

Was this useful?