├── .gitignore ├── README.md ├── check-terraform-version.sentinel ├── restrict-s3-buckets.sentinel ├── sentinel.hcl ├── terraform-sentinel-cis-policies └── sentinel.hcl └── terraform-sentinel-cost-control-policies ├── less-than-100-month.sentinel └── sentinel.hcl /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # Crash log files 9 | crash.log 10 | 11 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 12 | # .tfvars files are managed as part of configuration and so should be included in 13 | # version control. 14 | # 15 | # example.tfvars 16 | 17 | # Ignore override files as they are usually used to override resources locally and so 18 | # are not checked in 19 | override.tf 20 | override.tf.json 21 | *_override.tf 22 | *_override.tf.json 23 | 24 | # Include override files you do wish to add to version control using negated pattern 25 | # 26 | # !example_override.tf 27 | 28 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 29 | # example: *tfplan* 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-sentinel-policies 2 | Terraform Cloud and Sentinel Policies Demo 3 | -------------------------------------------------------------------------------- /check-terraform-version.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | v = strings.split(tfplan.terraform_version, ".") 5 | version_major = int(v[1]) 6 | version_minor = int(v[2]) 7 | 8 | main = rule { 9 | #version_major is 14 and version_minor >= 1 10 | version_major >= 14 11 | } -------------------------------------------------------------------------------- /restrict-s3-buckets.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | s3_buckets = filter tfplan.resource_changes as _, rc { 4 | rc.type is "aws_s3_bucket" and 5 | (rc.change.actions contains "create" or rc.change.actions is ["update"]) 6 | } 7 | 8 | required_tags = [ 9 | "Terraform", 10 | "Environment", 11 | ] 12 | 13 | allowed_acls = [ 14 | "public-read", 15 | ] 16 | 17 | bucket_tags = rule { 18 | all s3_buckets as _, instances { 19 | all required_tags as rt { 20 | instances.change.after.tags contains rt 21 | } 22 | } 23 | } 24 | 25 | acl_allowed = rule { 26 | all s3_buckets as _, buckets { 27 | buckets.change.after.acl in allowed_acls 28 | } 29 | } 30 | 31 | main = rule { 32 | (bucket_tags and acl_allowed) else false 33 | } 34 | -------------------------------------------------------------------------------- /sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "check-terraform-version" { 2 | source = "./check-terraform-version.sentinel" 3 | enforcement_level = "hard-mandatory" 4 | } 5 | 6 | policy "restrict-s3-buckets" { 7 | source = "./restrict-s3-buckets.sentinel" 8 | enforcement_level = "soft-mandatory" 9 | } -------------------------------------------------------------------------------- /terraform-sentinel-cis-policies/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "aws-cis-4.1-networking-deny-public-ssh-acl-rules" { 2 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.1-networking-deny-public-ssh-acl-rules/aws-cis-4.1-networking-deny-public-ssh-acl-rules.sentinel" 3 | enforcement_level = "advisory" 4 | } 5 | 6 | policy "aws-cis-4.2-networking-deny-public-rdp-acl-rules" { 7 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.2-networking-deny-public-rdp-acl-rules/aws-cis-4.2-networking-deny-public-rdp-acl-rules.sentinel" 8 | enforcement_level = "advisory" 9 | } 10 | 11 | policy "aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules" { 12 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules.sentinel" 13 | enforcement_level = "advisory" 14 | } -------------------------------------------------------------------------------- /terraform-sentinel-cost-control-policies/less-than-100-month.sentinel: -------------------------------------------------------------------------------- 1 | import "tfrun" 2 | import "decimal" 3 | 4 | delta_monthly_cost = decimal.new(tfrun.cost_estimate.delta_monthly_cost) 5 | 6 | main = rule { 7 | delta_monthly_cost.less_than(100) 8 | } -------------------------------------------------------------------------------- /terraform-sentinel-cost-control-policies/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "less-than-100-month" { 2 | source = "./less-than-100-month.sentinel" 3 | enforcement_level = "soft-mandatory" 4 | } --------------------------------------------------------------------------------