AikidoSec/aws-native-terraform-module: Terraform That Deploys Like an AWS Control Plane
It uses Terraform where orchestration belongs, StackSets where AWS can fan out cleanly, and `moved` blocks to refactor live security roles without a destructive rewrite.
- This module treats Terraform as the orchestrator and AWS StackSets as the distribution layer, which makes multi-account security rollout feel native instead of bolted on.
- Its IAM design narrows access with external ID enforcement, conditional resource creation, and tag-gated snapshot deletion instead of handing out broad permissions.
- The repo treats refactoring as a production concern, using submodules and `moved` blocks to preserve live role identity while the codebase changes shape.
- The hybrid pattern is more complex than single-account Terraform, but that complexity is doing real work at AWS Organization scale.
The odd thing about this repo is not that it uses Terraform. It is that Terraform is not doing the part AWS already does best. AikidoSec/aws-native-terraform-module uses Terraform as the control plane, then hands distribution to CloudFormation StackSets so the same security posture can land across member accounts without a custom rollout system.
Terraform in the hub, StackSets in the spokes
That split is the whole point. The root module handles orchestration in the management account, while StackSets push the member-account side of the setup through AWS-native fan-out. For an AWS Organization, that is a cleaner boundary than trying to make Terraform impersonate a distribution service across every account.
The security model is shaped, not broad
The IAM layer is not trying to be generous. It is trying to be precise. The module enforces an external ID for role assumption, layers a custom `aikido_security_audit` policy on top of AWS-managed permissions, and only creates scanning resources when the relevant feature flags are on.
variable "external_id" {
type = string
}
resource "aws_iam_role_policy" "ebs_scan" {
name = "aikido-ebs-scan"
role = aws_iam_role.aikido.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["ec2:DescribeSnapshots"]
Resource = "*"
},
{
Effect = "Allow"
Action = ["ec2:DeleteSnapshot"]
Resource = "*"
Condition = {
StringEquals = {
"ec2:ResourceTag/aikido_snapshot" = "true"
}
}
}
]
})
}
Least privilege, but with deliberate tradeoffs
The cleanest detail in the repo is also the most opinionated. The `enable_comprehensive_permissions` toggle admits that full scan coverage and quiet CloudTrail logs are not the same goal. Turn it off, and the module stays leaner, but Aikido will hit more `Access Denied` responses while probing the account. That is not a bug. It is an explicit tradeoff.
How to refactor a live security module without breaking it
This is where the repo stops looking like a module and starts looking like an operating discipline. Version 2.0.0 split the logic into submodules, the repository keeps linting and release automation in place, and `moved` blocks preserve resource identity while the file structure changes. That means the maintainers can reshape the code without forcing Terraform to tear down live IAM roles and rebuild them from scratch.
moved {
from = aws_iam_role.aikido
to = module.iam_roles.aws_iam_role.aikido
}
moved {
from = aws_iam_role_policy.aikido_security_audit
to = module.iam_roles.aws_iam_role_policy.aikido_security_audit
}
resource "aws_cloudformation_stack_set" "member_accounts" {
name = "aikido-security-rollout"
}
That is the important part. Terraform can rename resources. What matters here is that the repo treats refactoring as a rollout constraint, not a cleanup task.
What this beats, and what it costs
| Model | Rollout model | Operational complexity | Org-scale fit | Refactor safety | Least-privilege control | Best use case |
|---|---|---|---|---|---|---|
| Pure Terraform per account | Repeat the same module in each account | Low at first, then duplication and drift | Weak unless you add more tooling | Depends on manual discipline | Strong in theory, noisy in practice | Small estates or one-off setups |
| AWS-native StackSets only | Push a template from AWS into member accounts | Moderate, with less Terraform glue | Strong for fan-out | Medium, but code-level refactors are less expressive | Good, but the authoring model is narrower | Standardized AWS-only rollouts |
| Aikido hybrid module | Terraform orchestrates, StackSets distribute | Higher upfront, lower rollout friction later | Strong, because the org boundary is explicit | Strong, thanks to `moved` blocks and submodules | Strongest balance, because policy shape stays localized | Security controls in AWS Organizations |
The hybrid wins when rollout safety matters more than simplicity. If you only need one account, it is probably overbuilt. If you need to touch many accounts without rewriting live IAM roles, the extra moving parts are the point.