Skip to content

JamesWoolfenden/sato

Folders and files

NameName
Last commit message
Last commit date

Latest commit

75477da · Mar 23, 2025
Mar 23, 2025
Nov 29, 2024
Aug 19, 2024
Aug 20, 2024
Mar 23, 2025
Mar 23, 2025
Aug 20, 2024
Sep 21, 2023
Aug 20, 2024
Jul 16, 2024
May 29, 2023
Mar 23, 2025
Aug 20, 2024
Oct 16, 2022
Jun 13, 2023
Dec 7, 2024
Aug 20, 2024
Aug 19, 2024
Dec 6, 2024
Dec 6, 2024
Oct 16, 2022
Mar 23, 2025
Mar 23, 2025
Mar 23, 2025
Dec 6, 2024
Aug 19, 2024

Repository files navigation

Sato

Maintenance Build Status Latest Release GitHub tag (latest SemVer) Terraform Version pre-commit checkov Github All Releases codecov

Converts CloudFormation (and now also ARM) into Terraform. In Go, but quickerly.

Table of Contents

Install

Compile

Download the latest releases https://github.com/JamesWoolfenden/sato/releases/tag/v0.1.19 or:

Compile locally:

git clone https://github.com/JamesWoolfenden/sato
cd sato
go install

MacOS

brew tap jameswoolfenden/homebrew-tap
brew install jameswoolfenden/tap/pike

Windows

I'm now using Scoop to distribute releases, it's much quicker to update and easier to manage than previous methods, you can install scoop from https://scoop.sh/.

Add my scoop bucket:

scoop bucket add iac https://github.com/JamesWoolfenden/scoop.git

Then you can install a tool:

scoop install sato

Docker

docker pull jameswoolfenden/sato
docker run --tty --volume /local/path/to/tf:/tf jameswoolfenden/sato scan -d /tf

https://hub.docker.com/repository/docker/jameswoolfenden/sato

Usage

Parse

Get yourself some valid CloudFormation*

 git clone https://github.com/JamesWoolfenden/aws-cloudformation-templates
 >cd aws-cloudformation-templates/community/codestar/custom-ci-cd-pipeline
 ❯ ls
 README.md    template.yml
 >sato parse -f template.yml
 9:17PM INF Created .sato\variables.tf
 9:17PM INF Created .sato\data.tf
 9:17PM INF Created .sato\aws_codebuild_project.productionbuild.tf
 9:17PM INF Created .sato\aws_codebuild_project.productiondeploy.tf
 9:17PM INF Created .sato\aws_codebuild_project.stagingbuild.tf
 9:17PM INF Created .sato\aws_codebuild_project.stagingdeploy.tf
 9:17PM INF Created .sato\aws_iam_role.codebuildrole.tf
 9:17PM INF Created .sato\aws_codepipeline_pipeline.pipeline.tf
 9:17PM INF Created .sato\aws_iam_role.pipelinerole.tf
 9:17PM INF Created .sato\aws_s3_bucket.pipelines3bucket.tf

That's it. So by default (overridable) the parsed CloudFormation (now Terraform) will be in a .sato subdirectory. So let's have a look see:

> ls .sato
aws_codebuild_project.productionbuild.tf  aws_codebuild_project.stagingbuild.tf     aws_codepipeline_pipeline.pipeline.tf     aws_iam_role.pipelinerole.tf              variables.tf
aws_codebuild_project.productiondeploy.tf aws_codebuild_project.stagingdeploy.tf    aws_iam_role.codebuildrole.tf             aws_s3_bucket.pipelines3bucket.tf

So there are some files that could be Terraform.

The Cats Pyjamas

Testing...

>terraform init
...
Terraform has been successfully initialized!
....
>terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create
...
Plan: 12 to add, 0 to change, 0 to destroy.
...

See

Shows the Terraform resource equivalent to a CloudFormation resource, or vice versa.

This tells you the equivalent resource required, given a CF or an ARM resource;

