I have a Terraform configuration targeting deployment on AWS. It applies beautifully when using an IAM user that has permission to do anything (i.e. {actions: [\"*\"],
Here is another approach, similar to what was said above, but without getting into CloudTrail -
TF_LOG=trace terraform apply --auto-approve &> log.log
cat log.log | grep "DEBUG: Request"
You will get a list of all AWS Actions used.
The method you are attempting is a bit unusual in cloud technology. Instead of giving fine grained control to the terraform user running the API calls, you could run terraform on an EC2 instance with an EC2 IAM profile that allows the instance itself to call the API's with the correct set of AWS service permissions.
Each call is made to a specific API endpoint. Some terraform operations applied during a apply would be different if you pushed an update. You also need to know what happens during a modify operation where a resource is updated in place.
Instead of restricting that API key to specifics, let it have more leeway, if it needs to create and destroy EC2, let it have EC2 full perms maybe with conditionals to restrict to account level or VPC.
As I guess that there's no perfect solution, treat this answer a bit as result of my brain storming. At least for the initial permission setup, I could imagine the following:
Allow everything first and then process the CloudTrail logs to see, which API calls were made in a terraform apply
/ destroy
cycle.
Afterwards, you update the IAM policy to include exactly these calls.
The way I deal with is, allow all permissions (*) for that service first, then deny some of them if not required.
For example
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSpecifics",
"Action": [
"ec2:*",
"rds:*",
"s3:*",
"sns:*",
"sqs:*",
"iam:*",
"elasticloadbalancing:*",
"autoscaling:*",
"cloudwatch:*",
"cloudfront:*",
"route53:*",
"ecr:*",
"logs:*",
"ecs:*",
"application-autoscaling:*",
"logs:*",
"events:*",
"elasticache:*",
"es:*",
"kms:*",
"dynamodb:*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Sid": "DenySpecifics",
"Action": [
"iam:*User*",
"iam:*Login*",
"iam:*Group*",
"iam:*Provider*",
"aws-portal:*",
"budgets:*",
"config:*",
"directconnect:*",
"aws-marketplace:*",
"aws-marketplace-management:*",
"ec2:*ReservedInstances*"
],
"Effect": "Deny",
"Resource": "*"
}
]
}
You can easily adjust the list in Deny session, if terraform doesn't need or your company doesn't use some aws services.