Pike is a tool, to determine the minimum permissions required to run a TF/IAC run:
Still very much under active development, I intend it to:
- run in ci - limit external outbound connections
- run on a path or a file (path is done)
- determines permission drift (Compare verb now exists)
- least privilege enabler
- policy creator (This is done)
- test policy against environment (This is done see compare)
Pike currently supports Terraform and can support multiple providers, So far I've added support for a larger number of AWS resources, but I have just added support for GCP. Feel free to submit PR or Issue, and then I'll take a look.
CAVEAT The policies and roles are to get you started, there are no conditions and resources are all wildcards (for AWS) - this is definitely not best practice- you need will to modify these permissions to minimum required by adding these constrictions.
Ideally I would like to do this for you, but these policies are determined statically, and we would need to determine the resource names that will be created and know your intentions.
Download the latest binary here:
https://github.com/JamesWoolfenden/pike/releases
Install from code:
- Clone repo
- Run
go install
Install remotely:
go install github.com/jameswoolfenden/pike@latestbrew tap jameswoolfenden/homebrew-tap
brew install jameswoolfenden/tap/pikechoco install pikedocker pull jameswoolfenden/pike
docker run --tty --volume /local/path/to/tf:/tf jameswoolfenden/pike -d /tf scanhttps://hub.docker.com/repository/docker/jameswoolfenden/pike
To scan a directory of Terraform file:
./pike -d .\terraform\ scan
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": [
"ec2:MonitorInstances",
"ec2:UnmonitorInstances",
"ec2:DescribeInstances",
"ec2:DescribeTags",
"ec2:DescribeInstanceAttribute",
"ec2:DescribeVolumes",
"ec2:DescribeInstanceTypes",
"ec2:RunInstances",
"ec2:DescribeInstanceCreditSpecifications",
"ec2:StopInstances",
"ec2:StartInstances",
"ec2:ModifyInstanceAttribute",
"ec2:TerminateInstances",
"s3:GetBucketObjectLockConfiguration",
"s3:PutBucketObjectLockConfiguration",
"s3:PutObjectLegalHold",
"s3:PutObjectRetention",
"s3:PutObject",
"s3:DeleteBucket",
"s3:CreateBucket",
"s3:GetLifecycleConfiguration",
"s3:GetBucketTagging",
"s3:GetBucketWebsite",
"s3:GetBucketLogging",
"s3:ListBucket",
"s3:GetAccelerateConfiguration",
"s3:GetBucketVersioning",
"s3:GetBucketAcl",
"s3:GetBucketPolicy",
"s3:GetReplicationConfiguration",
"s3:GetObjectAcl",
"s3:GetObject",
"s3:GetEncryptionConfiguration",
"s3:GetBucketRequestPayment",
"s3:GetBucketCORS",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroups",
"ec2:DescribeAccountAttributes",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteSecurityGroup",
"ec2:RevokeSecurityGroupEgress"
],
"Resource": "*"
}
}You can also generate the policy as Terraform instead:
$pike -o terraform -d ../modules/aws/terraform-aws-activemq scan
resource "aws_iam_policy" "terraformXVlBzgba" {
name = "terraformXVlBzgba"
path = "/"
description = "Add Description"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CreateNetworkInterface",
"ec2:CreateNetworkInterfacePermission",
"ec2:CreateSecurityGroup",
"ec2:CreateTags",
"ec2:DeleteNetworkInterface",
"ec2:DeleteNetworkInterfacePermission",
"ec2:DeleteSecurityGroup",
"ec2:DeleteTags",
"ec2:DescribeAccountAttributes",
"ec2:DescribeInternetGateways",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"ec2:DetachNetworkInterface",
"ec2:RevokeSecurityGroupEgress",
"ec2:RevokeSecurityGroupIngress"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"kms:CreateKey",
"kms:DescribeKey",
"kms:EnableKeyRotation",
"kms:GetKeyPolicy",
"kms:GetKeyRotationStatus",
"kms:ListResourceTags",
"kms:ScheduleKeyDeletion",
"kms:TagResource",
"kms:UntagResource"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": [
"mq:CreateBroker",
"mq:CreateConfiguration",
"mq:CreateTags",
"mq:CreateUser",
"mq:DeleteBroker",
"mq:DeleteTags",
"mq:DeleteUser",
"mq:DescribeBroker",
"mq:DescribeConfiguration",
"mq:DescribeConfigurationRevision",
"mq:DescribeUser",
"mq:RebootBroker",
"mq:UpdateBroker",
"mq:UpdateConfiguration",
"mq:UpdateUser"
],
"Resource": "*"
}
]
})
}If you select the -w flag, pike will write out the role/policy required to build your project into the .pike folder:
$pike -w -i -d . scan
2022/09/17 13:50:51 terraform init at .
2022/09/17 13:50:51 downloaded ipThe .pike folder will contain:
aws_iam_role.terraform_pike.tf
pike.generated_policy.tfWhich you can deploy using terraform to create the role/policy to build your IAC project.
You can now deploy the policy you need directly (AWS only so far):
$pike -d ../modules/aws/terraform-aws-apigateway/ make
2022/09/18 08:53:41 terraform init at ..\modules\aws\terraform-aws-apigateway\
2022/09/18 08:53:41 modules not found at ..\modules\aws\terraform-aws-apigateway\
2022/09/18 08:53:49 aws role create/updated arn:aws:iam::680235478471:role/terraform_pike_20220918071439382800000002
arn:aws:iam::680235478471:role/terraform_pike_20220918071439382800000002This new verb returns the ARN of the role created, and you can find the tf used in your .pike folder.
Pike can now be used to update a projects README.md file:
./pike -o terraform -d ..\modules\aws\terraform-aws-activemq\ readme
This looks in the readme for the deliminators:
<!-- BEGINNING OF PRE-COMMIT-PIKE DOCS HOOK -->
<!-- END OF PRE-COMMIT-PIKE DOCS HOOK -->and replaces is either with json or Terraform like so:
This is the policy required to build this project:
The Policy required is
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": [
"mq:CreateTags",
"mq:DeleteTags",
"ec2:DescribeInternetGateways",
"ec2:DescribeAccountAttributes",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:CreateNetworkInterface",
"ec2:CreateNetworkInterfacePermission",
"ec2:DeleteNetworkInterfacePermission",
"ec2:DetachNetworkInterface",
"ec2:DeleteNetworkInterface",
"mq:CreateBroker",
"mq:DescribeBroker",
"mq:DescribeUser",
"mq:UpdateBroker",
"mq:DeleteBroker",
"mq:CreateConfiguration",
"mq:UpdateConfiguration",
"mq:DescribeConfiguration",
"mq:DescribeConfigurationRevision",
"mq:RebootBroker",
"ec2:CreateTags",
"ec2:DeleteTags",
"ec2:CreateSecurityGroup",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteSecurityGroup",
"ec2:RevokeSecurityGroupEgress",
"kms:TagResource",
"kms:UntagResource",
"kms:EnableKeyRotation",
"kms:CreateKey",
"kms:DescribeKey",
"kms:GetKeyPolicy",
"kms:GetKeyRotationStatus",
"kms:ListResourceTags",
"kms:ScheduleKeyDeletion"
],
"Resource": "*"
}
}You can see an example here https://github.com/jamesWoolfenden/terraform-aws-activemq#policy.
Want to check your deployed IAM policy against your IAC requirement?
$./pike -d ../modules/aws/terraform-aws-appsync -a arn:aws:iam::680235478471:policy/basic compare
IAM Policy arn:aws:iam::680235478471:policy/basic versus Local ../modules/aws/terraform-aws-appsync
{
"Statement": [
0: {
"Action": [
- 0: "kinesisvideo:CreateStream"
+ 0: "firehose:CreateDeliveryStream"
+ 0: "firehose:CreateDeliveryStream"
+ 1: "firehose:DeleteDeliveryStream"
+ 2: "firehose:DescribeDeliveryStream"
+ 3: "firehose:ListTagsForDeliveryStream"
+ 4: "iam:AttachRolePolicy"
+ 5: "iam:CreateRole"
+ 6: "iam:DeleteRole"
+ 7: "iam:DetachRolePolicy"
+ 8: "iam:GetRole"
+ 9: "iam:ListAttachedRolePolicies"
+ 10: "iam:ListInstanceProfilesForRole"
+ 11: "iam:ListRolePolicies"
+ 12: "iam:PassRole"
+ 13: "iam:TagRole"
+ 14: "kms:CreateKey"
+ 15: "kms:DescribeKey"
+ 16: "kms:EnableKeyRotation"
+ 17: "kms:GetKeyPolicy"
+ 18: "kms:GetKeyRotationStatus"
+ 19: "kms:ListResourceTags"
+ 20: "kms:ScheduleKeyDeletion"
+ 21: "logs:AssociateKmsKey"
+ 22: "logs:CreateLogGroup"
+ 23: "logs:DeleteLogGroup"
+ 24: "logs:DeleteRetentionPolicy"
+ 25: "logs:DescribeLogGroups"
+ 26: "logs:DisassociateKmsKey"
+ 27: "logs:ListTagsLogGroup"
+ 28: "logs:PutRetentionPolicy"
+ 29: "s3:CreateBucket"
+ 30: "s3:DeleteBucket"
+ 31: "s3:GetAccelerateConfiguration"
+ 32: "s3:GetBucketAcl"
+ 33: "s3:GetBucketCORS"
+ 34: "s3:GetBucketLogging"
+ 35: "s3:GetBucketObjectLockConfiguration"
+ 36: "s3:GetBucketPolicy"
+ 37: "s3:GetBucketPublicAccessBlock"
+ 38: "s3:GetBucketRequestPayment"
+ 39: "s3:GetBucketTagging"
+ 40: "s3:GetBucketVersioning"
+ 41: "s3:GetBucketWebsite"
+ 42: "s3:GetEncryptionConfiguration"
+ 43: "s3:GetLifecycleConfiguration"
+ 44: "s3:GetObject"
+ 45: "s3:GetObjectAcl"
+ 46: "s3:GetReplicationConfiguration"
+ 47: "s3:ListAllMyBuckets"
+ 48: "s3:ListBucket"
+ 49: "s3:PutBucketAcl"
+ 50: "s3:PutBucketPublicAccessBlock"
+ 51: "s3:PutEncryptionConfiguration"
+ 52: "wafv2:CreateWebACL"
+ 53: "wafv2:DeleteWebACL"
+ 54: "wafv2:GetWebACL"
],
"Effect": "Allow",
"Resource": "*",
- "Sid": ""
+ "Sid": "VisualEditor0"
}
],
"Version": "2012-10-17"
}
./pike -h
NAME:
pike - Generate IAM policy from your IAC code
USAGE:
pike [global options] command [command options] [arguments...]
VERSION:
v0.1.81
AUTHOR:
James Woolfenden <support@bridgecrew.io>
COMMANDS:
compare, c policy comparison of deployed versus IAC
readme, r Looks in dir for a README.md and updates it with the Policy required to build the code
scan, s scan a directory for IAM code
version, v Outputs the application version
watch, w Waits for policy update
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--arn value, -a value Policy identifier e.g. arn (default: "arn:aws:iam::680235478471:policy/basic") [%ARN%]
--auto, -A Automatically adds policy section to the end of Readme (default: false)
--config FILE, -c FILE Load configuration from FILE
--directory value, -d value Directory to scan (defaults to .) (default: ".")
--file value, -f value File to scan
--help, -h show help (default: false)
--init, -i Run Terraform init to download modules (default: false)
--output json, -o json Output types e.g. json terraform (default: "terraform") [%OUTPUT%]
--version, -v print the version (default: false)
--wait value, -W value Time to wait for policy change (in tenths of seconds) (default: 100) [%WAIT%]
--write, -w Write the policy output to a file at .pike (default: false)go buildor
Make buildDetermine and Create IAM mapping file, working out the permissions required for your resource: e.g. aws_security_group.json
[
{
"apply": [
"ec2:CreateSecurityGroup",
"ec2:DescribeSecurityGroups",
"ec2:DescribeAccountAttributes",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteSecurityGroup",
"ec2:RevokeSecurityGroupEgress"
],
"attributes": {
"ingress": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:AuthorizeSecurityGroupEgress"
],
"tags": [
"ec2:CreateTags",
"ec2:DeleteTags"
]
},
"destroy": [
"ec2:DeleteSecurityGroup"
],
"modify": [],
"plan": []
}
]
Update files.go with:
//go:embed aws_security_group.json
var securityGroup []byteOnce you have added the json import above you just need to update the lookup table, so we can read it and get the permissions:
func GetAWSResourcePermissions(result template) []interface{} {
TFLookup := map[string]interface{}{
"aws_s3_bucket": awsS3Bucket,
"aws_s3_bucket_acl": awsS3BucketACL,
+ "aws_security_group": awsSecurityGroup,Also add an example Terraform file into the folder terraform/backups.