$ sato see -r Microsoft.Storage/storageAccounts
azurerm_storage_account

or

$sato see -r AWS::EC2::Instance
aws_instance%

Bisect

ARM to Terraform conversion.

What? You've got these legacy ARM templates, and you'd dearly love to drop them, but you really don't fancy Bicep and the rework. I got you covered. Sato now bisects ARM into Terraform.

Take one of the Azure quickstart examples from here https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.compute/vm-simple-windows:

Clone it:

git clone https://github.com/Azure/azure-quickstart-templates.git

Then bisect it!

$ sato bisect -f /Users/jwoolfenden/code/azure-quickstart-templates/quickstarts/microsoft.compute/vm-simple-windows/azuredeploy.json
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/variables.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/locals.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_storage_account.sato0.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_public_ip.sato1.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_network_security_group.sato2.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_virtual_network.sato3.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_network_interface.sato4.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_virtual_machine.sato5.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/azurerm_virtual_machine_extension.sato6.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/outputs.tf
1:56PM INF Created /Users/jwoolfenden/code/sato/.sato/data.tf

I make an opinionated translation, in Terraform there are no parameters, resources and dependencies are very different, there's no one for one - ARM to Terraform, so the aim is to get you close to 100%.

There needs to be a lot of work supporting resources and built-in functions/template as yet. If you want to use this, let me know so, then I'll know to do so, or even better send me a PR.

Version

$sato version
9.9.9

Help

$ sato
NAME:
sato - Translate Cloudformation to Terraform

USAGE:
sato [global options] command [command options] [arguments...]

VERSION:
9.9.9

AUTHOR:
James Woolfenden <jim.wolf@duck.com>

COMMANDS:
bisect      translate ARM to Terraform
parse       translate CFN to Terraform
see         shows equivalent Terraform resource
version, v  Outputs the application version
help, h     Shows a list of commands or help for one command

GLOBAL OPTIONS:
--help, -h     show help
--version, -v  print the version

Extra credit - Pike

If you use my other tool, Pike you can now apply that and get the policy requirements:

pike scan -d .sato -o json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "codebuild:BatchGetProjects",
        "codebuild:CreateProject",
        "codebuild:DeleteProject",
        "codebuild:UpdateProject"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "VisualEditor1",
      "Effect": "Allow",
      "Action": [
        "codepipeline:CreatePipeline",
        "codepipeline:DeletePipeline",
        "codepipeline:GetPipeline",
        "codepipeline:ListTagsForResource"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "VisualEditor2",
      "Effect": "Allow",
      "Action": [
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:DeleteRolePolicy",
        "iam:GetRole",
        "iam:GetRolePolicy",
        "iam:ListAttachedRolePolicies",
        "iam:ListInstanceProfilesForRole",
        "iam:ListRolePolicies",
        "iam:PassRole",
        "iam:PutRolePolicy"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Sid": "VisualEditor3",
      "Effect": "Allow",
      "Action": [
        "s3:CreateBucket",
        "s3:DeleteBucket",
        "s3:GetAccelerateConfiguration",
        "s3:GetBucketAcl",
        "s3:GetBucketCORS",
        "s3:GetBucketLogging",
        "s3:GetBucketObjectLockConfiguration",
        "s3:GetBucketPolicy",
        "s3:GetBucketRequestPayment",
        "s3:GetBucketTagging",
        "s3:GetBucketVersioning",
        "s3:GetBucketWebsite",
        "s3:GetEncryptionConfiguration",
        "s3:GetLifecycleConfiguration",
        "s3:GetObject",
        "s3:GetObjectAcl",
        "s3:GetReplicationConfiguration",
        "s3:ListBucket"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Valid CloudFormation

Ditch it all, OK, but some older samples can play fast and lose with the CloudFormation schema and data types. The Go-formation parser is less accommodating, you may need to be stricter on your typing.

  • Booleans are true or false and not "false"
  • Ints are 1,2,3 not "1", "2", "3"