├── .gitignore ├── LICENSE ├── README.md ├── cloud-management-platform └── README.md ├── governance ├── README.md ├── first-generation │ ├── README.md │ ├── aws │ │ ├── README.md │ │ ├── aws-vpcs-must-have-tags-and-enable-dns-hostnames.sentinel │ │ ├── enforce-ami-owners.sentinel │ │ ├── enforce-mandatory-tags.sentinel │ │ ├── enforce-tag-from-data-source.sentinel │ │ ├── must_have_remote_exec_provisioner.sentinel │ │ ├── openshift-aws-cluster-policy.sentinel │ │ ├── require-private-acl-and-kms-for-s3-buckets.sentinel │ │ ├── require-vpc-and-kms-for-lambda-functions.sentinel │ │ ├── restrict-aws-availability-zones.sentinel │ │ ├── restrict-aws-cidr-blocks.sentinel │ │ ├── restrict-aws-instance-type.sentinel │ │ ├── restrict-aws-region.sentinel │ │ ├── restrict-iam-policy-statement.sentinel │ │ ├── restrict-iam-policy-statement2.sentinel │ │ └── sentinel.hcl │ ├── azure │ │ ├── README.md │ │ ├── acs-cluster-policy.sentinel │ │ ├── aks-cluster-policy.sentinel │ │ ├── block-allow-all-cidr.sentinel │ │ ├── enforce-mandatory-tags.sentinel │ │ ├── restrict-current-azure-vms.sentinel │ │ ├── restrict-vm-image-id.sentinel │ │ ├── restrict-vm-publisher.sentinel │ │ └── restrict-vm-size.sentinel │ ├── cloud-agnostic │ │ ├── README.md │ │ └── destroy-limit.sentinel │ ├── external │ │ ├── README.md │ │ ├── check_account.sh │ │ ├── check_account.tf │ │ └── check_account_balance.sentinel │ ├── gcp │ │ ├── README.md │ │ ├── block-allow-all-cidr.sentinel │ │ ├── enforce-mandatory-labels.sentinel │ │ ├── gke-cluster-policy.sentinel │ │ ├── pod_limit.sentinel │ │ └── restrict-machine-type.sentinel │ └── vmware │ │ ├── require-storage-drs.sentinel │ │ ├── require_nfs41_and_kerberos.sentinel │ │ ├── restrict-virtual-disk-size-and-type.sentinel │ │ ├── restrict-vm-cpu-and-memory.sentinel │ │ ├── restrict-vm-creation-hours │ │ └── restrict-vm-disk-size.sentinel ├── second-generation │ ├── README.md │ ├── aws │ │ ├── enforce-mandatory-tags.sentinel │ │ ├── mocks │ │ │ ├── ec2-instance-mock-tfconfig.sentinel │ │ │ ├── ec2-instance-mock-tfplan.sentinel │ │ │ ├── ec2-instance-mock-tfstate.sentinel │ │ │ ├── launch-configuration-mock-tfconfig.sentinel │ │ │ ├── launch-configuration-mock-tfplan.sentinel │ │ │ ├── launch-configuration-mock-tfstate.sentinel │ │ │ ├── rds-db-instance-mock-tfconfig.sentinel │ │ │ ├── rds-db-instance-mock-tfplan.sentinel │ │ │ ├── rds-db-instance-mock-tfstate.sentinel │ │ │ ├── s3-bucket-mock-tfconfig.sentinel │ │ │ ├── s3-bucket-mock-tfplan.sentinel │ │ │ ├── s3-bucket-mock-tfstate.sentinel │ │ │ ├── sgr-mock-tfconfig.sentinel │ │ │ ├── sgr-mock-tfplan.sentinel │ │ │ └── sgr-mock-tfstate.sentinel │ │ ├── require-private-acl-and-kms-for-s3-buckets.sentinel │ │ ├── restrict-ami-owners.sentinel │ │ ├── restrict-assumed-role-by-workspace.sentinel │ │ ├── restrict-assumed-role.sentinel │ │ ├── restrict-availability-zones.sentinel │ │ ├── restrict-db-instance-engines.sentinel │ │ ├── restrict-ec2-instance-type.sentinel │ │ ├── restrict-ingress-sg-rule-cidr-blocks.sentinel │ │ ├── restrict-launch-configuration-instance-type.sentinel │ │ ├── sentinel.hcl │ │ └── test │ │ │ ├── enforce-mandatory-tags │ │ │ ├── fail-missing-tags-0.11.json │ │ │ ├── fail-missing-tags-0.12.json │ │ │ ├── fail-no-tags-0.11.json │ │ │ ├── fail-no-tags-0.12.json │ │ │ ├── mock-tfplan-fail-missing-tags-0.11.sentinel │ │ │ ├── mock-tfplan-fail-missing-tags-0.12.sentinel │ │ │ ├── mock-tfplan-fail-no-tags-0.11.sentinel │ │ │ ├── mock-tfplan-fail-no-tags-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── require-private-acl-and-kms-for-s3-buckets │ │ │ ├── fail-acl-0.11.json │ │ │ ├── fail-acl-and-kms-0.11.json │ │ │ ├── fail-acl-and-kms-0.12.json │ │ │ ├── fail-kms-0.11.json │ │ │ ├── fail-kms-no-ssec-0.12.json │ │ │ ├── mock-tfplan-fail-acl-0.11.sentinel │ │ │ ├── mock-tfplan-fail-acl-and-kms-0.11.sentinel │ │ │ ├── mock-tfplan-fail-acl-and-kms-0.12.sentinel │ │ │ ├── mock-tfplan-fail-kms-0.11.sentinel │ │ │ ├── mock-tfplan-fail-kms-no-ssec-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-ami-owners │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfstate-fail-0.11.sentinel │ │ │ ├── mock-tfstate-fail-0.12.sentinel │ │ │ ├── mock-tfstate-pass-0.11.sentinel │ │ │ ├── mock-tfstate-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-assumed-role-by-workspace │ │ │ ├── fail-bad-role-0.11.json │ │ │ ├── fail-bad-role-0.12.json │ │ │ ├── fail-dev-0.11.json │ │ │ ├── fail-dev-0.12.json │ │ │ ├── fail-prod-0.11.json │ │ │ ├── fail-prod-0.12.json │ │ │ ├── fail-qa-0.11.json │ │ │ ├── fail-qa-0.12.json │ │ │ ├── mock-tfconfig-fail-bad-role-0.11.sentinel │ │ │ ├── mock-tfconfig-fail-bad-role-0.12.sentinel │ │ │ ├── mock-tfconfig-fail-dev-0.11.sentinel │ │ │ ├── mock-tfconfig-fail-dev-0.12.sentinel │ │ │ ├── mock-tfconfig-fail-prod-0.11.sentinel │ │ │ ├── mock-tfconfig-fail-prod-0.12.sentinel │ │ │ ├── mock-tfconfig-fail-qa-0.11.sentinel │ │ │ ├── mock-tfconfig-fail-qa-0.12.sentinel │ │ │ ├── mock-tfconfig-pass-dev-0.11.sentinel │ │ │ ├── mock-tfconfig-pass-dev-0.12.sentinel │ │ │ ├── mock-tfconfig-pass-prod-0.11.sentinel │ │ │ ├── mock-tfconfig-pass-prod-0.12.sentinel │ │ │ ├── mock-tfconfig-pass-qa-0.11.sentinel │ │ │ ├── mock-tfconfig-pass-qa-0.12.sentinel │ │ │ ├── mock-tfplan-fail-bad-role-0.11.sentinel │ │ │ ├── mock-tfplan-fail-bad-role-0.12.sentinel │ │ │ ├── mock-tfplan-fail-dev-0.11.sentinel │ │ │ ├── mock-tfplan-fail-dev-0.12.sentinel │ │ │ ├── mock-tfplan-fail-prod-0.11.sentinel │ │ │ ├── mock-tfplan-fail-prod-0.12.sentinel │ │ │ ├── mock-tfplan-fail-qa-0.11.sentinel │ │ │ ├── mock-tfplan-fail-qa-0.12.sentinel │ │ │ ├── mock-tfplan-pass-dev-0.11.sentinel │ │ │ ├── mock-tfplan-pass-dev-0.12.sentinel │ │ │ ├── mock-tfplan-pass-prod-0.11.sentinel │ │ │ ├── mock-tfplan-pass-prod-0.12.sentinel │ │ │ ├── mock-tfplan-pass-qa-0.11.sentinel │ │ │ ├── mock-tfplan-pass-qa-0.12.sentinel │ │ │ ├── mock-tfrun-dev.sentinel │ │ │ ├── mock-tfrun-prod.sentinel │ │ │ ├── mock-tfrun-qa.sentinel │ │ │ ├── pass-dev-0.11.json │ │ │ ├── pass-dev-0.12.json │ │ │ ├── pass-prod-0.11.json │ │ │ ├── pass-prod-0.12.json │ │ │ ├── pass-qa-0.11.json │ │ │ └── pass-qa-0.12.json │ │ │ ├── restrict-assumed-role │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-availability-zones │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-db-instance-engines │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-ec2-instance-type │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-ingress-sg-rule-cidr-blocks │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── mock-tfplan-pass-no-cidr-blocks-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ ├── pass-0.12.json │ │ │ └── pass-no-cidr-blocks-0.12.json │ │ │ └── restrict-launch-configuration-instance-type │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ ├── azure │ │ ├── enforce-mandatory-tags.sentinel │ │ ├── mocks │ │ │ ├── app-service-mock-tfconfig.sentinel │ │ │ ├── app-service-mock-tfplan.sentinel │ │ │ ├── app-service-mock-tfstate.sentinel │ │ │ ├── network-and-vms-mock-tfconfig.sentinel │ │ │ ├── network-and-vms-mock-tfplan.sentinel │ │ │ └── network-and-vms-mock-tfstate.sentinel │ │ ├── restrict-app-service-to-https.sentinel │ │ ├── restrict-publishers-of-current-vms.sentinel │ │ ├── restrict-vm-size.sentinel │ │ ├── sentinel.hcl │ │ └── test │ │ │ ├── enforce-mandatory-tags │ │ │ ├── fail-missing-tag-0.11.json │ │ │ ├── fail-missing-tag-0.12.json │ │ │ ├── fail-no-tags-0.11.json │ │ │ ├── fail-no-tags-0.12.json │ │ │ ├── mock-tfplan-fail-missing-tag-0.11.sentinel │ │ │ ├── mock-tfplan-fail-missing-tag-0.12.sentinel │ │ │ ├── mock-tfplan-fail-no-tags-0.11.sentinel │ │ │ ├── mock-tfplan-fail-no-tags-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ ├── restrict-app-service-to-https │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ └── pass-0.12.json │ │ │ ├── restrict-publishers-of-current-vms │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfstate-fail-0.11.sentinel │ │ │ ├── mock-tfstate-fail-0.12.sentinel │ │ │ ├── mock-tfstate-pass-0.11.sentinel │ │ │ ├── mock-tfstate-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ └── restrict-vm-size │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ ├── cloud-agnostic │ │ ├── allowed-resources.sentinel │ │ ├── http-examples │ │ │ ├── README.md │ │ │ ├── asteroids.sentinel │ │ │ ├── check-external-http-api.sentinel │ │ │ ├── mocks │ │ │ │ └── mock-tfconfig-fail-0.12.sentinel │ │ │ ├── sentinel.hcl │ │ │ ├── sentinel.json │ │ │ ├── test │ │ │ │ ├── asteroids │ │ │ │ │ ├── fail.json │ │ │ │ │ └── pass.json │ │ │ │ ├── check-external-http-api │ │ │ │ │ └── test.json │ │ │ │ └── use-latest-module-versions │ │ │ │ │ ├── fail-0.11.json │ │ │ │ │ ├── fail-0.12.json │ │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ │ ├── mock-tfconfig-pass-no-pmr-modules-0.11.sentinel │ │ │ │ │ ├── mock-tfconfig-pass-no-pmr-modules-0.12.sentinel │ │ │ │ │ ├── mock-tfconfig-pass-valid-versions-0.11.sentinel │ │ │ │ │ ├── mock-tfconfig-pass-valid-versions-0.12.sentinel │ │ │ │ │ ├── pass-no-pmr-modules-0.11.json │ │ │ │ │ ├── pass-no-pmr-modules-0.12.json │ │ │ │ │ ├── pass-valid-versions-0.11.json │ │ │ │ │ └── pass-valid-versions-0.12.json │ │ │ └── use-latest-module-versions.sentinel │ │ ├── limit-cost-by-workspace-type.sentinel │ │ ├── limit-proposed-monthly-cost.sentinel │ │ ├── prevent-destruction-of-prohibited-resources.sentinel │ │ ├── prevent-non-root-providers.sentinel │ │ ├── prevent-remote-exec-provisioners-on-null-resources.sentinel │ │ ├── prohibited-datasources.sentinel │ │ ├── prohibited-providers.sentinel │ │ ├── prohibited-provisioners.sentinel │ │ ├── prohibited-resources.sentinel │ │ ├── require-all-resources-from-pmr.sentinel │ │ ├── restrict-cost-and-percentage-increase.sentinel │ │ ├── sentinel.hcl │ │ ├── test │ │ │ ├── allowed-resources │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ │ └── pass-0.12.json │ │ │ ├── limit-cost-by-workspace-type │ │ │ │ ├── fail-dev-0.12.json │ │ │ │ ├── fail-other-0.12.json │ │ │ │ ├── fail-prod-0.12.json │ │ │ │ ├── fail-qa-0.12.json │ │ │ │ ├── mock-tfrun-fail-dev-0.12.sentinel │ │ │ │ ├── mock-tfrun-fail-other-0.12.sentinel │ │ │ │ ├── mock-tfrun-fail-prod-0.12.sentinel │ │ │ │ ├── mock-tfrun-fail-qa-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-dev-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-no-estimates-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-other-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-prod-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-qa-0.12.sentinel │ │ │ │ ├── pass-dev-0.12.json │ │ │ │ ├── pass-no-estimates-0.12.json │ │ │ │ ├── pass-other-0.12.json │ │ │ │ ├── pass-prod-0.12.json │ │ │ │ └── pass-qa-0.12.json │ │ │ ├── limit-proposed-monthly-cost │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfrun-fail-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-no-estimates-0.12.sentinel │ │ │ │ ├── pass-0.12.json │ │ │ │ └── pass-no-estimates-0.12.json │ │ │ ├── prevent-destruction-of-prohibited-resources │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── prevent-non-root-providers │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── prevent-remote-exec-provisioners-on-null-resources │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── prohibited-datasources │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── prohibited-providers │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── prohibited-provisioners │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ └── pass-0.12.json │ │ │ ├── prohibited-resources │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ │ └── pass-0.12.json │ │ │ ├── require-all-resources-from-pmr │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ │ ├── restrict-cost-and-percentage-increase │ │ │ │ ├── fail-limit-0.12.json │ │ │ │ ├── fail-percent-increase-0.12.json │ │ │ │ ├── mock-tfrun-fail-limit-0.12.sentinel │ │ │ │ ├── mock-tfrun-fail-percent-increase-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-0.12.sentinel │ │ │ │ ├── mock-tfrun-pass-no-estimates-0.12.sentinel │ │ │ │ ├── pass-0.12.json │ │ │ │ └── pass-no-estimates-0.12.json │ │ │ └── validate-all-variables-have-descriptions │ │ │ │ ├── fail-0.11.json │ │ │ │ ├── fail-0.12.json │ │ │ │ ├── mock-tfconfig-fail-0.11.sentinel │ │ │ │ ├── mock-tfconfig-fail-0.12.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.11.sentinel │ │ │ │ ├── mock-tfconfig-pass-0.12.sentinel │ │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ │ ├── pass-0.11.json │ │ │ │ └── pass-0.12.json │ │ └── validate-all-variables-have-descriptions.sentinel │ ├── common-functions │ │ ├── README.md │ │ ├── config │ │ │ ├── find_all_provisioners.md │ │ │ ├── find_all_provisioners.sentinel │ │ │ ├── find_datasources_from_config.md │ │ │ ├── find_datasources_from_config.sentinel │ │ │ ├── find_provider_aliases.md │ │ │ ├── find_provider_aliases.sentinel │ │ │ ├── find_resources_from_config.md │ │ │ ├── find_resources_from_config.sentinel │ │ │ ├── find_variables_in_config.md │ │ │ └── find_variables_in_config.sentinel │ │ ├── plan │ │ │ ├── find_datasources_from_plan.md │ │ │ ├── find_datasources_from_plan.sentinel │ │ │ ├── find_resource_types_from_plan.md │ │ │ ├── find_resource_types_from_plan.sentinel │ │ │ ├── find_resources_from_plan.md │ │ │ ├── find_resources_from_plan.sentinel │ │ │ ├── validate_attribute_contains_list.md │ │ │ ├── validate_attribute_contains_list.sentinel │ │ │ ├── validate_attribute_greater_than_value.md │ │ │ ├── validate_attribute_greater_than_value.sentinel │ │ │ ├── validate_attribute_has_value.md │ │ │ ├── validate_attribute_has_value.sentinel │ │ │ ├── validate_attribute_in_list.md │ │ │ ├── validate_attribute_in_list.sentinel │ │ │ ├── validate_attribute_less_than_value.md │ │ │ ├── validate_attribute_less_than_value.sentinel │ │ │ ├── validate_attribute_matches_expression.md │ │ │ ├── validate_attribute_matches_expression.sentinel │ │ │ ├── validate_destroyed_resources.md │ │ │ └── validate_destroyed_resources.sentinel │ │ └── state │ │ │ ├── find_datasources_from_state.md │ │ │ ├── find_datasources_from_state.sentinel │ │ │ ├── find_resources_from_state.md │ │ │ └── find_resources_from_state.sentinel │ ├── gcp │ │ ├── enforce-mandatory-labels.sentinel │ │ ├── mocks │ │ │ ├── gce-instance-mock-tfconfig.sentinel │ │ │ ├── gce-instance-mock-tfplan.sentinel │ │ │ └── gce-instance-mock-tfstate.sentinel │ │ ├── restrict-gce-machine-type.sentinel │ │ ├── sentinel.hcl │ │ └── test │ │ │ ├── enforce-mandatory-labels │ │ │ ├── fail-missing-labels-0.11.json │ │ │ ├── fail-missing-labels-0.12.json │ │ │ ├── fail-no-labels-0.11.json │ │ │ ├── fail-no-labels-0.12.json │ │ │ ├── mock-tfplan-fail-missing-labels-0.11.sentinel │ │ │ ├── mock-tfplan-fail-missing-labels-0.12.sentinel │ │ │ ├── mock-tfplan-fail-no-labels-0.11.sentinel │ │ │ ├── mock-tfplan-fail-no-labels-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ │ │ └── restrict-gce-machine-type │ │ │ ├── fail-0.11.json │ │ │ ├── fail-0.12.json │ │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ │ ├── pass-0.11.json │ │ │ └── pass-0.12.json │ └── vmware │ │ ├── mocks │ │ ├── vsphere-test-mock-tfconfig.sentinel │ │ ├── vsphere-test-mock-tfplan.sentinel │ │ └── vsphere-test-mock-tfstate.sentinel │ │ ├── restrict-vm-cpu-and-memory.sentinel │ │ ├── restrict-vm-disk-size.sentinel │ │ ├── sentinel.hcl │ │ └── test │ │ ├── restrict-vm-cpu-and-memory │ │ ├── fail-cpu-0.11.json │ │ ├── fail-cpu-and-memory-0.11.json │ │ ├── fail-cpu-and-memory-0.12.json │ │ ├── fail-memory-0.11.json │ │ ├── mock-tfplan-fail-cpu-0.11.sentinel │ │ ├── mock-tfplan-fail-cpu-and-memory-0.11.sentinel │ │ ├── mock-tfplan-fail-cpu-and-memory-0.12.sentinel │ │ ├── mock-tfplan-fail-memory-0.11.sentinel │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ ├── pass-0.11.json │ │ └── pass-0.12.json │ │ └── restrict-vm-disk-size │ │ ├── fail-0.11.json │ │ ├── fail-0.12.json │ │ ├── mock-tfplan-fail-0.11.sentinel │ │ ├── mock-tfplan-fail-0.12.sentinel │ │ ├── mock-tfplan-pass-0.11.sentinel │ │ ├── mock-tfplan-pass-0.12.sentinel │ │ ├── pass-0.11.json │ │ └── pass-0.12.json └── third-generation │ └── README.md ├── infrastructure-as-code ├── README.md ├── aws-ec2-instance │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── aws-lambda-ec2-lifecycles │ ├── README.md │ ├── asg_data_collectors.tf │ ├── asg_reaper.tf │ ├── asg_untagged_janitor.tf │ ├── assets │ │ ├── aws_bot.png │ │ ├── dummy_event.png │ │ └── good_morning.png │ ├── ec2_data_collectors.tf │ ├── ec2_reaper.tf │ ├── ec2_untagged_janitor.tf │ ├── encryption.tf.disabled │ ├── files │ │ ├── ASGJanitor.py │ │ ├── ASGJanitor.zip │ │ ├── ASGReaper.py │ │ ├── ASGReaper.zip │ │ ├── EC2Janitor.py │ │ ├── EC2Janitor.zip │ │ ├── EC2Reaper.py │ │ ├── EC2Reaper.zip │ │ ├── getInstanceReport.py │ │ ├── getInstanceReport.zip │ │ ├── getRunningInstances.py │ │ ├── getRunningInstances.zip │ │ ├── getTaggedASGs.py │ │ ├── getTaggedASGs.zip │ │ ├── getTaggedInstances.py │ │ ├── getTaggedInstances.zip │ │ ├── getUntaggedASGs.py │ │ ├── getUntaggedASGs.zip │ │ ├── getUntaggedInstances.py │ │ ├── getUntaggedInstances.zip │ │ ├── iam_decrypt_kms.tpl │ │ ├── iam_lambda_notify.tpl │ │ ├── iam_lambda_read_instances.tpl │ │ ├── iam_lambda_stop_and_terminate_instances.tpl │ │ ├── iam_lambda_terminate_asgs.tpl │ │ ├── notifyInstanceUsage.py │ │ ├── notifyInstanceUsage.zip │ │ ├── notifyUntaggedInstances.py │ │ └── notifyUntaggedInstances.zip │ ├── iam_roles.tf │ ├── main.tf │ ├── notify_instance_usage.tf │ ├── notify_untagged.tf │ ├── outputs.tf │ └── variables.tf ├── azure-vm │ ├── README.md │ └── main.tf ├── dynamic-aws-creds-from-vault │ ├── LICENSE │ ├── README.md │ ├── main.tf │ ├── networks-firewalls-ingress.tf │ ├── networks-firewalls.tf │ ├── networks-gateways.tf │ ├── networks-routes.tf │ ├── networks-subnets.tf │ ├── networks.tf │ ├── outputs.tf │ └── variables.tf ├── dynamic-aws-creds │ ├── README.md │ ├── assets │ │ ├── dynamic-iam-creds-iam-ec2-policy.png │ │ ├── dynamic-iam-creds-iam-policy.png │ │ ├── dynamic-iam-creds.png │ │ └── ec2-instance.png │ ├── consumer-workspace │ │ └── main.tf │ └── producer-workspace │ │ └── main.tf ├── gcp-compute-instance │ ├── README.md │ └── main.tf ├── hashistack │ ├── .gitignore │ ├── README.md │ ├── best-practices │ │ └── terraform-aws │ │ │ ├── README.md │ │ │ ├── gitignore.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── terraform.auto.tfvars │ │ │ └── variables.tf │ ├── dev │ │ ├── terraform-aws │ │ │ ├── README.md │ │ │ ├── gitignore.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── terraform.auto.tfvars │ │ │ └── variables.tf │ │ ├── terraform-azure │ │ │ ├── README.md │ │ │ ├── _interface.tf │ │ │ ├── env.sh │ │ │ ├── main.tf │ │ │ ├── modules │ │ │ │ ├── consul-azure │ │ │ │ │ ├── _interface.tf │ │ │ │ │ ├── init-cluster.tpl │ │ │ │ │ ├── instances-consul.tf │ │ │ │ │ └── main.tf │ │ │ │ ├── images-azure │ │ │ │ │ └── _interface.tf │ │ │ │ ├── network-azure │ │ │ │ │ ├── README.md │ │ │ │ │ ├── _interface.tf │ │ │ │ │ ├── firewalls-jumphost.tf │ │ │ │ │ ├── instances-jumphost.tf │ │ │ │ │ ├── main.tf │ │ │ │ │ ├── networks.tf │ │ │ │ │ └── subnets.tf │ │ │ │ └── ssh-keypair-data │ │ │ │ │ ├── _interface.tf │ │ │ │ │ └── main.tf │ │ │ └── terraform.tfvars.example │ │ ├── terraform-gcp │ │ │ ├── README.md │ │ │ ├── _interface.tf │ │ │ ├── main.tf │ │ │ └── terraform.tfvars.example │ │ └── vagrant-local │ │ │ ├── README.md │ │ │ └── Vagrantfile │ ├── quick-start │ │ └── terraform-aws │ │ │ ├── README.md │ │ │ ├── gitignore.tf │ │ │ ├── main.tf │ │ │ ├── outputs.tf │ │ │ ├── terraform.auto.tfvars │ │ │ └── variables.tf │ └── templates │ │ ├── best-practices-bastion-systemd.sh.tpl │ │ ├── best-practices-hashistack-systemd.sh.tpl │ │ ├── install-base.sh.tpl │ │ ├── install-consul-systemd.sh.tpl │ │ ├── install-docker.sh.tpl │ │ ├── install-java.sh.tpl │ │ ├── install-nomad-systemd.sh.tpl │ │ ├── install-vault-systemd.sh.tpl │ │ ├── quick-start-bastion-systemd.sh.tpl │ │ └── quick-start-hashistack-systemd.sh.tpl ├── k8s-cluster-aks │ ├── README.md │ ├── aks-cluster-policy.sentinel │ ├── ca_certificate │ ├── client_certificate │ ├── client_key │ ├── config │ ├── k8s.tfvars.example │ ├── main.tf │ ├── outputs.tf │ ├── private_key.pem │ ├── sample-policy.hcl │ └── variables.tf ├── k8s-cluster-gke │ ├── README.md │ ├── gke-cluster-policy.sentinel │ ├── main.tf │ ├── outputs.tf │ ├── sample-policy.hcl │ └── variables.tf ├── k8s-cluster-openshift-aws │ ├── README.md │ ├── ca_certificate │ ├── client_certificate │ ├── client_key │ ├── config │ ├── delay-vault-aws │ ├── main.tf │ ├── modules │ │ └── openshift │ │ │ ├── 00-variables.tf │ │ │ ├── 01-amis.tf │ │ │ ├── 02-vpc.tf │ │ │ ├── 03-security-groups.tf │ │ │ ├── 04-roles.tf │ │ │ ├── 05-nodes.tf │ │ │ ├── 06-dns.tf │ │ │ ├── 07-bastion.tf │ │ │ ├── 08-outputs.tf │ │ │ ├── delay-aws │ │ │ └── files │ │ │ ├── install-from-bastion.sh │ │ │ ├── setup-master.sh │ │ │ └── setup-node.sh │ ├── openshift-aws-cluster-policy.sentinel │ ├── openshift.tfvars.example │ ├── outputs.tf │ ├── sample-policy.hcl │ ├── scripts │ │ ├── postinstall-master.sh │ │ └── postinstall-node.sh │ ├── variables.tf │ ├── vault-reviewer-rbac.yaml │ ├── vault-reviewer-token │ └── vault-reviewer.yaml ├── k8s-vault-config │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── vault-reviewer-token ├── s3-buckets-and-policies │ ├── README.md │ └── main.tf ├── sagemaker-notebook │ ├── README.md │ └── main.tf ├── terraform-0.12-examples │ ├── README.md │ ├── advanced-dynamic-blocks │ │ ├── README.md │ │ ├── main.tf │ │ └── terraform.tfvars │ ├── dynamic-blocks-and-splat-expressions │ │ ├── README.md │ │ └── main.tf │ ├── first-class-expressions │ │ ├── README.md │ │ └── main.tf │ ├── for-each-for-resources │ │ ├── README.md │ │ └── main.tf │ ├── for-expressions │ │ ├── README.md │ │ ├── lists-and-maps-with-for.tf │ │ └── main.tf │ ├── new-template-syntax │ │ ├── README.md │ │ ├── actual_vote.txt │ │ ├── main.tf │ │ └── rigged_vote.txt │ ├── reliable-json-syntax │ │ ├── README.md │ │ ├── variable-correct.tf.txt │ │ ├── variable-with-comment.tf.txt │ │ ├── variable1.tf.json │ │ ├── variable2.tf.txt │ │ ├── variable3.tf.txt │ │ └── variable4.tf.txt │ └── rich-value-types │ │ ├── README.md │ │ ├── main.tf │ │ └── network │ │ ├── main.tf │ │ ├── outputs.tf │ │ └── variables.tf ├── terraform-0.13-examples │ ├── README.md │ └── module-depends-on │ │ ├── README.md │ │ ├── main-1.tf │ │ ├── main-2.tf.txt │ │ ├── main-3.tf.txt │ │ └── modules │ │ ├── read-files-complicated │ │ └── main.tf │ │ ├── read-files │ │ └── main.tf │ │ ├── write-files-complicated │ │ └── main.tf │ │ └── write-files │ │ └── main.tf └── terraform-gcp-cloudsql │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── examples │ ├── prod-and-dev │ │ ├── README.md │ │ └── main.tf │ └── simple │ │ ├── README.md │ │ └── main.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── operations ├── README.md ├── automation-script │ ├── README.md │ ├── config │ │ └── main.tf │ ├── deleteWorkspace.sh │ ├── loadAndRunWorkspace-jq.sh │ ├── loadAndRunWorkspace-python.sh │ ├── restrict-name-variable.sentinel │ └── variables.csv ├── sentinel-policies-scripts │ ├── README.md │ ├── create-policy-set-version.sh │ ├── delete_policies.sh │ ├── export_policies.sh │ ├── import_policies.sh │ └── policy-set │ │ ├── restrict-s3-bucket-policies.sentinel │ │ ├── restrict-sagemaker-notebooks.sentinel │ │ └── sentinel.hcl └── variable-scripts │ ├── README.md │ ├── delete-variables.sh │ ├── hcl-variables.csv │ ├── other-variables.csv │ ├── set-variables.sh │ └── variables.csv └── self-serve-infrastructure ├── README.md ├── cats-and-dogs ├── README.md ├── backend │ ├── Dockerfile │ └── vote-db │ │ └── start_redis.sh └── frontend │ ├── Dockerfile │ └── azure-vote │ ├── config_file.cfg │ ├── main.py │ ├── static │ └── default.css │ └── templates │ └── index.html ├── getting-started ├── README.md ├── terraform-aws │ ├── _interface.tf │ ├── main.tf │ ├── outputs.tf │ └── terraform.auto.tfvars ├── terraform-azure │ ├── _interface.tf │ ├── main.tf │ ├── outputs.tf │ └── terraform.auto.tfvars └── terraform-gcp │ ├── _interface.tf │ ├── main.tf │ ├── outputs.tf │ └── terraform.auto.tfvars ├── k8s-services-openshift ├── README.md ├── cats-and-dogs-secret-name ├── cats-and-dogs.yaml ├── main.tf ├── openshift.tfvars.example ├── outputs.tf └── variables.tf └── k8s-services ├── README.md ├── main.tf ├── outputs.tf └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.tfstate 3 | *.tfstate.backup 4 | *.tfstate.lock.info 5 | 6 | # logs 7 | *.log 8 | 9 | # Directories 10 | .terraform/ 11 | .vagrant/ 12 | 13 | # SSH Keys 14 | *.pem 15 | 16 | # Backup files 17 | *.bak 18 | 19 | # Ignored Terraform files 20 | *gitignore*.tf 21 | 22 | # Ignore Mac .DS_Store files 23 | .DS_Store 24 | 25 | # Ignored vscode files 26 | .vscode/ 27 | 28 | # Ignore Any Generated JSON Files 29 | operations/automation-script/apply.json 30 | operations/automation-script/configversion.json 31 | operations/automation-script/run.template.json 32 | operations/automation-script/run.json 33 | operations/automation-script/variable.template.json 34 | operations/automation-script/variable.json 35 | operations/automation-script/workspace.template.json 36 | operations/automation-script/workspace.json 37 | operations/sentinel-policies-scripts/create-policy.template.json 38 | operations/sentinel-policies-scripts/create-policy.json 39 | operations/variable-scripts/variable.template.json 40 | operations/variable-scripts/variable.json 41 | 42 | # Sentinel runtime directory 43 | .sentinel 44 | -------------------------------------------------------------------------------- /cloud-management-platform/README.md: -------------------------------------------------------------------------------- 1 | # Cloud Management Platform 2 | To be implemented. 3 | -------------------------------------------------------------------------------- /governance/first-generation/aws/README.md: -------------------------------------------------------------------------------- 1 | # Sentinel Policies for AWS 2 | The sample Sentinel policy files in this directory can be used with Terraform Enterprise to ensure that provisioned AWS VPCs, EC2 instances, S3 buckets, Lambda functions, and other resources comply with your organization's provisioning rules. There are also policies that restrict AMI owner IDs and the region or availability zones into which resources can be provisioned. 3 | -------------------------------------------------------------------------------- /governance/first-generation/aws/aws-vpcs-must-have-tags-and-enable-dns-hostnames.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all AWS vpcs from all modules 4 | get_vpcs = func() { 5 | vpcs = [] 6 | for tfplan.module_paths as path { 7 | vpcs += values(tfplan.module(path).resources.aws_vpc) else [] 8 | } 9 | return vpcs 10 | } 11 | 12 | vpcs = get_vpcs() 13 | 14 | vpc_must_have_tags = rule { 15 | all vpcs as name, instances { 16 | all instances as index, r { 17 | (length(r.applied.tags) else 0) > 0 18 | } 19 | } 20 | } 21 | 22 | vpc_hostnames_true = rule { 23 | all vpcs as name, instances { 24 | all instances as index, r { 25 | r.applied.enable_dns_hostnames == true 26 | } 27 | } 28 | } 29 | 30 | main = rule { 31 | (vpc_must_have_tags and vpc_hostnames_true) else true 32 | } 33 | -------------------------------------------------------------------------------- /governance/first-generation/aws/enforce-mandatory-tags.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Warning, this is case sensitive. 4 | # This is on purpose especially for organizations that do cost analysis on tag names. 5 | # where case sensitivity will cause grouping issues 6 | 7 | mandatory_tags = [ 8 | "TTL", 9 | "Owner", 10 | ] 11 | 12 | # Get all AWS instances contained in all modules being used 13 | get_aws_instances = func() { 14 | instances = [] 15 | for tfplan.module_paths as path { 16 | instances += values(tfplan.module(path).resources.aws_instance) else [] 17 | } 18 | return instances 19 | } 20 | 21 | aws_instances = get_aws_instances() 22 | 23 | # Instance tag rule 24 | instance_tags = rule { 25 | all aws_instances as _, instances { 26 | all instances as index, r { 27 | all mandatory_tags as t { 28 | r.applied.tags contains t 29 | } 30 | } 31 | } 32 | } 33 | 34 | main = rule { 35 | (instance_tags) else true 36 | } 37 | -------------------------------------------------------------------------------- /governance/first-generation/aws/must_have_remote_exec_provisioner.sentinel: -------------------------------------------------------------------------------- 1 | import "tfconfig" 2 | 3 | main = rule { 4 | all tfconfig.resources.aws_instance as _, r { 5 | any r.provisioners as _, p { 6 | p.type == "remote-exec" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/first-generation/aws/openshift-aws-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all master instances from openshift module 4 | get_master_instances = func() { 5 | instances = values(tfplan.module(["openshift"]).resources.aws_instance.master) else [] 6 | return instances 7 | } 8 | 9 | masters = get_master_instances() 10 | 11 | # Rule to restrict Master instance type 12 | master_type_allowed = rule { 13 | all masters as index, r { 14 | r.applied.instance_type is "m4.xlarge" 15 | } 16 | } 17 | 18 | # Get all bastion instances from openshift module 19 | get_bastion_instances = func() { 20 | instances = values(tfplan.module(["openshift"]).resources.aws_instance.bastion) else [] 21 | return instances 22 | } 23 | 24 | bastions = get_bastion_instances() 25 | 26 | # Rule to restrict Bastion instance type 27 | bastion_type_allowed = rule { 28 | all bastions as index, r { 29 | r.applied.instance_type is "t2.micro" 30 | } 31 | } 32 | 33 | # Main rule that requires other rules to be true 34 | main = rule { 35 | (master_type_allowed and bastion_type_allowed) else true 36 | } 37 | -------------------------------------------------------------------------------- /governance/first-generation/aws/require-private-acl-and-kms-for-s3-buckets.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all S3 buckets from all modules 4 | get_s3_buckets = func() { 5 | buckets = [] 6 | for tfplan.module_paths as path { 7 | buckets += values(tfplan.module(path).resources.aws_s3_bucket) else [] 8 | } 9 | return buckets 10 | } 11 | 12 | s3_buckets = get_s3_buckets() 13 | 14 | # Allowed S3 ACLs 15 | # Don't allow public-read-write 16 | allowed_acls = [ 17 | "private", 18 | ] 19 | 20 | # Rule to restrict S3 bucket ACLs 21 | acl_allowed = rule { 22 | all s3_buckets as _, instances { 23 | all instances as index, r { 24 | r.applied.acl in allowed_acls 25 | } 26 | } 27 | } 28 | 29 | # Rule to require server-side encryption 30 | require_encryption = rule { 31 | all s3_buckets as _, instances { 32 | all instances as index, r { 33 | (length(r.applied.server_side_encryption_configuration) > 0 and r.applied.server_side_encryption_configuration[0]["rule"][0].apply_server_side_encryption_by_default[0].sse_algorithm is "aws:kms") else false 34 | } 35 | } 36 | } 37 | 38 | # Main rule that requires other rules to be true 39 | main = rule { 40 | (acl_allowed and require_encryption) else true 41 | } 42 | 43 | -------------------------------------------------------------------------------- /governance/first-generation/aws/require-vpc-and-kms-for-lambda-functions.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all Lambda functions from all modules 4 | get_lambda_functions = func() { 5 | lambdas = [] 6 | for tfplan.module_paths as path { 7 | lambdas += values(tfplan.module(path).resources.aws_lambda_function) else [] 8 | } 9 | return lambdas 10 | } 11 | 12 | lambda_functions = get_lambda_functions() 13 | 14 | # Rule to require KMS key 15 | require_kms_key = rule { 16 | all lambda_functions as _, instances { 17 | all instances as index, r { 18 | (r.applied.kms_key_arn is not "") else false 19 | } 20 | } 21 | } 22 | 23 | # Rule to require VPC 24 | require_vpc = rule { 25 | all lambda_functions as _, instances { 26 | all instances as index, r { 27 | (length(r.applied.vpc_config) > 0 and 28 | length(r.applied.vpc_config[0].security_group_ids) > 0 and 29 | length(r.applied.vpc_config[0].subnet_ids) > 0) else false 30 | } 31 | } 32 | } 33 | 34 | # Main rule that requires other rules to be true 35 | main = rule { 36 | (require_kms_key and require_vpc) else true 37 | } 38 | 39 | -------------------------------------------------------------------------------- /governance/first-generation/aws/restrict-aws-availability-zones.sentinel: -------------------------------------------------------------------------------- 1 | # NOTE that you must explicitly specify availability_zone on all aws_instances 2 | # or this policy will fail since the computed availability_zone is not available 3 | # to plan 4 | 5 | import "tfplan" 6 | 7 | # Get all AWS instances from all modules 8 | get_aws_instances = func() { 9 | instances = [] 10 | for tfplan.module_paths as path { 11 | instances += values(tfplan.module(path).resources.aws_instance) else [] 12 | } 13 | return instances 14 | } 15 | 16 | # Allowed availability zones 17 | allowed_zones = [ 18 | "us-east-1a", 19 | "us-east-1b", 20 | "us-east-1c", 21 | "us-east-1d", 22 | "us-east-1e", 23 | "us-east-1f", 24 | ] 25 | 26 | aws_instances = get_aws_instances() 27 | 28 | # Rule to restrict availability zones and region 29 | region_allowed = rule { 30 | all aws_instances as _, instances { 31 | all instances as index, r { 32 | r.applied.availability_zone in allowed_zones 33 | } 34 | } 35 | } 36 | 37 | # Main rule that requires other rules to be true 38 | main = rule { 39 | (region_allowed) else true 40 | } 41 | -------------------------------------------------------------------------------- /governance/first-generation/aws/restrict-aws-cidr-blocks.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | disallowed_cidr_blocks = [ 4 | "0.0.0.0/0", 5 | ] 6 | 7 | main = rule { 8 | all tfplan.resources.aws_security_group as _, instances { 9 | all instances as _, sg { 10 | all sg.applied.ingress as ingress { 11 | all disallowed_cidr_blocks as block { 12 | ingress.cidr_blocks not contains block 13 | } 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /governance/first-generation/aws/restrict-aws-instance-type.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all AWS instances from all modules 4 | get_aws_instances = func() { 5 | instances = [] 6 | for tfplan.module_paths as path { 7 | instances += values(tfplan.module(path).resources.aws_instance) else [] 8 | } 9 | return instances 10 | } 11 | 12 | # Allowed Types 13 | allowed_types = [ 14 | "t2.small", 15 | "t2.medium", 16 | "t2.large", 17 | ] 18 | 19 | aws_instances = get_aws_instances() 20 | 21 | # Rule to restrict instance types 22 | instance_type_allowed = rule { 23 | all aws_instances as _, instances { 24 | all instances as index, r { 25 | r.applied.instance_type in allowed_types 26 | } 27 | } 28 | } 29 | 30 | # Main rule that requires other rules to be true 31 | main = rule { 32 | (instance_type_allowed) else true 33 | } 34 | -------------------------------------------------------------------------------- /governance/first-generation/aws/restrict-iam-policy-statement.sentinel: -------------------------------------------------------------------------------- 1 | import "json" 2 | import "tfplan" 3 | 4 | # get all IAM policy resources from the tfplan 5 | all_policy_resources = func() { 6 | policies = [] 7 | for tfplan.module_paths as path { 8 | resources = values(tfplan.module(path).resources.aws_iam_policy) else [] 9 | for resources as _, r { 10 | policies += values(r) 11 | } 12 | } 13 | 14 | return policies 15 | } 16 | 17 | # get all IAM Policy statements 18 | policy_statements = func() { 19 | statements = [] 20 | for all_policy_resources() as r { 21 | statements += json.unmarshal(r.applied.policy).Statement 22 | } 23 | return statements 24 | } 25 | 26 | valid_statement = func(s) { 27 | if s.Action contains "iam:PassRole" { 28 | return s.Resource is not "*" 29 | } 30 | 31 | return true 32 | } 33 | 34 | # Main rule that requires other rules to be true 35 | main = rule { 36 | all policy_statements() as s { 37 | valid_statement(s) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /governance/first-generation/aws/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "restrict-aws-region" { 2 | enforcement_level = "soft-mandatory" 3 | } -------------------------------------------------------------------------------- /governance/first-generation/azure/README.md: -------------------------------------------------------------------------------- 1 | # Sentinel Policies for Azure 2 | The sample Sentinel policy files in this directory can be used with Terraform Enterprise to ensure that provisioned Azure security groups, VMs, and ACS clusters comply with your organization's provisioning rules. 3 | 4 | The restrict-current-azure-vms.sentinel policy is interesting because it actually checks VMs that have already been provisioned using the tfstate import and because it only prints the VMs that are not from an allowed publisher. It achieves the latter by using double negation (two nots) and "any" instead of "all". (For those familiar with logic, we are using one of De Morgan's laws: `not(P or Q) <-> (not P) and (not Q)`.) 5 | -------------------------------------------------------------------------------- /governance/first-generation/azure/acs-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | clusters = tfplan.resources.azurerm_container_service 4 | 5 | agent_node_count_limit = rule { 6 | all clusters as name, instances { 7 | all instances as index, r { 8 | int(r.applied.agent_pool_profile[0].count) < 10 9 | } 10 | } 11 | } 12 | 13 | master_node_count_limit = rule { 14 | all clusters as name, instances { 15 | all instances as index, r { 16 | int(r.applied.master_profile[0].count) <= 3 17 | } 18 | } 19 | } 20 | 21 | vm_size_allowed = rule { 22 | all clusters as name, instances { 23 | all instances as index, r { 24 | r.applied.agent_pool_profile[0].vm_size matches "Standard_A1" 25 | } 26 | } 27 | } 28 | main = rule { 29 | (master_node_count_limit and agent_node_count_limit and vm_size_allowed) else true 30 | } 31 | -------------------------------------------------------------------------------- /governance/first-generation/azure/aks-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | clusters = tfplan.resources.azurerm_kubernetes_cluster 4 | 5 | agent_node_count_limit = rule { 6 | all clusters as name, instances { 7 | all instances as index, r { 8 | int(r.applied.agent_pool_profile[0].count) < 10 9 | } 10 | } 11 | } 12 | 13 | # Allowed VM Sizes 14 | allowed_vm_sizes = [ 15 | "Standard_A1", 16 | "Standard_A2", 17 | "Standard_A3", 18 | ] 19 | 20 | vm_size_allowed = rule { 21 | all clusters as name, instances { 22 | all instances as index, r { 23 | r.applied.agent_pool_profile[0].vm_size in allowed_vm_sizes 24 | } 25 | } 26 | } 27 | main = rule { 28 | (agent_node_count_limit and vm_size_allowed) else true 29 | } 30 | -------------------------------------------------------------------------------- /governance/first-generation/azure/block-allow-all-cidr.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_sgs = func() { 4 | sgs = [] 5 | for tfplan.module_paths as path { 6 | sgs += values(tfplan.module(path).resources.azurerm_network_security_group) else [] 7 | } 8 | return sgs 9 | } 10 | 11 | network_sgs = get_sgs() 12 | 13 | disallowed_cidr_blocks = [ 14 | "0.0.0.0/0", 15 | "0.0.0.0", 16 | "*", 17 | ] 18 | 19 | block_allow_all = rule { 20 | all network_sgs as _, instances { 21 | all instances as _, sg { 22 | all sg.applied.security_rule as _, sr { 23 | (sr.source_address_prefix not in disallowed_cidr_blocks) or sr.access == "Deny" 24 | } 25 | } 26 | } 27 | } 28 | 29 | main = rule { 30 | (block_allow_all) else true 31 | } 32 | -------------------------------------------------------------------------------- /governance/first-generation/azure/enforce-mandatory-tags.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Warning, this is case sensitive. 4 | # This is on purpose especially for organizations that do cost analysis on tag names. 5 | # where case sensitivity will cause grouping issues 6 | 7 | mandatory_tags = [ 8 | "TTL", 9 | "Owner", 10 | ] 11 | 12 | # Get all AWS instances contained in all modules being used 13 | get_azure_instances = func() { 14 | instances = [] 15 | for tfplan.module_paths as path { 16 | instances += values(tfplan.module(path).resources.azurerm_virtual_machine) else [] 17 | } 18 | return instances 19 | } 20 | 21 | azure_instances = get_azure_instances() 22 | 23 | # Instance tag rule 24 | instance_tags = rule { 25 | all azure_instances as _, instances { 26 | all instances as index, r { 27 | all mandatory_tags as t { 28 | r.applied.tags contains t 29 | } 30 | } 31 | } 32 | } 33 | 34 | main = rule { 35 | (instance_tags) else true 36 | } 37 | -------------------------------------------------------------------------------- /governance/first-generation/azure/restrict-current-azure-vms.sentinel: -------------------------------------------------------------------------------- 1 | import "tfstate" 2 | 3 | # Get VMs that already exist in the state of this workspace 4 | get_vms = func() { 5 | vms = [] 6 | for tfstate.module_paths as path { 7 | vms += values(tfstate.module(path).resources.azurerm_virtual_machine) else [] 8 | } 9 | return vms 10 | } 11 | 12 | # List of allowed publishers 13 | allowed_publishers = [ 14 | "RedHat", 15 | "Canonical", 16 | ] 17 | 18 | vms = get_vms() 19 | 20 | # This rule uses a double negative expression (two nots) so that 21 | # only VMs that are NOT in the list of approved publishers 22 | # will be printed. 23 | # If we had used all instead of any and left out the nots, 24 | # only the valid VMs would have been printed. 25 | # Or, if we had done that and put the print() statement before 26 | # testing the VM's publisher, all VMs would have been printed. 27 | vm_publisher_allowed = rule { 28 | not ( 29 | any vms as _, instances { 30 | any instances as index, r { 31 | (r.attr.storage_image_reference[0].publisher not in allowed_publishers) and print("Existing VM publisher ", r.attr.storage_image_reference[0].publisher, "for VM ", r.attr.name, "is invalid") 32 | } 33 | }) 34 | } 35 | 36 | main = rule { 37 | (vm_publisher_allowed) else true 38 | } 39 | -------------------------------------------------------------------------------- /governance/first-generation/azure/restrict-vm-image-id.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.azurerm_virtual_machine) else [] 7 | } 8 | return vms 9 | } 10 | 11 | 12 | allowed_image_ids = [ 13 | "/subscriptions//resourceGroups/ABC-US-Z-RGP-NJS3-E005/providers/Microsoft.Compute/images/WIN-base-image", 14 | "/subscriptions//resourceGroups/ABC-US-Z-RGP-NJS3-E005/providers/Microsoft.Compute/images/RHEL-base-image", 15 | ] 16 | 17 | vms = get_vms() 18 | vm_image_id_allowed = rule { 19 | all vms as _, instances { 20 | all instances as index, r { 21 | # Two possible ways to restrict image ID 22 | r.applied.storage_image_reference[0].id in allowed_image_ids 23 | #r.applied.storage_image_reference[0].id matches "/subscriptions//(.*)[Win|RHEL](.*)" 24 | } 25 | } 26 | } 27 | 28 | main = rule { 29 | (vm_image_id_allowed) else true 30 | } 31 | -------------------------------------------------------------------------------- /governance/first-generation/azure/restrict-vm-publisher.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.azurerm_virtual_machine) else [] 7 | } 8 | return vms 9 | } 10 | 11 | 12 | allowed_publishers = [ 13 | "MicrosoftWindowsServer", 14 | "RedHat", 15 | ] 16 | 17 | vms = get_vms() 18 | vm_publisher_allowed = rule { 19 | all vms as _, instances { 20 | all instances as index, r { 21 | r.applied.storage_image_reference[0].publisher in allowed_publishers 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | (vm_publisher_allowed) else true 28 | } 29 | -------------------------------------------------------------------------------- /governance/first-generation/azure/restrict-vm-size.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.azurerm_virtual_machine) else [] 7 | } 8 | return vms 9 | } 10 | 11 | # comparison is case-sensitive 12 | # so including both cases for "v" 13 | # since we have seen both used 14 | allowed_vm_sizes = [ 15 | "Standard_D1_v2", 16 | "Standard_D1_V2", 17 | "Standard_D2_v2", 18 | "Standard_D2_V2", 19 | "Standard_DS1_v2", 20 | "Standard_DS1_V2", 21 | "Standard_DS2_v2", 22 | "Standard_DS2_V2", 23 | "Standard_A1", 24 | "Standard_A2", 25 | "Standard_D1", 26 | "Standard_D2", 27 | ] 28 | 29 | vms = get_vms() 30 | vm_size_allowed = rule { 31 | all vms as _, instances { 32 | all instances as index, r { 33 | r.applied.vm_size in allowed_vm_sizes 34 | } 35 | } 36 | } 37 | 38 | main = rule { 39 | (vm_size_allowed) else true 40 | } 41 | -------------------------------------------------------------------------------- /governance/first-generation/cloud-agnostic/README.md: -------------------------------------------------------------------------------- 1 | # Cloud-Agnostic Policies 2 | This directory contains example policies that are cloud agnostic. 3 | -------------------------------------------------------------------------------- /governance/first-generation/external/README.md: -------------------------------------------------------------------------------- 1 | This repository contains an example of using a data source that calls a function together with a Sentinel policy that checks the result returned by the function call. While the example here just trivially runs a shell script that returns different values based on the account number passed to it by the Terraform code, a customer could actually call an external API to capture real data and then have Sentinel check the result. 2 | 3 | There is a commented out line, `#(length(check_account_balance) > 0) and`, which if uncommented would require the check_balance data source to be present in every single workspace in the current organization. Enable this with caution since any workspace that did not have this data source would cause hard-mandatory failure of this policy. 4 | -------------------------------------------------------------------------------- /governance/first-generation/external/check_account.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set -e 4 | 5 | CODE=$1 6 | 7 | case $CODE in 8 | 1) 9 | BALANCE=100 10 | ;; 11 | 2) 12 | BALANCE=0 13 | ;; 14 | *) 15 | BALANCE=0 16 | ;; 17 | esac 18 | 19 | echo "{ \"balance\": \"$BALANCE\" }" 20 | -------------------------------------------------------------------------------- /governance/first-generation/external/check_account.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.11.7" 3 | } 4 | 5 | variable "account_code" { 6 | description = "code of cloud account: can be 1 or 2" 7 | } 8 | 9 | 10 | # Add fake resource to make sure that TFE runs this each time 11 | resource "null_resource" "fake" { 12 | triggers { 13 | uuid = "${uuid()}" 14 | } 15 | } 16 | 17 | data "external" "check_balance" { 18 | program = ["./check_account.sh", "${var.account_code}"] 19 | } 20 | 21 | output "balance" { 22 | value = "${data.external.check_balance.result["balance"]}" 23 | } 24 | 25 | 26 | -------------------------------------------------------------------------------- /governance/first-generation/external/check_account_balance.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get instances of from root module 4 | check_account_balance = tfplan.state.data.external.check_balance 5 | 6 | # Rule to validate that account has balance > 50 7 | balance_test = rule { 8 | # If you wanted every single workspace to include the check_balance 9 | # data source, you could uncomment the following line. Use caution! 10 | #(length(check_account_balance) > 0) and 11 | all check_account_balance as _, r { 12 | print( r.attr.result.balance ) and (int(r.attr.result.balance) else 0) > 50 13 | } 14 | } 15 | 16 | # Main rule that requires other rules to be true 17 | main = rule { 18 | (balance_test) else true 19 | } 20 | -------------------------------------------------------------------------------- /governance/first-generation/gcp/README.md: -------------------------------------------------------------------------------- 1 | # Sentinel Policies for Google Cloud Platform 2 | The sample Sentinel policy files in this directory can be used with Terraform Enterprise to ensure that provisioned GCP VMs, firewalls, and GKE clusters comply with your organization's provisioning rules. 3 | -------------------------------------------------------------------------------- /governance/first-generation/gcp/block-allow-all-cidr.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_firewalls = func() { 4 | firewalls = [] 5 | for tfplan.module_paths as path { 6 | firewalls += values(tfplan.module(path).resources.google_compute_firewall) else [] 7 | } 8 | return firewalls 9 | } 10 | 11 | firewalls = get_firewalls() 12 | 13 | disallowed_cidr_block = "0.0.0.0/0" 14 | 15 | block_allow_all = rule { 16 | all firewalls as _, instances { 17 | all instances as _, fw { 18 | length(fw.applied.source_ranges else []) > 0 and 19 | all fw.applied.source_ranges as sr { 20 | print("source range:", sr) and disallowed_cidr_block not in sr 21 | } 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | (block_allow_all) else true 28 | } 29 | -------------------------------------------------------------------------------- /governance/first-generation/gcp/gke-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | clusters = tfplan.resources.google_container_cluster 4 | 5 | node_count_limit = rule { 6 | all clusters as name, instances { 7 | all instances as index, r { 8 | int(r.applied.initial_node_count) < 10 9 | } 10 | } 11 | } 12 | 13 | machine_type_allowed = rule { 14 | all clusters as name, instances { 15 | all instances as index, r { 16 | r.applied.node_config[0].machine_type in ["n1-standard-1", "n1-standard-2", "n1-standard-4"] 17 | } 18 | } 19 | } 20 | 21 | main = rule { 22 | (machine_type_allowed and node_count_limit) else true 23 | } 24 | -------------------------------------------------------------------------------- /governance/first-generation/gcp/pod_limit.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | pods_limit = tfplan.resources.kubernetes_resource_quota 4 | 5 | pod_count_limit = rule { 6 | all pods_limit as name, instances { 7 | all instances as index, r { 8 | int(r.applied.spec[0].hard.pods) < 10 9 | } 10 | } 11 | } 12 | 13 | main = rule { 14 | (pod_count_limit) else true 15 | } 16 | 17 | -------------------------------------------------------------------------------- /governance/first-generation/gcp/restrict-machine-type.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.google_compute_instance) else [] 7 | } 8 | return vms 9 | } 10 | 11 | 12 | allowed_machine_types = [ 13 | "n1-standard-1", 14 | "n1-standard-2", 15 | "n1-standard-4", 16 | ] 17 | 18 | vms = get_vms() 19 | machine_type_allowed = rule { 20 | all vms as _, instances { 21 | all instances as index, r { 22 | r.applied.machine_type in allowed_machine_types 23 | } 24 | } 25 | } 26 | 27 | main = rule { 28 | (machine_type_allowed) else true 29 | } 30 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/require-storage-drs.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_datastore_clusters = func() { 4 | datastore_clusters = [] 5 | for tfplan.module_paths as path { 6 | datastore_clusters += values(tfplan.module(path).resources.vsphere_datastore_cluster) else [] 7 | } 8 | return datastore_clusters 9 | } 10 | 11 | datastore_clusters = get_datastore_clusters() 12 | 13 | # Require Storage DRS be enabled (true) 14 | # other option is false 15 | require_storage_drs = rule { 16 | all datastore_clusters as _, instances { 17 | all instances as index, r { 18 | r.applied.sdrs_enabled is true 19 | } 20 | } 21 | } 22 | 23 | main = rule { 24 | (require_storage_drs) else true 25 | } 26 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/require_nfs41_and_kerberos.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_nas_datastores = func() { 4 | nas_datastores = [] 5 | for tfplan.module_paths as path { 6 | nas_datastores += values(tfplan.module(path).resources.vsphere_nas_datastore) else [] 7 | } 8 | return nas_datastores 9 | } 10 | 11 | nas_datastores = get_nas_datastores() 12 | 13 | # Require NAS datastore type be nfs41 14 | # Default is NFS (which means NFS v3) 15 | require_nfs41 = rule { 16 | all nas_datastores as _, instances { 17 | all instances as index, r { 18 | r.applied.type is "NFS41" 19 | } 20 | } 21 | } 22 | 23 | # Require security type be one of two Kerberos options 24 | # Only applicable when type is NFS41. 25 | # Only other option is AUTH_SYS 26 | require_kerberos = rule { 27 | all nas_datastores as _, instances { 28 | all instances as index, r { 29 | r.applied.security_type in ["SEC_KRB5", "SEC_KRB5I"] 30 | } 31 | } 32 | } 33 | 34 | main = rule { 35 | (require_nfs41 and require_kerberos) else true 36 | } 37 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/restrict-virtual-disk-size-and-type.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_virtual_disks = func() { 4 | virtual_disks = [] 5 | for tfplan.module_paths as path { 6 | virtual_disks += values(tfplan.module(path).resources.vsphere_virtual_disk) else [] 7 | } 8 | return virtual_disks 9 | } 10 | 11 | virtual_disks = get_virtual_disks() 12 | 13 | # Restrict size of disk in GB 14 | disk_size_limit = rule { 15 | all virtual_disks as _, instances { 16 | all instances as index, r { 17 | r.applied.size < 100 18 | } 19 | } 20 | } 21 | 22 | # Specify disk type as thin. 23 | # Could also be eagerZeroedThick (the default) or lazy 24 | disk_type = rule { 25 | all virtual_disks as _, instances { 26 | all instances as index, r { 27 | r.applied.type is "thin" 28 | } 29 | } 30 | } 31 | 32 | main = rule { 33 | (disk_size_limit and disk_type) else true 34 | } 35 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/restrict-vm-cpu-and-memory.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.vsphere_virtual_machine) else [] 7 | } 8 | return vms 9 | } 10 | 11 | vms = get_vms() 12 | 13 | # Restrict number of CPUs 14 | cpus_limit = rule { 15 | all vms as _, instances { 16 | all instances as index, r { 17 | int(r.applied.num_cpus) <= 4 18 | } 19 | } 20 | } 21 | 22 | # Restrict Memory (in MB) 23 | memory_limit = rule { 24 | all vms as _, instances { 25 | all instances as index, r { 26 | int(r.applied.memory) <= 8192 27 | } 28 | } 29 | } 30 | 31 | main = rule { 32 | (cpus_limit and memory_limit) else true 33 | } 34 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/restrict-vm-creation-hours: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | import "time" 3 | 4 | get_vms = func() { 5 | vms = [] 6 | for tfplan.module_paths as path { 7 | vms += values(tfplan.module(path).resources.vsphere_virtual_machine) else [] 8 | } 9 | return vms 10 | } 11 | 12 | vms = get_vms() 13 | 14 | # UTC Hours when VMs can be created 15 | # to be after 10pm or before 4am 16 | restrict_hours = rule { 17 | all vms as _, instances { 18 | all instances as index, r { 19 | time.now.hour >= 22 or time.now.hour <= 4 20 | } 21 | } 22 | } 23 | 24 | main = rule { 25 | (restrict_hours) else true 26 | } 27 | -------------------------------------------------------------------------------- /governance/first-generation/vmware/restrict-vm-disk-size.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | get_vms = func() { 4 | vms = [] 5 | for tfplan.module_paths as path { 6 | vms += values(tfplan.module(path).resources.vsphere_virtual_machine) else [] 7 | } 8 | return vms 9 | } 10 | 11 | vms = get_vms() 12 | 13 | # Restrict size of VM disk in GiB 14 | disk_size_limit = rule { 15 | all vms as _, instances { 16 | all instances as index, r { 17 | all r.applied.disk as disk { 18 | int(disk.size) < 100 19 | } 20 | } 21 | } 22 | } 23 | 24 | main = rule { 25 | (disk_size_limit) else true 26 | } 27 | -------------------------------------------------------------------------------- /governance/second-generation/aws/mocks/rds-db-instance-mock-tfconfig.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | 3 | _modules = { 4 | "root": { 5 | "data": {}, 6 | "modules": {}, 7 | "outputs": {}, 8 | "providers": {}, 9 | "resources": { 10 | "aws_db_instance": { 11 | "default": { 12 | "config": { 13 | "allocated_storage": 20, 14 | "engine": "sqlserver-web", 15 | "engine_version": "5.7", 16 | "instance_class": "db.t2.micro", 17 | "name": "mydb", 18 | "parameter_group_name": "default.mysql5.7", 19 | "password": "foobarbaz", 20 | "storage_type": "gp2", 21 | "username": "foo", 22 | }, 23 | "provisioners": null, 24 | }, 25 | }, 26 | }, 27 | "variables": {}, 28 | }, 29 | } 30 | 31 | module_paths = [ 32 | [], 33 | ] 34 | 35 | module = func(path) { 36 | if length(path) < 1 { 37 | return _modules.root 38 | } 39 | 40 | return _modules[strings.join(["module", path], ".")] 41 | } 42 | 43 | data = _modules.root.data 44 | modules = _modules.root.modules 45 | providers = _modules.root.providers 46 | resources = _modules.root.resources 47 | variables = _modules.root.variables 48 | outputs = _modules.root.outputs -------------------------------------------------------------------------------- /governance/second-generation/aws/mocks/rds-db-instance-mock-tfstate.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | 3 | _modules = { 4 | "root": { 5 | "data": {}, 6 | "outputs": {}, 7 | "path": [], 8 | "resources": {}, 9 | }, 10 | } 11 | 12 | module_paths = [ 13 | [], 14 | ] 15 | 16 | terraform_version = "0.11.14" 17 | 18 | module = func(path) { 19 | if length(path) < 1 { 20 | return _modules.root 21 | } 22 | 23 | return _modules[strings.join(["module", path], ".")] 24 | } 25 | 26 | data = _modules.root.data 27 | outputs = _modules.root.outputs 28 | path = _modules.root.path 29 | resources = _modules.root.resources -------------------------------------------------------------------------------- /governance/second-generation/aws/mocks/s3-bucket-mock-tfstate.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | 3 | _modules = { 4 | "root": { 5 | "data": {}, 6 | "outputs": {}, 7 | "path": [], 8 | "resources": {}, 9 | }, 10 | } 11 | 12 | module_paths = [ 13 | [], 14 | ] 15 | 16 | terraform_version = "0.11.13" 17 | 18 | module = func(path) { 19 | if length(path) < 1 { 20 | return _modules.root 21 | } 22 | 23 | return _modules[strings.join(["module", path], ".")] 24 | } 25 | 26 | data = _modules.root.data 27 | outputs = _modules.root.outputs 28 | path = _modules.root.path 29 | resources = _modules.root.resources -------------------------------------------------------------------------------- /governance/second-generation/aws/mocks/sgr-mock-tfconfig.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | 3 | _modules = { 4 | "root": { 5 | "data": {}, 6 | "modules": {}, 7 | "outputs": {}, 8 | "providers": {}, 9 | "resources": { 10 | "aws_security_group_rule": { 11 | "allow_all": { 12 | "config": { 13 | "cidr_blocks": [ 14 | "0.0.0.0/0", 15 | ], 16 | "from_port": 0, 17 | "protocol": "tcp", 18 | "security_group_id": "sg-0ecaf664fe45ff737", 19 | "to_port": 65535, 20 | "type": "ingress", 21 | }, 22 | "provisioners": null, 23 | }, 24 | }, 25 | }, 26 | "variables": {}, 27 | }, 28 | } 29 | 30 | module_paths = [ 31 | [], 32 | ] 33 | 34 | module = func(path) { 35 | if length(path) < 1 { 36 | return _modules.root 37 | } 38 | 39 | return _modules[strings.join(["module", path], ".")] 40 | } 41 | 42 | data = _modules.root.data 43 | modules = _modules.root.modules 44 | providers = _modules.root.providers 45 | resources = _modules.root.resources 46 | variables = _modules.root.variables 47 | outputs = _modules.root.outputs -------------------------------------------------------------------------------- /governance/second-generation/aws/mocks/sgr-mock-tfstate.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | 3 | _modules = { 4 | "root": { 5 | "data": {}, 6 | "outputs": {}, 7 | "path": [], 8 | "resources": {}, 9 | }, 10 | } 11 | 12 | module_paths = [ 13 | [], 14 | ] 15 | 16 | terraform_version = "0.11.14" 17 | 18 | module = func(path) { 19 | if length(path) < 1 { 20 | return _modules.root 21 | } 22 | 23 | return _modules[strings.join(["module", path], ".")] 24 | } 25 | 26 | data = _modules.root.data 27 | outputs = _modules.root.outputs 28 | path = _modules.root.path 29 | resources = _modules.root.resources -------------------------------------------------------------------------------- /governance/second-generation/aws/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "enforce-mandatory-tags" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "require-private-acl-and-kms-for-s3-buckets" { 6 | enforcement_level = "advisory" 7 | } 8 | 9 | policy "restrict-assumed-role-by-workspace" { 10 | enforcement_level = "advisory" 11 | } 12 | 13 | policy "restrict-assumed-role" { 14 | enforcement_level = "advisory" 15 | } 16 | 17 | policy "restrict-availability-zones" { 18 | enforcement_level = "advisory" 19 | } 20 | 21 | policy "restrict-db-instance-engines" { 22 | enforcement_level = "advisory" 23 | } 24 | 25 | policy "restrict-ec2-instance-type" { 26 | enforcement_level = "advisory" 27 | } 28 | 29 | policy "restrict-ingress-sg-rule-cidr-blocks" { 30 | enforcement_level = "advisory" 31 | } 32 | 33 | policy "restrict-launch-configuration-instance-type" { 34 | enforcement_level = "advisory" 35 | } 36 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/fail-missing-tags-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-tags-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/fail-missing-tags-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-tags-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/fail-no-tags-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-tags-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/fail-no-tags-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-tags-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/enforce-mandatory-tags/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/fail-acl-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-acl-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/fail-acl-and-kms-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-acl-and-kms-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/fail-acl-and-kms-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-acl-and-kms-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/fail-kms-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-kms-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/fail-kms-no-ssec-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-kms-no-ssec-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/require-private-acl-and-kms-for-s3-buckets/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ami-owners/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ami-owners/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ami-owners/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ami-owners/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-bad-role-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-bad-role-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-bad-role-0.11.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-bad-role-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-bad-role-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-bad-role-0.12.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-dev-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-dev-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-dev-0.11.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-dev-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-dev-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-dev-0.12.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-prod-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-prod-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-prod-0.11.sentinel", 5 | "tfrun": "mock-tfrun-prod.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-prod-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-prod-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-prod-0.12.sentinel", 5 | "tfrun": "mock-tfrun-prod.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-qa-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-qa-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-qa-0.11.sentinel", 5 | "tfrun": "mock-tfrun-qa.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/fail-qa-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-qa-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-qa-0.12.sentinel", 5 | "tfrun": "mock-tfrun-qa.sentinel" 6 | }, 7 | "test": { 8 | "main": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/mock-tfrun-dev.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "test-dev", 8 | "vcs_repo": null, 9 | "working_directory": "", 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/mock-tfrun-prod.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "prod-test", 8 | "vcs_repo": null, 9 | "working_directory": "", 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/mock-tfrun-qa.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "test-qa", 8 | "vcs_repo": null, 9 | "working_directory": "", 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-dev-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-dev-0.11.sentinel", 4 | "tfplan": "mock-tfplan-pass-dev-0.11.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-dev-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-dev-0.12.sentinel", 4 | "tfplan": "mock-tfplan-pass-dev-0.12.sentinel", 5 | "tfrun": "mock-tfrun-dev.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-prod-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-prod-0.11.sentinel", 4 | "tfplan": "mock-tfplan-pass-prod-0.11.sentinel", 5 | "tfrun": "mock-tfrun-prod.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-prod-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-prod-0.12.sentinel", 4 | "tfplan": "mock-tfplan-pass-prod-0.12.sentinel", 5 | "tfrun": "mock-tfrun-prod.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-qa-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-qa-0.11.sentinel", 4 | "tfplan": "mock-tfplan-pass-qa-0.11.sentinel", 5 | "tfrun": "mock-tfrun-qa.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role-by-workspace/pass-qa-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-qa-0.12.sentinel", 4 | "tfplan": "mock-tfplan-pass-qa-0.12.sentinel", 5 | "tfrun": "mock-tfrun-qa.sentinel" 6 | }, 7 | "test": { 8 | "main": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 5 | }, 6 | "test": { 7 | "main": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 5 | }, 6 | "test": { 7 | "main": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel", 4 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 5 | }, 6 | "test": { 7 | "main": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-assumed-role/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel", 4 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 5 | }, 6 | "test": { 7 | "main": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-availability-zones/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-availability-zones/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-availability-zones/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-availability-zones/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-db-instance-engines/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-db-instance-engines/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-db-instance-engines/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-db-instance-engines/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ec2-instance-type/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ec2-instance-type/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ec2-instance-type/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ec2-instance-type/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/pass-no-cidr-blocks-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-no-cidr-blocks-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-launch-configuration-instance-type/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-launch-configuration-instance-type/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-launch-configuration-instance-type/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/aws/test/restrict-launch-configuration-instance-type/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "enforce-mandatory-tags" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "restrict-app-service-to-https" { 6 | enforcement_level = "advisory" 7 | } 8 | 9 | policy "restrict-publishers-of-current-vms" { 10 | enforcement_level = "advisory" 11 | } 12 | 13 | policy "restrict-vm-size" { 14 | enforcement_level = "advisory" 15 | } 16 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/fail-missing-tag-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-tag-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/fail-missing-tag-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-tag-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/fail-no-tags-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-tags-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/fail-no-tags-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-tags-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/enforce-mandatory-tags/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-app-service-to-https/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-app-service-to-https/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-publishers-of-current-vms/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-publishers-of-current-vms/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-publishers-of-current-vms/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-publishers-of-current-vms/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfstate": "mock-tfstate-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-vm-size/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-vm-size/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-vm-size/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/azure/test/restrict-vm-size/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "check-external-http-api" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "use-latest-module-versions" { 6 | enforcement_level = "advisory" 7 | } 8 | 9 | policy "asteroids" { 10 | enforcement_level = "advisory" 11 | } 12 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/sentinel.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "public_registry": true, 4 | "address": "registry.terraform.io", 5 | "organization": "Azure", 6 | "token": "" 7 | }, 8 | "mock": { 9 | "tfconfig": "mocks/mock-tfconfig-fail-0.12.sentinel" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/asteroids/fail.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "api_token": "", 4 | "danger_distance": 10000000 5 | }, 6 | "test": { 7 | "main": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/asteroids/pass.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "api_token": "", 4 | "danger_distance": 200000 5 | }, 6 | "test": { 7 | "main": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/check-external-http-api/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "main": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 8 | }, 9 | "test": { 10 | "main": false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 8 | }, 9 | "test": { 10 | "main": false 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/pass-no-pmr-modules-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-pass-no-pmr-modules-0.11.sentinel" 8 | }, 9 | "test": { 10 | "main": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/pass-no-pmr-modules-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-pass-no-pmr-modules-0.12.sentinel" 8 | }, 9 | "test": { 10 | "main": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/pass-valid-versions-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-pass-valid-versions-0.11.sentinel" 8 | }, 9 | "test": { 10 | "main": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/http-examples/test/use-latest-module-versions/pass-valid-versions-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "param": { 3 | "organization": "Cloud-Operations", 4 | "token": "" 5 | }, 6 | "mock": { 7 | "tfconfig": "mock-tfconfig-pass-valid-versions-0.12.sentinel" 8 | }, 9 | "test": { 10 | "main": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/prevent-non-root-providers.sentinel: -------------------------------------------------------------------------------- 1 | # This policy uses the tfconfig import to prevent providers from being declared 2 | # in non-root modules, aligning with the best practices given in: 3 | # https://www.terraform.io/docs/configuration/modules.html 4 | 5 | ##### Imports ##### 6 | import "tfconfig" 7 | import "strings" 8 | 9 | ##### Functions ##### 10 | 11 | # Prevent providers in non-root modules 12 | prevent_non_root_providers = func() { 13 | 14 | validated = true 15 | 16 | # Iterate over all modules in the tfconfig import 17 | for tfconfig.module_paths as path { 18 | # Check non-root modules 19 | if length(path) > 0 { 20 | # Iterate over providers of given type in module 21 | providers = tfconfig.module(path).providers 22 | if length(providers) > 0 { 23 | print("Module module." + strings.join(path, ".module.") + 24 | " has providers.") 25 | validated = false 26 | } 27 | } 28 | } 29 | 30 | return validated 31 | } 32 | 33 | ##### Rules ##### 34 | 35 | # Call the validation function 36 | providers_validated = prevent_non_root_providers() 37 | 38 | # Main rule 39 | main = rule { 40 | providers_validated 41 | } 42 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "prohibited-datasources" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "prohibited-providers" { 6 | enforcement_level = "advisory" 7 | } 8 | 9 | policy "prohibited-provisioners" { 10 | enforcement_level = "advisory" 11 | } 12 | 13 | policy "prohibited-resources" { 14 | enforcement_level = "advisory" 15 | } 16 | 17 | policy "limit-cost-by-workspace-type" { 18 | enforcement_level = "advisory" 19 | } 20 | 21 | policy "limit-proposed-monthly-cost" { 22 | enforcement_level = "advisory" 23 | } 24 | 25 | policy "prevent-destruction-of-prohibited-resources" { 26 | enforcement_level = "advisory" 27 | } 28 | 29 | policy "prevent-non-root-providers" { 30 | enforcement_level = "advisory" 31 | } 32 | 33 | policy "prevent-remote-exec-provisioners-on-null-resources" { 34 | enforcement_level = "advisory" 35 | } 36 | 37 | policy "require-all-resources-from-pmr" { 38 | enforcement_level = "advisory" 39 | } 40 | 41 | policy "restrict-cost-and-percentage-increase" { 42 | enforcement_level = "advisory" 43 | } 44 | 45 | policy "validate-all-variables-have-descriptions" { 46 | enforcement_level = "advisory" 47 | } 48 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/allowed-resources/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/allowed-resources/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/fail-dev-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-dev-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/fail-other-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-other-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/fail-prod-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-prod-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/fail-qa-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-qa-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-fail-dev-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-dev", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "300.0000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "300.0000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-fail-other-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "55.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "55.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-fail-prod-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-prod", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "1200.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "1200.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-fail-qa-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-qa", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "524.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "524.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-pass-dev-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-dev", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "172.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "172.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-pass-no-estimates-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-pass-other-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "36.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "36.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-pass-prod-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-prod", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "950.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "950.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/mock-tfrun-pass-qa-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance-qa", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "480.00000", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "480.00000", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/pass-dev-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-dev-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/pass-no-estimates-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-no-estimates-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/pass-other-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-other-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/pass-prod-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-prod-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-cost-by-workspace-type/pass-qa-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-qa-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/mock-tfrun-fail-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "1211.10435", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "1211.10435", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/mock-tfrun-pass-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "341.19982", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "341.19982", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/mock-tfrun-pass-no-estimates-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/limit-proposed-monthly-cost/pass-no-estimates-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-no-estimates-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-destruction-of-prohibited-resources/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-destruction-of-prohibited-resources/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-destruction-of-prohibited-resources/mock-tfplan-pass-0.11.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | _modules = { 5 | "root": { 6 | "data": {}, 7 | "path": [], 8 | "resources": { 9 | "azurerm_virtual_machine": { 10 | "demo": { 11 | 0: { 12 | "destroy": true, 13 | "diff": {}, 14 | "requires_new": false, 15 | }, 16 | }, 17 | }, 18 | }, 19 | }, 20 | } 21 | 22 | module_paths = [ 23 | [], 24 | ] 25 | 26 | terraform_version = "0.11.14" 27 | 28 | variables = { 29 | "prefix": "azure-demo", 30 | "vm_size": "Standard_A1", 31 | } 32 | 33 | module = func(path) { 34 | if types.type_of(path) is not "list" { 35 | error("expected list, got", types.type_of(path)) 36 | } 37 | 38 | if length(path) < 1 { 39 | return _modules.root 40 | } 41 | 42 | addr = [] 43 | for path as p { 44 | append(addr, "module") 45 | append(addr, p) 46 | } 47 | 48 | return _modules[strings.join(addr, ".")] 49 | } 50 | 51 | data = _modules.root.data 52 | path = _modules.root.path 53 | resources = _modules.root.resources -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-destruction-of-prohibited-resources/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-destruction-of-prohibited-resources/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-non-root-providers/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-non-root-providers/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-non-root-providers/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-non-root-providers/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-remote-exec-provisioners-on-null-resources/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-remote-exec-provisioners-on-null-resources/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-remote-exec-provisioners-on-null-resources/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prevent-remote-exec-provisioners-on-null-resources/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-datasources/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-datasources/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-datasources/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-datasources/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-providers/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-providers/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-providers/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-providers/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-provisioners/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-provisioners/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-resources/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/prohibited-resources/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/require-all-resources-from-pmr/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/require-all-resources-from-pmr/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/require-all-resources-from-pmr/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/require-all-resources-from-pmr/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/fail-limit-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-limit-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/fail-percent-increase-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-fail-percent-increase-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/mock-tfrun-fail-limit-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "1211.10435", 19 | "prior_monthly_cost": "0.0", 20 | "proposed_monthly_cost": "1211.10435", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/mock-tfrun-fail-percent-increase-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "43.05439", 19 | "prior_monthly_cost": "320.14543", 20 | "proposed_monthly_cost": "363.19982", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/mock-tfrun-pass-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | 17 | cost_estimate = { 18 | "delta_monthly_cost": "21.05439", 19 | "prior_monthly_cost": "320.14543", 20 | "proposed_monthly_cost": "341.19982", 21 | } 22 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/mock-tfrun-pass-no-estimates-0.12.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | workspace = { 5 | "auto_apply": false, 6 | "description": null, 7 | "name": "gcp-compute-instance", 8 | "vcs_repo": { 9 | "branch": "master", 10 | "display_identifier": "rberlind/gcp_compute_instance", 11 | "identifier": "rberlind/gcp_compute_instance", 12 | "ingress_submodules": false, 13 | }, 14 | "working_directory": "", 15 | } 16 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/restrict-cost-and-percentage-increase/pass-no-estimates-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfrun": "mock-tfrun-pass-no-estimates-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/validate-all-variables-have-descriptions/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.11.sentinel", 4 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 5 | }, 6 | "test": { 7 | "main": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/validate-all-variables-have-descriptions/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-fail-0.12.sentinel", 4 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 5 | }, 6 | "test": { 7 | "main": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/validate-all-variables-have-descriptions/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.11.sentinel", 4 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 5 | }, 6 | "test": { 7 | "main": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/cloud-agnostic/test/validate-all-variables-have-descriptions/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfconfig": "mock-tfconfig-pass-0.12.sentinel", 4 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 5 | }, 6 | "test": { 7 | "main": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/config/find_datasources_from_config.sentinel: -------------------------------------------------------------------------------- 1 | # Find all datasources of specific type from all modules 2 | # using the tfconfig import 3 | find_datasources_from_config = func(type) { 4 | 5 | datasources = {} 6 | 7 | # Iterate over all modules in the tfconfig import 8 | for tfconfig.module_paths as path { 9 | # Iterate over the named datasources of desired type in the module 10 | for tfconfig.module(path).data[type] else {} as name, d { 11 | 12 | # Get the address of the datasource 13 | if length(path) == 0 { 14 | # root module 15 | address = type + "." + name 16 | } else { 17 | # non-root module 18 | address = "module." + strings.join(path, ".module.") + "." + 19 | type + "." + name 20 | } 21 | 22 | # Add the datasource to datasources map, setting the key to the address 23 | datasources[address] = d 24 | } 25 | } 26 | 27 | return datasources 28 | } 29 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/config/find_provider_aliases.sentinel: -------------------------------------------------------------------------------- 1 | # Find all providers aliases of given type using the tfconfig import 2 | find_provider_aliases = func(type) { 3 | 4 | # We will find all provider aliases og given type from tfconfig, 5 | # meaning providers.TYPE.alias.ALIAS 6 | providers = {} 7 | 8 | # Iterate over all modules in the tfconfig import 9 | for tfconfig.module_paths as path { 10 | # Iterate over providers of given type in module 11 | aliases = tfconfig.module(path).providers[type]["alias"] else {} 12 | for aliases as alias, data { 13 | # Change default alias ("") to "default" 14 | if alias is "" { 15 | alias = "default" 16 | } 17 | 18 | # Get the address of the provider alias 19 | if length(path) == 0 { 20 | # root module 21 | address = type + "." + alias 22 | } else { 23 | # non-root module 24 | address = "module." + strings.join(path, ".module.") + "." + 25 | type + "." + alias 26 | } 27 | 28 | providers[address] = data 29 | 30 | } // end aliases loop 31 | } // end module_paths loop 32 | 33 | return providers 34 | } 35 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/config/find_resources_from_config.sentinel: -------------------------------------------------------------------------------- 1 | # Find all resources of specific type from all modules using the tfconfig import 2 | find_resources_from_config = func(type) { 3 | 4 | resources = {} 5 | 6 | # Iterate over all modules in the tfconfig import 7 | for tfconfig.module_paths as path { 8 | # Iterate over the named resources of desired type in the module 9 | for tfconfig.module(path).resources[type] else {} as name, r { 10 | 11 | # Get the address of the resource 12 | if length(path) == 0 { 13 | # root module 14 | address = type + "." + name 15 | } else { 16 | # non-root module 17 | address = "module." + strings.join(path, ".module.") + "." + 18 | type + "." + name 19 | } 20 | 21 | # Add the resource to resources map, setting the key to the address 22 | resources[address] = r 23 | } 24 | } 25 | 26 | return resources 27 | } 28 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/config/find_variables_in_config.sentinel: -------------------------------------------------------------------------------- 1 | # Find all variables using the tfconfig import 2 | # This returns a flat map of variables across all modules 3 | find_variables_in_config = func() { 4 | variables = {} 5 | 6 | # Iterate over all modules in the tfconfig import 7 | for tfconfig.module_paths as path { 8 | # Iterate over the variables in the module 9 | for tfconfig.module(path).variables else {} as name, v { 10 | 11 | # Get the address of the variable 12 | if length(path) == 0 { 13 | # root module 14 | address = name 15 | } else { 16 | # non-root module 17 | address = "module." + strings.join(path, ".module.") + "." + name 18 | } 19 | 20 | # Add the variable to the variables map, setting the key to the address 21 | variables[address] = v 22 | } 23 | } 24 | 25 | return variables 26 | 27 | } 28 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/plan/find_datasources_from_plan.sentinel: -------------------------------------------------------------------------------- 1 | # Find all data sources of a specific type from all modules using the tfplan import 2 | find_datasources_from_plan = func(type) { 3 | 4 | datasources = {} 5 | 6 | # Iterate over all modules in the tfplan import 7 | for tfplan.module_paths as path { 8 | # Iterate over the named datasources of desired type in the module 9 | for tfplan.module(path).data[type] else {} as name, instances { 10 | # Iterate over datasource instances 11 | for instances as index, d { 12 | 13 | # Get the address of the instance 14 | if length(path) == 0 { 15 | # root module 16 | address = type + "." + name + "[" + string(index) + "]" 17 | } else { 18 | # non-root module 19 | address = "module." + strings.join(path, ".module.") + "." + 20 | type + "." + name + "[" + string(index) + "]" 21 | } 22 | 23 | # Add the instance to datasources map, setting the key to the address 24 | datasources[address] = d 25 | } 26 | } 27 | } 28 | 29 | return datasources 30 | } 31 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/plan/find_resource_types_from_plan.md: -------------------------------------------------------------------------------- 1 | # find_resource_types_from_plan 2 | This function finds all resource types from all modules using the [tfplan](https://www.terraform.io/docs/enterprise/sentinel/import/tfplan.html) import. 3 | 4 | ## Scope 5 | Terraform plans 6 | 7 | ## Declaration 8 | `find_resource_types_from_plan = func()` 9 | 10 | ## Arguments 11 | * None 12 | 13 | ## Required Imports 14 | This function requires the following imports: 15 | ``` 16 | import "tfplan" 17 | ``` 18 | Be sure to include it in any policy that uses this function. 19 | 20 | ## Custom Functions Used 21 | None 22 | 23 | ## What It Returns 24 | This function returns a single list of all resource types used within the plan. 25 | 26 | ## What It Prints 27 | This function does not print anything. 28 | 29 | ## Code 30 | The Sentinel code for this function is in [find_resource_types_from_plan.sentinel](./find_resource_types_from_plan.sentinel). 31 | 32 | ## Examples 33 | Here is an example of using this function: 34 | ``` 35 | find_resource_types_from_plan() 36 | ``` 37 | You can see this function being used in context in the policy [allowed-resources](../../cloud-agnostic/allowed-resources.sentinel)in this repository. 38 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/plan/find_resource_types_from_plan.sentinel: -------------------------------------------------------------------------------- 1 | # Find all resource types from all modules using the tfplan import 2 | find_resource_types_from_plan = func() { 3 | 4 | types = [] 5 | 6 | # Iterate over all modules in the tfplan import 7 | for tfplan.module_paths as path { 8 | # Find all types of resources used in the module 9 | for tfplan.module(path).resources else {} as type { 10 | #print("type is:", type) 11 | # Add the type to the types list 12 | append(types, type) 13 | } 14 | } 15 | 16 | return types 17 | } 18 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/plan/find_resources_from_plan.sentinel: -------------------------------------------------------------------------------- 1 | # Find all resources of a specific type from all modules using the tfplan import 2 | find_resources_from_plan = func(type) { 3 | 4 | resources = {} 5 | 6 | # Iterate over all modules in the tfplan import 7 | for tfplan.module_paths as path { 8 | # Iterate over the named resources of desired type in the module 9 | for tfplan.module(path).resources[type] else {} as name, instances { 10 | # Iterate over resource instances 11 | for instances as index, r { 12 | 13 | # Get the address of the instance 14 | if length(path) == 0 { 15 | # root module 16 | address = type + "." + name + "[" + string(index) + "]" 17 | } else { 18 | # non-root module 19 | address = "module." + strings.join(path, ".module.") + "." + 20 | type + "." + name + "[" + string(index) + "]" 21 | } 22 | 23 | # Add the instance to resources map, setting the key to the address 24 | resources[address] = r 25 | } 26 | } 27 | } 28 | 29 | return resources 30 | } 31 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/plan/validate_destroyed_resources.sentinel: -------------------------------------------------------------------------------- 1 | # Validate that resources of prohibited types are not being destroyed 2 | validate_destroyed_resources = func(prohibited_list) { 3 | 4 | valid = true 5 | 6 | for prohibited_list as type { 7 | found_resources = find_resources_from_plan(type) 8 | for found_resources as address, r { 9 | if r.destroy and not r.requires_new { 10 | print("You are trying to destroy a resource", address, 11 | "of prohibited type", type) 12 | valid = false 13 | } 14 | } 15 | } 16 | 17 | return valid 18 | } 19 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/state/find_datasources_from_state.sentinel: -------------------------------------------------------------------------------- 1 | # Find all data sources of a specific type from all modules using the 2 | # tfstate import 3 | find_datasources_from_state = func(type) { 4 | 5 | datasources = {} 6 | 7 | # Iterate over all modules in the tfstate import 8 | for tfstate.module_paths else [] as path { 9 | # Iterate over the named datasources of desired type in the module 10 | for tfstate.module(path).data[type] else {} as name, instances { 11 | # Iterate over datasource instances 12 | for instances as index, d { 13 | 14 | # Get the address of the instance 15 | if length(path) == 0 { 16 | # root module 17 | address = type + "." + name + "[" + string(index) + "]" 18 | } else { 19 | # non-root module 20 | address = "module." + strings.join(path, ".module.") + "." + 21 | type + "." + name + "[" + string(index) + "]" 22 | } 23 | 24 | # Add the instance to datasources map, setting the key to the address 25 | datasources[address] = d 26 | } 27 | } 28 | } 29 | 30 | return datasources 31 | } 32 | -------------------------------------------------------------------------------- /governance/second-generation/common-functions/state/find_resources_from_state.sentinel: -------------------------------------------------------------------------------- 1 | # Find all resources of specific type from all modules using the tfstate import 2 | find_resources_from_state = func(type) { 3 | 4 | resources = {} 5 | 6 | # Iterate over all modules in the tfstate import 7 | for tfstate.module_paths else [] as path { 8 | # Iterate over the named resources of desired type in the module 9 | for tfstate.module(path).resources[type] else {} as name, instances { 10 | # Iterate over resource instances 11 | for instances as index, r { 12 | 13 | # Get the address of the instance 14 | if length(path) == 0 { 15 | # root module 16 | address = type + "." + name + "[" + string(index) + "]" 17 | } else { 18 | # non-root module 19 | address = "module." + strings.join(path, ".module.") + "." + 20 | type + "." + name + "[" + string(index) + "]" 21 | } 22 | 23 | # Add the instance to resources map, setting the key to the address 24 | resources[address] = r 25 | } 26 | } 27 | } 28 | 29 | return resources 30 | } 31 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/mocks/gce-instance-mock-tfstate.sentinel: -------------------------------------------------------------------------------- 1 | import "strings" 2 | import "types" 3 | 4 | _modules = { 5 | "root": { 6 | "data": {}, 7 | "outputs": {}, 8 | "path": [], 9 | "resources": {}, 10 | }, 11 | } 12 | 13 | module_paths = [ 14 | [], 15 | ] 16 | 17 | terraform_version = "0.11.13" 18 | 19 | module = func(path) { 20 | if types.type_of(path) is not "list" { 21 | error("expected list, got", types.type_of(path)) 22 | } 23 | 24 | if length(path) < 1 { 25 | return _modules.root 26 | } 27 | 28 | addr = [] 29 | for path as p { 30 | append(addr, "module") 31 | append(addr, p) 32 | } 33 | 34 | return _modules[strings.join(addr, ".")] 35 | } 36 | 37 | data = _modules.root.data 38 | outputs = _modules.root.outputs 39 | path = _modules.root.path 40 | resources = _modules.root.resources -------------------------------------------------------------------------------- /governance/second-generation/gcp/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "enforce-mandatory-labels" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "restrict-gce-machine-type" { 6 | enforcement_level = "advisory" 7 | } 8 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/fail-missing-labels-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-labels-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/fail-missing-labels-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-missing-labels-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/fail-no-labels-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-labels-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/fail-no-labels-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-no-labels-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/enforce-mandatory-labels/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/restrict-gce-machine-type/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/restrict-gce-machine-type/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/restrict-gce-machine-type/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/gcp/test/restrict-gce-machine-type/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/sentinel.hcl: -------------------------------------------------------------------------------- 1 | policy "restrict-vm-cpu-and-memory" { 2 | enforcement_level = "advisory" 3 | } 4 | 5 | policy "restrict-vm-disk-size" { 6 | enforcement_level = "advisory" 7 | } 8 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/fail-cpu-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-cpu-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/fail-cpu-and-memory-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-cpu-and-memory-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/fail-cpu-and-memory-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-cpu-and-memory-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/fail-memory-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-memory-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-cpu-and-memory/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-disk-size/fail-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-disk-size/fail-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-fail-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-disk-size/pass-0.11.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.11.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/second-generation/vmware/test/restrict-vm-disk-size/pass-0.12.json: -------------------------------------------------------------------------------- 1 | { 2 | "mock": { 3 | "tfplan": "mock-tfplan-pass-0.12.sentinel" 4 | }, 5 | "test": { 6 | "main": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /governance/third-generation/README.md: -------------------------------------------------------------------------------- 1 | # Third-Generation Sentinel Policies 2 | 3 | **Note: The Third-Generation Policies are being migrated to the Terraform registry. While this process continues, refer to [terraform-sentinel-policies](https://github.com/hashicorp/terraform-sentinel-policies). Please add and edit policies in that repository.** 4 | 5 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-ec2-instance/README.md: -------------------------------------------------------------------------------- 1 | # Provision an EC2 instance in AWS 2 | This Terraform configuration provisions an EC2 instance in AWS. 3 | 4 | ## Details 5 | By default, this configuration provisions a Ubuntu 14.04 Base Image AMI (with ID ami-2e1ef954) with type t2.micro in the us-east-1 region. The AMI ID, region, and type can all be set as variables. You can also set the name variable to determine the value set for the Name tag. 6 | 7 | Note that you need to set environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. 8 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-ec2-instance/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.11.0" 3 | } 4 | 5 | provider "aws" { 6 | region = "${var.aws_region}" 7 | } 8 | 9 | resource "aws_instance" "ubuntu" { 10 | ami = "${var.ami_id}" 11 | instance_type = "${var.instance_type}" 12 | availability_zone = "${var.aws_region}a" 13 | 14 | tags { 15 | Name = "${var.name}" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-ec2-instance/outputs.tf: -------------------------------------------------------------------------------- 1 | output "public_dns" { 2 | value = "${aws_instance.ubuntu.public_dns}" 3 | } 4 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-ec2-instance/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_region" { 2 | description = "AWS region" 3 | default = "us-west-1" 4 | } 5 | 6 | variable "ami_id" { 7 | description = "ID of the AMI to provision. Default is Ubuntu 14.04 Base Image" 8 | default = "ami-2e1ef954" 9 | } 10 | 11 | variable "instance_type" { 12 | description = "type of EC2 instance to provision." 13 | default = "t2.micro" 14 | } 15 | 16 | variable "name" { 17 | description = "name to pass to Name tag" 18 | default = "Provisioned by Terraform" 19 | } 20 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/aws_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/aws_bot.png -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/dummy_event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/dummy_event.png -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/good_morning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/assets/good_morning.png -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/encryption.tf.disabled: -------------------------------------------------------------------------------- 1 | # Optional extra resources to help encrypt your Slack Webhook URL 2 | 3 | # This key is used to encrypt the slack webhook URL 4 | resource "aws_kms_key" "notify_slack" { 5 | description = "Key for encrypting the Slack webhook URL" 6 | enable_key_rotation = "false" 7 | is_enabled = "true" 8 | } 9 | 10 | # A human friendly alias so we can find it in the UI 11 | resource "aws_kms_alias" "notify_slack" { 12 | name = "alias/notify_slack" 13 | target_key_id = "${aws_kms_key.notify_slack.key_id}" 14 | } 15 | 16 | # Template for our 'decrypt_kms' lambda IAM policy 17 | data "template_file" "iam_decrypt_kms" { 18 | template = "${file("./files/iam_decrypt_kms.tpl")}" 19 | 20 | vars { 21 | kmskey = "${aws_kms_key.notify_slack.arn}" 22 | account_id = "${data.aws_caller_identity.current.account_id}" 23 | region = "${var.region}" 24 | } 25 | } 26 | 27 | # Here we ingest the template and attach it to our notify_slack role 28 | resource "aws_iam_role_policy" "decrypt_kms" { 29 | name = "decrypt_kms" 30 | policy = "${data.template_file.iam_decrypt_kms.rendered}" 31 | role = "${aws_iam_role.lambda_notify_slack.id}" 32 | } -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/ASGJanitor.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/ASGJanitor.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/ASGReaper.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/ASGReaper.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/EC2Janitor.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/EC2Janitor.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/EC2Reaper.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/EC2Reaper.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getInstanceReport.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getInstanceReport.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getRunningInstances.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getRunningInstances.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getTaggedASGs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getTaggedASGs.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getTaggedInstances.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getTaggedInstances.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getUntaggedASGs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getUntaggedASGs.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getUntaggedInstances.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/getUntaggedInstances.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/iam_decrypt_kms.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "kms:Decrypt" 8 | ], 9 | "Resource": [ 10 | "${kmskey}" 11 | ] 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/iam_lambda_notify.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "logs:CreateLogGroup", 8 | "logs:CreateLogStream", 9 | "logs:PutLogEvents" 10 | ], 11 | "Resource": "arn:aws:logs:${region}:${account_id}:*" 12 | }, 13 | { 14 | "Effect": "Allow", 15 | "Action": [ 16 | "lambda:InvokeFunction", 17 | "ses:SendEmail", 18 | "ses:SendRawEmail" 19 | ], 20 | "Resource": "*" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/iam_lambda_stop_and_terminate_instances.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "logs:CreateLogGroup", 7 | "Resource": "arn:aws:logs:${region}:${account_id}:*" 8 | }, 9 | { 10 | "Effect": "Allow", 11 | "Action": [ 12 | "logs:CreateLogStream", 13 | "logs:PutLogEvents" 14 | ], 15 | "Resource": [ 16 | "arn:aws:logs:${region}:${account_id}:*" 17 | ] 18 | }, 19 | { 20 | "Effect": "Allow", 21 | "Action": [ 22 | "lambda:InvokeFunction", 23 | "ses:SendEmail", 24 | "ses:SendRawEmail", 25 | "ec2:*" 26 | ], 27 | "Resource": "*" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/iam_lambda_terminate_asgs.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": "logs:CreateLogGroup", 7 | "Resource": "arn:aws:logs:${region}:${account_id}:*" 8 | }, 9 | { 10 | "Effect": "Allow", 11 | "Action": [ 12 | "logs:CreateLogStream", 13 | "logs:PutLogEvents" 14 | ], 15 | "Resource": [ 16 | "arn:aws:logs:${region}:${account_id}:*" 17 | ] 18 | }, 19 | { 20 | "Effect": "Allow", 21 | "Action": [ 22 | "lambda:InvokeFunction", 23 | "ses:SendEmail", 24 | "ses:SendRawEmail", 25 | "autoscaling:*" 26 | ], 27 | "Resource": "*" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/notifyInstanceUsage.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/notifyInstanceUsage.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/files/notifyUntaggedInstances.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/files/notifyUntaggedInstances.zip -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/main.tf: -------------------------------------------------------------------------------- 1 | # Terraform configurations for creating lambda functions to help manage 2 | # your ec2 instance lifecycles. The data_collectors.tf and iam_roles.tf 3 | # files are required. You may also use one or more of the following: 4 | # 5 | # notify_instance_usage.tf - Notify slack with instance usage #s 6 | # notify_untagged.tf - Checks for mandatory tags, notifies slack. 7 | # instance_reaper.tf - Terminates instances that have passed their TTL. 8 | # untagged_janitor.tf - Cleans up untagged instances. 9 | 10 | provider "aws" { 11 | region = "${var.region}" 12 | } 13 | -------------------------------------------------------------------------------- /infrastructure-as-code/aws-lambda-ec2-lifecycles/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/aws-lambda-ec2-lifecycles/outputs.tf -------------------------------------------------------------------------------- /infrastructure-as-code/azure-vm/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.11.1" 3 | } 4 | 5 | variable "location" { 6 | description = "Azure location in which to create resources" 7 | default = "East US" 8 | } 9 | 10 | variable "windows_dns_prefix" { 11 | description = "DNS prefix to add to to public IP address for Windows VM" 12 | } 13 | 14 | variable "admin_password" { 15 | description = "admin password for Windows VM" 16 | default = "pTFE1234!" 17 | } 18 | 19 | module "windowsserver" { 20 | source = "Azure/compute/azurerm" 21 | version = "1.1.5" 22 | location = "${var.location}" 23 | resource_group_name = "${var.windows_dns_prefix}-rc" 24 | vm_hostname = "pwc-ptfe" 25 | admin_password = "${var.admin_password}" 26 | vm_os_simple = "WindowsServer" 27 | public_ip_dns = ["${var.windows_dns_prefix}"] 28 | vnet_subnet_id = "${module.network.vnet_subnets[0]}" 29 | } 30 | 31 | module "network" { 32 | source = "Azure/network/azurerm" 33 | version = "1.1.1" 34 | location = "${var.location}" 35 | resource_group_name = "${var.windows_dns_prefix}-rc" 36 | allow_ssh_traffic = true 37 | } 38 | 39 | output "windows_vm_public_name"{ 40 | value = "${module.windowsserver.public_ip_dns_name}" 41 | } 42 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.11.0" 3 | } 4 | 5 | // Vault provider 6 | // Set VAULT_ADDR and VAULT_TOKEN environment variables 7 | provider "vault" {} 8 | 9 | // AWS credentials from Vault 10 | data "vault_aws_access_credentials" "aws_creds" { 11 | backend = "aws" 12 | role = "deploy" 13 | } 14 | 15 | // Setup the core provider information. 16 | provider "aws" { 17 | access_key = "${data.vault_aws_access_credentials.aws_creds.access_key}" 18 | secret_key = "${data.vault_aws_access_credentials.aws_creds.secret_key}" 19 | region = "${var.region}" 20 | } 21 | 22 | data "aws_availability_zones" "main" {} 23 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks-firewalls-ingress.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group_rule" "ssh" { 2 | security_group_id = "${aws_security_group.egress_public.id}" 3 | type = "ingress" 4 | protocol = "tcp" 5 | from_port = 22 6 | to_port = 22 7 | cidr_blocks = ["0.0.0.0/0"] 8 | } 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks-firewalls.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "egress_public" { 2 | name = "${var.environment_name}-egress_public" 3 | description = "${var.environment_name}-egress_public" 4 | vpc_id = "${aws_vpc.main.id}" 5 | } 6 | 7 | resource "aws_security_group_rule" "egress_public" { 8 | security_group_id = "${aws_security_group.egress_public.id}" 9 | type = "egress" 10 | protocol = "-1" 11 | from_port = 0 12 | to_port = 0 13 | cidr_blocks = ["0.0.0.0/0"] 14 | } 15 | 16 | resource "aws_security_group_rule" "ingress_internal" { 17 | security_group_id = "${aws_security_group.egress_public.id}" 18 | type = "ingress" 19 | protocol = "-1" 20 | from_port = 0 21 | to_port = 0 22 | self = "true" 23 | } 24 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks-gateways.tf: -------------------------------------------------------------------------------- 1 | resource "aws_internet_gateway" "main" { 2 | vpc_id = "${aws_vpc.main.id}" 3 | 4 | tags { 5 | Name = "${var.environment_name}" 6 | } 7 | } 8 | 9 | resource "aws_nat_gateway" "nat" { 10 | count = "${length(var.vpc_cidrs_public)}" 11 | 12 | allocation_id = "${element(aws_eip.nat.*.id,count.index)}" 13 | subnet_id = "${element(aws_subnet.public.*.id,count.index)}" 14 | } 15 | 16 | resource "aws_eip" "nat" { 17 | count = "${length(var.vpc_cidrs_public)}" 18 | 19 | vpc = true 20 | } 21 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks-routes.tf: -------------------------------------------------------------------------------- 1 | # 2 | # Public 3 | # 4 | resource "aws_route_table" "public" { 5 | vpc_id = "${aws_vpc.main.id}" 6 | 7 | route { 8 | cidr_block = "0.0.0.0/0" 9 | gateway_id = "${aws_internet_gateway.main.id}" 10 | } 11 | 12 | tags { 13 | Name = "${var.environment_name}-public" 14 | } 15 | } 16 | 17 | resource "aws_route_table_association" "public" { 18 | count = "${length(var.vpc_cidrs_public)}" 19 | 20 | subnet_id = "${element(aws_subnet.public.*.id,count.index)}" 21 | route_table_id = "${aws_route_table.public.id}" 22 | } 23 | 24 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks-subnets.tf: -------------------------------------------------------------------------------- 1 | resource "aws_subnet" "public" { 2 | count = "${length(var.vpc_cidrs_public)}" 3 | 4 | vpc_id = "${aws_vpc.main.id}" 5 | availability_zone = "${element(data.aws_availability_zones.main.names,count.index)}" 6 | cidr_block = "${element(var.vpc_cidrs_public,count.index)}" 7 | map_public_ip_on_launch = true 8 | 9 | tags { 10 | Name = "${var.environment_name}-public-${count.index}" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/networks.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "main" { 2 | cidr_block = "${var.vpc_cidr}" 3 | enable_dns_hostnames = true 4 | 5 | tags { 6 | Name = "${var.environment_name}" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/outputs.tf: -------------------------------------------------------------------------------- 1 | # Outputs 2 | output "vpc_id" { 3 | value = "${aws_vpc.main.id}" 4 | } 5 | 6 | output "subnet_public_ids" { 7 | value = ["${aws_subnet.public.*.id}"] 8 | } 9 | 10 | output "security_group_apps" { 11 | value = "${aws_security_group.egress_public.id}" 12 | } 13 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds-from-vault/variables.tf: -------------------------------------------------------------------------------- 1 | # Required variables 2 | variable "environment_name" { 3 | description = "Environment Name" 4 | default = "Acme" 5 | } 6 | 7 | variable "region" { 8 | description = "AWS region" 9 | default = "us-west-2" 10 | } 11 | 12 | # Optional variables 13 | variable "vpc_cidr" { 14 | default = "172.19.0.0/16" 15 | } 16 | 17 | variable "vpc_cidrs_public" { 18 | default = [ 19 | "172.19.0.0/20", 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds-iam-ec2-policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds-iam-ec2-policy.png -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds-iam-policy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds-iam-policy.png -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/dynamic-aws-creds/assets/dynamic-iam-creds.png -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds/assets/ec2-instance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/dynamic-aws-creds/assets/ec2-instance.png -------------------------------------------------------------------------------- /infrastructure-as-code/dynamic-aws-creds/producer-workspace/main.tf: -------------------------------------------------------------------------------- 1 | variable "aws_access_key" { } 2 | variable "aws_secret_key" { } 3 | variable "name" { default = "dynamic-aws-creds-producer" } 4 | 5 | terraform { 6 | backend "local" { 7 | path = "terraform.tfstate" 8 | } 9 | } 10 | 11 | provider "vault" {} 12 | 13 | resource "vault_aws_secret_backend" "aws" { 14 | access_key = "${var.aws_access_key}" 15 | secret_key = "${var.aws_secret_key}" 16 | path = "${var.name}-path" 17 | 18 | default_lease_ttl_seconds = "120" 19 | max_lease_ttl_seconds = "240" 20 | } 21 | 22 | resource "vault_aws_secret_backend_role" "producer" { 23 | backend = "${vault_aws_secret_backend.aws.path}" 24 | name = "${var.name}-role" 25 | credential_type = "iam_user" 26 | 27 | policy_document = < ${var.private_key_filename}" 8 | } 9 | 10 | provisioner "local-exec" { 11 | command = "chmod 600 ${var.private_key_filename}" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/dev/terraform-azure/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | custom_image_id = "" 2 | 3 | auto_join_subscription_id = "" 4 | 5 | auto_join_client_id = "" 6 | 7 | auto_join_client_secret = "" 8 | 9 | auto_join_tenant_id = "" 10 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/dev/terraform-gcp/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # Operating System to use ie RHEL or Ubuntu 2 | os = "Ubuntu" 3 | #os = "RHEL" 4 | 5 | # Operating System version to use ie 7.3 (for RHEL) or 16.04 (for Ubuntu) 6 | os_version = "16.04" 7 | #os_version = "7.3" 8 | 9 | # GCP Region 10 | gcp_region = "us-east1" 11 | 12 | project_name = "my-hashistack-test-1" 13 | 14 | account_file_json = "~/.gcloud/my-image-test.json" 15 | 16 | cluster_name = "my-hashistack" 17 | environment_name = "my-hashistack" 18 | 19 | consul_version = "0.9.2+ent" 20 | nomad_version = "0.6.2" 21 | vault_version = "0.8.1+ent" 22 | 23 | machine_type = "g1-small" 24 | 25 | image_bucket_name = "my-image-store" 26 | environment = "test" 27 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/quick-start/terraform-aws/gitignore.tf: -------------------------------------------------------------------------------- 1 | # `.tf` files that contain the word "gitignore" are ignored 2 | # by git in the `.gitignore` file at the root of this repo. 3 | 4 | # If you have local Terraform configuration that you want 5 | # ignored like Terraform backend configuration, create 6 | # a new file (separate from this one) that contains the 7 | # word "gitignore" (e.g. `backend.gitignore.tf`). 8 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/templates/install-base.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "[---Begin install-base.sh---]" 4 | 5 | echo "Wait for system to be ready" 6 | sleep 10 7 | 8 | echo "Run base script" 9 | curl https://raw.githubusercontent.com/hashicorp/guides-configuration/master/shared/scripts/base.sh | bash 10 | 11 | echo "[---install-base.sh Complete---]" 12 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/templates/install-docker.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "[---Begin install-docker.sh---]" 4 | 5 | echo "Install Docker" 6 | curl https://raw.githubusercontent.com/hashicorp/guides-configuration/master/nomad/scripts/install-docker.sh | bash 7 | 8 | echo "[---install-docker.sh Complete---]" 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/hashistack/templates/install-java.sh.tpl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "[---Begin install-java.sh---]" 4 | 5 | echo "Install Java" 6 | curl https://raw.githubusercontent.com/hashicorp/guides-configuration/master/nomad/scripts/install-java.sh | bash 7 | 8 | echo "[---install-java.sh Complete---]" 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/aks-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | clusters = tfplan.resources.azurerm_kubernetes_cluster 4 | 5 | agent_node_count_limit = rule { 6 | all clusters as name, instances { 7 | all instances as index, r { 8 | int(r.applied.agent_pool_profile[0].count) < 10 9 | } 10 | } 11 | } 12 | 13 | # Allowed VM Sizes 14 | allowed_vm_sizes = [ 15 | "Standard_A1", 16 | "Standard_A2", 17 | "Standard_A3", 18 | ] 19 | 20 | vm_size_allowed = rule { 21 | all clusters as name, instances { 22 | all instances as index, r { 23 | r.applied.agent_pool_profile[0].vm_size in allowed_vm_sizes 24 | } 25 | } 26 | } 27 | main = rule { 28 | (agent_node_count_limit and vm_size_allowed) else true 29 | } 30 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/ca_certificate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-aks/ca_certificate -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/client_certificate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-aks/client_certificate -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/client_key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-aks/client_key -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-aks/config -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/k8s.tfvars.example: -------------------------------------------------------------------------------- 1 | resource_group_name = "" 2 | dns_prefix = "" 3 | vault_addr = "" 4 | vault_user = "" 5 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/outputs.tf: -------------------------------------------------------------------------------- 1 | output "private_key_pem" { 2 | value = "${chomp(tls_private_key.ssh_key.private_key_pem)}" 3 | } 4 | 5 | output "k8s_id" { 6 | value = "${azurerm_kubernetes_cluster.k8sexample.id}" 7 | } 8 | 9 | output "k8s_endpoint" { 10 | value = "${azurerm_kubernetes_cluster.k8sexample.fqdn}" 11 | } 12 | 13 | output "k8s_master_auth_client_certificate" { 14 | value = "${azurerm_kubernetes_cluster.k8sexample.kube_config.0.client_certificate}" 15 | } 16 | 17 | output "k8s_master_auth_client_key" { 18 | value = "${azurerm_kubernetes_cluster.k8sexample.kube_config.0.client_key}" 19 | } 20 | 21 | output "k8s_master_auth_cluster_ca_certificate" { 22 | value = "${azurerm_kubernetes_cluster.k8sexample.kube_config.0.cluster_ca_certificate}" 23 | } 24 | 25 | output "environment" { 26 | value = "${var.environment}" 27 | } 28 | 29 | output "vault_user" { 30 | value = "${var.vault_user}" 31 | } 32 | 33 | output "vault_addr" { 34 | value = "${var.vault_addr}" 35 | } 36 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/private_key.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-aks/private_key.pem -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-aks/sample-policy.hcl: -------------------------------------------------------------------------------- 1 | # Vault Policy file for user roger 2 | 3 | # Access to secret/roger 4 | path "secret/roger/*" { 5 | capabilities = ["create", "read", "update", "delete", "list"] 6 | } 7 | 8 | # Ability to change password 9 | path "auth/userpass/users/roger/password" { 10 | capabilities = ["update"] 11 | } 12 | 13 | # Ability to see their own policy 14 | path "sys/policies/acl/roger" { 15 | capabilities = ["read"] 16 | } 17 | 18 | # Additional access for UI 19 | path "secret/" { 20 | capabilities = ["list"] 21 | } 22 | path "secret/roger" { 23 | capabilities = ["list"] 24 | } 25 | path "sys/mounts" { 26 | capabilities = ["read", "list"] 27 | } 28 | path "sys/policies/acl/" { 29 | capabilities = ["list"] 30 | } 31 | 32 | # Ability to provision Kubernetes auth backends 33 | path "sys/auth/roger*" { 34 | capabilities = ["sudo", "create", "read", "update", "delete", "list"] 35 | } 36 | path "sys/auth" { 37 | capabilities = ["read", "list"] 38 | } 39 | path "auth/roger*" { 40 | capabilities = ["create", "read", "update", "delete", "list"] 41 | } 42 | 43 | # Needed for the Terraform Vault Provider 44 | path "auth/token/create" { 45 | capabilities = ["create", "read", "update", "list"] 46 | } 47 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-gke/gke-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | clusters = tfplan.resources.google_container_cluster 4 | 5 | node_count_limit = rule { 6 | all clusters as name, instances { 7 | all instances as index, r { 8 | int(r.applied.initial_node_count) < 10 9 | } 10 | } 11 | } 12 | 13 | machine_type_allowed = rule { 14 | all clusters as name, instances { 15 | all instances as index, r { 16 | r.applied.node_config[0].machine_type in ["n1-standard-1", "n1-standard-2", "n1-standard-4"] 17 | } 18 | } 19 | } 20 | 21 | main = rule { 22 | (machine_type_allowed and node_count_limit) else true 23 | } 24 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-gke/outputs.tf: -------------------------------------------------------------------------------- 1 | output "k8s_endpoint" { 2 | value = "${google_container_cluster.k8sexample.endpoint}" 3 | } 4 | 5 | output "k8s_master_version" { 6 | value = "${google_container_cluster.k8sexample.master_version}" 7 | } 8 | 9 | output "k8s_instance_group_urls" { 10 | value = "${google_container_cluster.k8sexample.instance_group_urls.0}" 11 | } 12 | 13 | output "k8s_master_auth_client_certificate" { 14 | value = "${google_container_cluster.k8sexample.master_auth.0.client_certificate}" 15 | } 16 | 17 | output "k8s_master_auth_client_key" { 18 | value = "${google_container_cluster.k8sexample.master_auth.0.client_key}" 19 | } 20 | 21 | output "k8s_master_auth_cluster_ca_certificate" { 22 | value = "${google_container_cluster.k8sexample.master_auth.0.cluster_ca_certificate}" 23 | } 24 | 25 | output "environment" { 26 | value = "${var.environment}" 27 | } 28 | 29 | output "vault_user" { 30 | value = "${var.vault_user}" 31 | } 32 | 33 | output "vault_addr" { 34 | value = "${var.vault_addr}" 35 | } 36 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-gke/sample-policy.hcl: -------------------------------------------------------------------------------- 1 | # Vault Policy file for user roger 2 | 3 | # Access to secret/roger 4 | path "secret/roger/*" { 5 | capabilities = ["create", "read", "update", "delete", "list"] 6 | } 7 | 8 | # Ability to change password 9 | path "auth/userpass/users/roger/password" { 10 | capabilities = ["update"] 11 | } 12 | 13 | # Ability to see their own policy 14 | path "sys/policies/acl/roger" { 15 | capabilities = ["read"] 16 | } 17 | 18 | # Additional access for UI 19 | path "secret/" { 20 | capabilities = ["list"] 21 | } 22 | path "secret/roger" { 23 | capabilities = ["list"] 24 | } 25 | path "sys/mounts" { 26 | capabilities = ["read", "list"] 27 | } 28 | path "sys/policies/acl/" { 29 | capabilities = ["list"] 30 | } 31 | 32 | # Ability to provision Kubernetes auth backends 33 | path "sys/auth/roger*" { 34 | capabilities = ["sudo", "create", "read", "update", "delete", "list"] 35 | } 36 | path "sys/auth" { 37 | capabilities = ["read", "list"] 38 | } 39 | path "auth/roger*" { 40 | capabilities = ["create", "read", "update", "delete", "list"] 41 | } 42 | 43 | # Needed for the Terraform Vault Provider 44 | path "auth/token/create" { 45 | capabilities = ["create", "read", "update", "list"] 46 | } 47 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/ca_certificate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-openshift-aws/ca_certificate -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/client_certificate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-openshift-aws/client_certificate -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/client_key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-openshift-aws/client_key -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/config: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-openshift-aws/config -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/delay-vault-aws: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | region=$1 3 | sleep 15 4 | echo "{ \"region\": \"$region\" }" 5 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/modules/openshift/00-variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | description = "The region to deploy the cluster in, e.g: us-east-1." 3 | } 4 | 5 | variable "amisize" { 6 | description = "The size of the cluster nodes, e.g: t2.large. Note that OpenShift will not run on anything smaller than t2.large" 7 | } 8 | 9 | variable "vpc_cidr" { 10 | description = "The CIDR block for the VPC, e.g: 10.0.0.0/16" 11 | } 12 | 13 | variable "subnetaz" { 14 | description = "The AZ for the public subnet, e.g: us-east-1a" 15 | type = "map" 16 | } 17 | 18 | variable "subnet_cidr" { 19 | description = "The CIDR block for the public subnet, e.g: 10.0.1.0/24" 20 | } 21 | 22 | variable "key_name" { 23 | description = "The name of the key to user for ssh access" 24 | } 25 | 26 | variable "private_key_data" { 27 | description = "contents of the private key" 28 | } 29 | 30 | variable "name_tag_prefix" { 31 | description = "prefixed to Name tag added to EC2 instances and other AWS resources" 32 | } 33 | 34 | variable "owner" { 35 | description = "value set on EC2 owner tag" 36 | } 37 | 38 | variable "ttl" { 39 | description = "value set on EC2 TTL tag. -1 means forever. Measured in hours." 40 | } 41 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/modules/openshift/01-amis.tf: -------------------------------------------------------------------------------- 1 | # Define the RHEL 7.2 AMI by: 2 | # RedHat, Latest, x86_64, EBS, HVM, RHEL 7.5 3 | data "aws_ami" "rhel7_5" { 4 | most_recent = true 5 | 6 | owners = ["309956199498"] // Red Hat's account ID. 7 | 8 | filter { 9 | name = "architecture" 10 | values = ["x86_64"] 11 | } 12 | 13 | filter { 14 | name = "root-device-type" 15 | values = ["ebs"] 16 | } 17 | 18 | filter { 19 | name = "virtualization-type" 20 | values = ["hvm"] 21 | } 22 | 23 | filter { 24 | name = "name" 25 | values = ["RHEL-7.5*"] 26 | } 27 | } 28 | 29 | # Define an Amazon Linux AMI. 30 | data "aws_ami" "amazonlinux" { 31 | most_recent = true 32 | 33 | owners = ["137112412989"] 34 | 35 | filter { 36 | name = "architecture" 37 | values = ["x86_64"] 38 | } 39 | 40 | filter { 41 | name = "root-device-type" 42 | values = ["ebs"] 43 | } 44 | 45 | filter { 46 | name = "virtualization-type" 47 | values = ["hvm"] 48 | } 49 | 50 | filter { 51 | name = "name" 52 | values = ["amzn-ami-hvm-2018.03.0.20190611-x86_64-gp2"] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/modules/openshift/06-dns.tf: -------------------------------------------------------------------------------- 1 | // Notes: We could make the internal domain a variable, but not sure it is 2 | // really necessary. 3 | 4 | // Create the internal DNS. 5 | resource "aws_route53_zone" "internal" { 6 | name = "${var.name_tag_prefix}-openshift.local" 7 | comment = "OpenShift Cluster Internal DNS" 8 | vpc { 9 | vpc_id = "${aws_vpc.openshift.id}" 10 | } 11 | tags { 12 | Name = "OpenShift Internal DNS" 13 | Project = "openshift" 14 | } 15 | } 16 | 17 | // Routes for 'master' and 'node1'. 18 | resource "aws_route53_record" "master-a-record" { 19 | zone_id = "${aws_route53_zone.internal.zone_id}" 20 | name = "master.${var.name_tag_prefix}-openshift.local" 21 | type = "A" 22 | ttl = 300 23 | records = [ 24 | "${aws_instance.master.private_ip}" 25 | ] 26 | } 27 | resource "aws_route53_record" "node1-a-record" { 28 | zone_id = "${aws_route53_zone.internal.zone_id}" 29 | name = "node1.${var.name_tag_prefix}-openshift.local" 30 | type = "A" 31 | ttl = 300 32 | records = [ 33 | "${aws_instance.node1.private_ip}" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/modules/openshift/08-outputs.tf: -------------------------------------------------------------------------------- 1 | // Output some useful variables for quick SSH access etc. 2 | output "master_public_dns" { 3 | value = "${aws_instance.master.public_dns}" 4 | } 5 | output "master_public_ip" { 6 | value = "${aws_instance.master.public_ip}" 7 | } 8 | output "master_private_dns" { 9 | value = "${aws_instance.master.private_dns}" 10 | } 11 | output "master_private_ip" { 12 | value = "${aws_instance.master.private_ip}" 13 | } 14 | 15 | output "node1_public_dns" { 16 | value = "${aws_instance.node1.public_dns}" 17 | } 18 | output "node1_public_ip" { 19 | value = "${aws_instance.node1.public_ip}" 20 | } 21 | output "node1_private_dns" { 22 | value = "${aws_instance.node1.private_dns}" 23 | } 24 | output "node1_private_ip" { 25 | value = "${aws_instance.node1.private_ip}" 26 | } 27 | 28 | output "bastion_public_dns" { 29 | value = "${aws_instance.bastion.public_dns}" 30 | } 31 | output "bastion_public_ip" { 32 | value = "${aws_instance.bastion.public_ip}" 33 | } 34 | output "bastion_private_dns" { 35 | value = "${aws_instance.bastion.private_dns}" 36 | } 37 | output "bastion_private_ip" { 38 | value = "${aws_instance.bastion.private_ip}" 39 | } 40 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/modules/openshift/delay-aws: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | sleep 60 3 | echo '{ "wait": "60" }' 4 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/openshift-aws-cluster-policy.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Get all master instances from openshift module 4 | get_master_instances = func() { 5 | instances = values(tfplan.module(["openshift"]).resources.aws_instance.master) else [] 6 | return instances 7 | } 8 | 9 | masters = get_master_instances() 10 | 11 | # Rule to restrict Master instance type 12 | master_type_allowed = rule { 13 | all masters as index, r { 14 | r.applied.instance_type is "m4.xlarge" 15 | } 16 | } 17 | 18 | # Get all bastion instances from openshift module 19 | get_bastion_instances = func() { 20 | instances = values(tfplan.module(["openshift"]).resources.aws_instance.bastion) else [] 21 | return instances 22 | } 23 | 24 | bastions = get_bastion_instances() 25 | 26 | # Rule to restrict Bastion instance type 27 | bastion_type_allowed = rule { 28 | all bastions as index, r { 29 | r.applied.instance_type is "t2.micro" 30 | } 31 | } 32 | 33 | # Main rule that requires other rules to be true 34 | main = rule { 35 | (master_type_allowed and bastion_type_allowed) else true 36 | } 37 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/openshift.tfvars.example: -------------------------------------------------------------------------------- 1 | key_name = "" 2 | private_key_data= "" 3 | vault_k8s_auth_path = "-openshift" 4 | vault_user = "" 5 | vault_addr = "http://
:8200" 6 | owner = "" 7 | ttl = "-1" 8 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/scripts/postinstall-master.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Note: This script runs after the ansible install, use it to make configuration 4 | # changes which would otherwise be overwritten by ansible. 5 | 6 | sleep 180 7 | 8 | # Create an htpasswd file, we'll use htpasswd auth for OpenShift. 9 | sudo mkdir -p /etc/origin/master 10 | sudo htpasswd -cb /etc/origin/master/htpasswd admin 123 11 | oc adm policy add-cluster-role-to-user cluster-admin admin 12 | 13 | # Update the docker config to allow OpenShift's local insecure registry. Also 14 | # use json-file for logging, so our Splunk forwarder can eat the container logs. 15 | # json-file for logging 16 | sudo sed -i '/OPTIONS=.*/c\OPTIONS="--selinux-enabled --insecure-registry 172.30.0.0/16 --log-driver=json-file --log-opt max-size=1M --log-opt max-file=3"' /etc/sysconfig/docker 17 | sudo systemctl restart docker 18 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/scripts/postinstall-node.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Note: This script runs after the ansible install, use it to make configuration 4 | # changes which would otherwise be overwritten by ansible. 5 | 6 | sleep 180 7 | 8 | # Update the docker config to allow OpenShift's local insecure registry. Also 9 | # use json-file for logging, so our Splunk forwarder can eat the container logs. 10 | # json-file for logging 11 | sudo sed -i '/OPTIONS=.*/c\OPTIONS="--selinux-enabled --insecure-registry 172.30.0.0/16 --log-driver=json-file --log-opt max-size=1M --log-opt max-file=3"' /etc/sysconfig/docker 12 | sudo systemctl restart docker 13 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/vault-reviewer-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: role-tokenreview-binding 5 | namespace: default 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: system:auth-delegator 10 | subjects: 11 | - kind: ServiceAccount 12 | name: vault-reviewer 13 | namespace: default 14 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/vault-reviewer-token: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-cluster-openshift-aws/vault-reviewer-token -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-cluster-openshift-aws/vault-reviewer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: vault-reviewer 5 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-vault-config/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vault_k8s_auth_backend" { 2 | value = "${vault_auth_backend.k8s.path}" 3 | } 4 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-vault-config/variables.tf: -------------------------------------------------------------------------------- 1 | variable "tfe_organization" { 2 | description = "TFE organization" 3 | default = "RogerBerlind" 4 | } 5 | 6 | variable "k8s_cluster_workspace" { 7 | description = "workspace to use for the k8s cluster" 8 | } 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/k8s-vault-config/vault-reviewer-token: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/infrastructure-as-code/k8s-vault-config/vault-reviewer-token -------------------------------------------------------------------------------- /infrastructure-as-code/sagemaker-notebook/README.md: -------------------------------------------------------------------------------- 1 | # Sagemaker Notebooks 2 | 3 | The Terraform code in this directory was used to generate a Sagemaker notebook 4 | instance and various supporting AWS resources in order to run a plan and generate 5 | Sentinel mocks for use with the [restrict-sagemaker-notebooks.sentinel](../governance/third-generation/restrict-sagemaker-notebooks.sentinel) 6 | Sentinel policy. 7 | 8 | That policy requires all Sagemaker Notebook instances created with the 9 | `aws_sagemaker_notebook_instance` resource to set their `root_access` and `direct_internet_access` arguments to `false`. 10 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/advanced-dynamic-blocks/main.tf: -------------------------------------------------------------------------------- 1 | variable "settings" { 2 | type = list(map(string)) 3 | } 4 | 5 | resource "aws_elastic_beanstalk_application" "tftest" { 6 | name = "tf-test-name" 7 | description = "tf-test-desc" 8 | } 9 | 10 | resource "aws_elastic_beanstalk_environment" "tfenvtest" { 11 | name = "tf-test-name" 12 | application = "${aws_elastic_beanstalk_application.tftest.name}" 13 | solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6" 14 | 15 | dynamic "setting" { 16 | for_each = var.settings 17 | content { 18 | namespace = setting.value["namespace"] 19 | name = setting.value["name"] 20 | value = setting.value["value"] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/advanced-dynamic-blocks/terraform.tfvars: -------------------------------------------------------------------------------- 1 | settings = [ 2 | { 3 | namespace = "aws:ec2:vpc" 4 | name = "VPCId" 5 | value = "vpc-xxxxxxxxxxxxxxxxx" 6 | }, 7 | { 8 | namespace = "aws:ec2:vpc" 9 | name = "Subnets" 10 | value = "subnet-xxxxxxxxxxxxxxxxx" 11 | }, 12 | ] 13 | 14 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/dynamic-blocks-and-splat-expressions/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.0" 3 | } 4 | 5 | variable "aws_region" { 6 | description = "AWS region" 7 | default = "us-east-1" 8 | } 9 | 10 | variable "ingress_ports" { 11 | type = list(number) 12 | description = "list of ingress ports" 13 | default = [8200, 8201] 14 | } 15 | 16 | provider "aws" { 17 | region = var.aws_region 18 | } 19 | 20 | resource "aws_vpc" "my_vpc" { 21 | cidr_block = "172.16.0.0/16" 22 | tags = { 23 | Name = "tf-0.12-dynamic-block-example" 24 | } 25 | } 26 | 27 | resource "aws_security_group" "vault" { 28 | name = "vault" 29 | description = "Ingress for Vault" 30 | vpc_id = aws_vpc.my_vpc.id 31 | 32 | dynamic "ingress" { 33 | iterator = port 34 | for_each = var.ingress_ports 35 | content { 36 | from_port = port.value 37 | to_port = port.value 38 | protocol = "tcp" 39 | cidr_blocks = ["0.0.0.0/0"] 40 | } 41 | } 42 | } 43 | 44 | output "from_ports" { 45 | value = aws_security_group.vault.ingress[*].from_port 46 | #value = aws_security_group.vault.ingress.*.from_port 47 | } 48 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/for-each-for-resources/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.6" 3 | } 4 | 5 | provider "aws" { 6 | region = "us-east-1" 7 | } 8 | 9 | variable "zones" { 10 | description = "AWS availability zones" 11 | type = map 12 | default = { 13 | a = "us-east-1a" 14 | b = "us-east-1b" 15 | c = "us-east-1c" 16 | d = "us-east-1d" 17 | e = "us-east-1e" 18 | f = "us-east-1f" 19 | } 20 | } 21 | 22 | data "aws_ami" "ubuntu" { 23 | most_recent = true 24 | 25 | filter { 26 | name = "name" 27 | values = ["ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"] 28 | } 29 | 30 | filter { 31 | name = "virtualization-type" 32 | values = ["hvm"] 33 | } 34 | 35 | owners = ["099720109477"] # Canonical 36 | } 37 | 38 | resource "aws_instance" "ubuntu" { 39 | for_each = var.zones 40 | ami = data.aws_ami.ubuntu.id 41 | instance_type = "t2.micro" 42 | associate_public_ip_address = true 43 | availability_zone = each.value 44 | 45 | tags = { 46 | Name = format("for-each-demo-zone-%s", each.key) 47 | } 48 | 49 | } 50 | 51 | output "public_ips" { 52 | value = [for r in aws_instance.ubuntu: r.public_ip] 53 | } 54 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/for-expressions/lists-and-maps-with-for.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.0" 3 | } 4 | 5 | # List of letters 6 | variable "letters" { 7 | description = "a list of letters" 8 | default = ["a", "b", "c"] 9 | } 10 | 11 | # Convert letters to upper-case as list 12 | output "upper-case-list" { 13 | value = [for l in var.letters: upper(l)] 14 | } 15 | 16 | # Convert letters to upper-case as map 17 | output "upper-case-map" { 18 | value = {for l in var.letters: l => upper(l)} 19 | } 20 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/new-template-syntax/actual_vote.txt: -------------------------------------------------------------------------------- 1 | 2 | I cast my vote for ${candidate} 3 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/new-template-syntax/rigged_vote.txt: -------------------------------------------------------------------------------- 1 | 2 | I cast my vote for %{ if candidate == "Dan McCready" }Mark Harris%{ else }${candidate}%{ endif } 3 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable-correct.tf.txt: -------------------------------------------------------------------------------- 1 | { 2 | "variable": { 3 | "example": { 4 | "default": "foo" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable-with-comment.tf.txt: -------------------------------------------------------------------------------- 1 | { 2 | "variable": { 3 | "example": { 4 | "//": "This property is a comment and ignored", 5 | "default": "foo" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable1.tf.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": { 3 | "example": "foo" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable2.tf.txt: -------------------------------------------------------------------------------- 1 | { 2 | "variable": "name" { 3 | "example": "foo" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable3.tf.txt: -------------------------------------------------------------------------------- 1 | { 2 | "variable": { 3 | "name": "foo", 4 | "example": "foo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/reliable-json-syntax/variable4.tf.txt: -------------------------------------------------------------------------------- 1 | { 2 | "variable": { 3 | "example": { 4 | "label": "foo" 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/rich-value-types/network/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "my_vpc" { 2 | cidr_block = var.network_config.vpc_cidr 3 | tags = { 4 | Name = var.network_config.vpc_name 5 | } 6 | } 7 | 8 | resource "aws_subnet" "my_subnet" { 9 | vpc_id = aws_vpc.my_vpc.id 10 | cidr_block = var.network_config.subnet_cidr 11 | tags = { 12 | Name = var.network_config.subnet_name 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/rich-value-types/network/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc" { 2 | value = aws_vpc.my_vpc 3 | } 4 | 5 | output "subnet" { 6 | value = aws_subnet.my_subnet 7 | } 8 | 9 | output "subnet_id" { 10 | value = aws_subnet.my_subnet.id 11 | } 12 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.12-examples/rich-value-types/network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "network_config" { 2 | type = object({ 3 | vpc_name = string 4 | vpc_cidr = string 5 | subnet_name = string 6 | subnet_cidr = string 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/main-1.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | module "write-files" { 6 | source = "./modules/write-files" 7 | } 8 | 9 | module "read-files" { 10 | source = "./modules/read-files" 11 | } 12 | 13 | output "fruit" { 14 | value = module.read-files.fruit 15 | } 16 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/main-2.tf.txt: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | module "write-files-complicated" { 6 | source = "./modules/write-files-complicated" 7 | } 8 | 9 | module "read-files-complicated" { 10 | source = "./modules/read-files-complicated" 11 | wait_for_write = module.write-files-complicated.write_done 12 | } 13 | 14 | output "fruit" { 15 | value = module.read-files-complicated.fruit 16 | } 17 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/main-3.tf.txt: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | module "write-files" { 6 | source = "./modules/write-files" 7 | } 8 | 9 | module "read-files" { 10 | source = "./modules/read-files" 11 | depends_on = [module.write-files] 12 | } 13 | 14 | output "fruit" { 15 | value = module.read-files.fruit 16 | } 17 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/modules/read-files-complicated/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | variable "wait_for_write" {} 6 | 7 | resource "null_resource" "dependency" { 8 | triggers = { 9 | dependency_id = var.wait_for_write 10 | } 11 | 12 | } 13 | 14 | data "local_file" "apple" { 15 | filename = "${path.root}/apple.txt" 16 | depends_on = [null_resource.dependency] 17 | } 18 | 19 | data "local_file" "banana" { 20 | filename = "${path.root}/banana.txt" 21 | depends_on = [null_resource.dependency] 22 | } 23 | 24 | data "local_file" "orange" { 25 | filename = "${path.root}/orange.txt" 26 | depends_on = [null_resource.dependency] 27 | } 28 | 29 | output "fruit" { 30 | value = [ 31 | data.local_file.apple.content, 32 | data.local_file.banana.content, 33 | data.local_file.orange.content, 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/modules/read-files/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | data "local_file" "apple" { 6 | filename = "${path.root}/apple.txt" 7 | } 8 | 9 | data "local_file" "banana" { 10 | filename = "${path.root}/banana.txt" 11 | } 12 | 13 | data "local_file" "orange" { 14 | filename = "${path.root}/orange.txt" 15 | } 16 | 17 | output "fruit" { 18 | value = [ 19 | data.local_file.apple.content, 20 | data.local_file.banana.content, 21 | data.local_file.orange.content, 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/modules/write-files-complicated/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | resource "local_file" "apple" { 6 | content = "apple" 7 | filename = "${path.root}/apple.txt" 8 | } 9 | 10 | resource "local_file" "banana" { 11 | content = "banana" 12 | filename = "${path.root}/banana.txt" 13 | } 14 | 15 | resource "local_file" "orange" { 16 | content = "orange" 17 | filename = "${path.root}/orange.txt" 18 | } 19 | 20 | output "write_done" { 21 | value = "apples, bananas, and oranges" 22 | } 23 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-0.13-examples/module-depends-on/modules/write-files/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.13.0" 3 | } 4 | 5 | resource "local_file" "apple" { 6 | content = "apple" 7 | filename = "${path.root}/apple.txt" 8 | } 9 | 10 | resource "local_file" "banana" { 11 | content = "banana" 12 | filename = "${path.root}/banana.txt" 13 | } 14 | 15 | resource "local_file" "orange" { 16 | content = "orange" 17 | filename = "${path.root}/orange.txt" 18 | } 19 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # .tfvars files 9 | *.tfvars 10 | 11 | # Emacs backup files 12 | *~ 13 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 kawsark-git-org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/examples/simple/main.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_credentials" { 2 | description = "GCP credentials needed by Google Terraform provider" 3 | } 4 | 5 | variable "gcp_project" { 6 | description = "GCP project name needed by Google Terraform provider" 7 | } 8 | 9 | variable "region" { 10 | default = "us-central1" 11 | } 12 | 13 | variable "gcp_sql_root_user_pw" {} 14 | 15 | variable "authorized_network" {} 16 | 17 | module "example-gcp-cloudsql" { 18 | source = "github.com/hashicorp/terraform-guides/tree/terraform-gcp-cloudsql/infrastructure-as-code/terraform-gcp-cloudsql" 19 | gcp_credentials = "${var.gcp_credentials}" 20 | gcp_project = "${var.gcp_project}" 21 | region = "${var.region}" 22 | database_name_prefix = "simple-cloudsql" 23 | gcp_sql_root_user_pw = "${var.gcp_sql_root_user_pw}" 24 | authorized_network = "${var.authorized_network}" 25 | } 26 | 27 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | credentials = "${var.gcp_credentials}" 3 | project = "${var.gcp_project}" 4 | region = "${var.region}" 5 | } 6 | 7 | # Random identifier for Database name 8 | resource "random_pet" "database_name" { 9 | prefix = "${var.database_name_prefix}" 10 | separator = "-" 11 | } 12 | 13 | resource "google_sql_database_instance" "cloudsql-postgres-master" { 14 | name = "${random_pet.database_name.id}" 15 | database_version = "${var.database_version}" 16 | region = "${var.region}" 17 | 18 | settings { 19 | # Second-generation instance tiers are based on the machine 20 | # type. See argument reference below. 21 | tier = "db-f1-micro" 22 | ip_configuration { 23 | ipv4_enabled = true 24 | require_ssl = false 25 | authorized_networks = { 26 | name = "terraform-server-IP-allowed-list" 27 | value = "${var.authorized_network}" 28 | } 29 | } 30 | } 31 | } 32 | 33 | resource "google_sql_user" "users" { 34 | name = "${var.gcp_sql_root_user_name}" 35 | instance = "${google_sql_database_instance.cloudsql-postgres-master.name}" 36 | password = "${var.gcp_sql_root_user_pw}" 37 | } 38 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/outputs.tf: -------------------------------------------------------------------------------- 1 | output "connection_name" { 2 | value = "${google_sql_database_instance.cloudsql-postgres-master.connection_name}" 3 | } 4 | 5 | output "ip" { 6 | value = "${google_sql_database_instance.cloudsql-postgres-master.ip_address.0.ip_address}" 7 | } 8 | 9 | -------------------------------------------------------------------------------- /infrastructure-as-code/terraform-gcp-cloudsql/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_credentials" { 2 | description = "GCP credentials needed by Google Terraform provider" 3 | } 4 | 5 | variable "gcp_project" { 6 | description = "GCP project name needed by Google Terraform provider" 7 | } 8 | 9 | variable "region" { 10 | default = "us-central1" 11 | } 12 | 13 | variable "gcp_sql_root_user_name" { 14 | default = "root" 15 | } 16 | 17 | variable "gcp_sql_root_user_pw" {} 18 | 19 | variable "authorized_network" {} 20 | 21 | variable "database_name_prefix" { 22 | default = "cloudsql-master" 23 | } 24 | 25 | variable "database_version" { 26 | default = "POSTGRES_9_6" 27 | } 28 | 29 | -------------------------------------------------------------------------------- /operations/automation-script/config/main.tf: -------------------------------------------------------------------------------- 1 | variable "name" { 2 | default = "Walter" 3 | } 4 | 5 | resource "random_id" "random" { 6 | keepers = { 7 | uuid = uuid() 8 | } 9 | byte_length = 32 10 | } 11 | 12 | output "random" { 13 | value = random_id.random.hex 14 | } 15 | 16 | output "hello_world" { 17 | value = "Hello, ${var.name}" 18 | } 19 | -------------------------------------------------------------------------------- /operations/automation-script/restrict-name-variable.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan" 2 | 3 | # Rule to restrict name variable 4 | name_allowed = rule { 5 | tfplan.variables.name != "Roger" 6 | } 7 | 8 | # Main rule that requires other rules to be true 9 | main = rule { 10 | (name_allowed) else true 11 | } 12 | -------------------------------------------------------------------------------- /operations/automation-script/variables.csv: -------------------------------------------------------------------------------- 1 | name,Roger,terraform,false,false 2 | TF_CLI_ARGS,-no-color,env,false,false 3 | -------------------------------------------------------------------------------- /operations/sentinel-policies-scripts/policy-set/sentinel.hcl: -------------------------------------------------------------------------------- 1 | module "tfplan-functions" { 2 | source = "https://raw.githubusercontent.com/hashicorp/terraform-guides/master/governance/third-generation/common-functions/tfplan-functions/tfplan-functions.sentinel" 3 | } 4 | 5 | module "tfconfig-functions" { 6 | source = "https://raw.githubusercontent.com/hashicorp/terraform-guides/fix-policy-set-example/governance/third-generation/common-functions/tfconfig-functions/tfconfig-functions.sentinel" 7 | } 8 | 9 | policy "restrict-s3-bucket-policies" { 10 | source = "./restrict-s3-bucket-policies.sentinel" 11 | enforcement_level = "advisory" 12 | } 13 | 14 | policy "restrict-sagemaker-notebooks" { 15 | source = "./restrict-sagemaker-notebooks.sentinel" 16 | enforcement_level = "soft-mandatory" 17 | } 18 | -------------------------------------------------------------------------------- /operations/variable-scripts/hcl-variables.csv: -------------------------------------------------------------------------------- 1 | a_list;[\\"Roger\\",\\"Sean\\",\\"Kawsar\\"];terraform;true;false 2 | a_map;{\\"Thomas\\":\\"New York\\",\\"Jake\\":\\"Los Angeles\\"};terraform;true;false 3 | -------------------------------------------------------------------------------- /operations/variable-scripts/other-variables.csv: -------------------------------------------------------------------------------- 1 | aws_region;us-east-1;terraform;false;false;preferred region 2 | instance_type;t2.micro;terraform;false;false;choose an appropriate instance size 3 | CONFIRM_DESTROY;1;env;false;false;allows destroy plans to be executed 4 | AWS_ACCESS_KEY_ID;AKIA3449403293;env;false;true;this is a secure value 5 | AWS_SECRET_ACCESS_KEY;dds9ip2330323wkd022ldw;env;false;true; this is a secure value 6 | -------------------------------------------------------------------------------- /operations/variable-scripts/variables.csv: -------------------------------------------------------------------------------- 1 | name;Roger;terraform;false;false 2 | CONFIRM_DESTROY;1;env;false;false 3 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/README.md: -------------------------------------------------------------------------------- 1 | # Source Code for Cats-and-Dogs Applications 2 | The source code for the Cats-and-Dogs applications deployed to Kubernetes pods and services using the Terraform configuration [k8s-services](../k8s-services) for AKS or GKE or the Terraform configuration [k8s-services-openshift](../k8s-services-openshift) for OpenShift. 3 | 4 | ## Backend 5 | The cats-and-dogs-backend application runs a redis database that stores votes recorded by users of the cats-and-dogs-frontend web application. It authenticates itself to a Vault server with the Kubernetes JWT service account token, reads the redis_pwd from Vault, and then starts the redis database with that password. 6 | 7 | ## Frontend 8 | The cats-and-dogs-frontend application is a simple Python web application that lets users vote for their favorite pets. It authenticates itself to a Vault server with the Kubernetes JWT service account token, reads the redis_pwd from Vault, and then connects to the redis database running in the cats-and-dogs-backend pod with that password. 9 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM redis 2 | 3 | RUN apt-get update 4 | RUN apt-get install -y curl 5 | RUN apt-get install -y python3-pip 6 | ADD /vote-db /app 7 | 8 | ENTRYPOINT ["docker-entrypoint.sh"] 9 | 10 | EXPOSE 6379 11 | 12 | CMD ["/app/start_redis.sh"] 13 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/backend/vote-db/start_redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Authenticate against Vault 3 | login_result=$(curl --request POST --data '{"role": "demo", "jwt": "'"${K8S_TOKEN}"'"}' ${VAULT_ADDR}/v1/auth/${VAULT_K8S_BACKEND}/login) 4 | 5 | # Read cats-and-dogs secret from Vault 6 | vault_token=$(echo $login_result | python3 -c "import sys, json; print(json.load(sys.stdin)['auth']['client_token'])") 7 | 8 | cats_and_dogs=$(curl -H "X-Vault-Token:$vault_token" ${VAULT_ADDR}/v1/secret/${VAULT_USER}/kubernetes/cats-and-dogs) 9 | 10 | redis_pwd=$(echo $cats_and_dogs | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['redis_pwd'])") 11 | echo "redis_pwd is: $redis_pwd" 12 | redis-server --requirepass $redis_pwd 13 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tiangolo/uwsgi-nginx-flask:python3.6 2 | 3 | RUN pip install redis hvac 4 | 5 | ADD /azure-vote /app 6 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/frontend/azure-vote/config_file.cfg: -------------------------------------------------------------------------------- 1 | # UI Configurations 2 | TITLE = 'Pets Voting App' 3 | VOTE1VALUE = 'Cats' 4 | VOTE2VALUE = 'Dogs' 5 | SHOWHOST = 'false' 6 | -------------------------------------------------------------------------------- /self-serve-infrastructure/cats-and-dogs/frontend/azure-vote/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 | 22 |
23 |
24 |
{{button1}} - {{ value1 }} | {{button2}} - {{ value2 }}
25 | 26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/README.md: -------------------------------------------------------------------------------- 1 | This directory includes some examples of provisioning networking infrastructure in AWS, Azure, and Google. 2 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-aws/_interface.tf: -------------------------------------------------------------------------------- 1 | variable "region" { 2 | default = "" 3 | description = "The default AZ to provision to for the provider" 4 | } 5 | 6 | variable "vpc_cidr_block" { 7 | default = "" 8 | description = "The default CIDR block for the VPC demo" 9 | } 10 | 11 | variable "subnet_cidr_block" { 12 | default = "" 13 | description = "The default CIDR block for the subnet demo" 14 | } 15 | 16 | variable "subnet_availability_zone" { 17 | default = "" 18 | description = "The default AZ for the subnet" 19 | } 20 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.region}" 3 | } 4 | 5 | resource "aws_vpc" "demo_vpc" { 6 | cidr_block = "${var.vpc_cidr_block}" 7 | 8 | tags { 9 | Name = "fp_demo_vpc" 10 | } 11 | } 12 | 13 | resource "aws_subnet" "demo_subnet" { 14 | vpc_id = "${aws_vpc.demo_vpc.id}" 15 | cidr_block = "${var.subnet_cidr_block}" 16 | availability_zone = "${var.subnet_availability_zone}" 17 | 18 | tags { 19 | Name = "fp_demo_subnet" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-aws/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id_consumable" { 2 | value = "${aws_vpc.demo_vpc.id}" 3 | description = "This is the VPC ID for later use" 4 | } 5 | 6 | output "demo_subnet_id" { 7 | value = "${aws_subnet.demo_subnet.id}" 8 | description = "This is the Subnet ID for later use" 9 | } 10 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-aws/terraform.auto.tfvars: -------------------------------------------------------------------------------- 1 | # name = "self-serve-getting-started-override" # Override "name" variable default 2 | # instance_type = "t2.small" # Override "instance_type" variable default 3 | # tags = { foo = "bar" fizz = "buzz" } # Override "tags" variable default 4 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-azure/_interface.tf: -------------------------------------------------------------------------------- 1 | variable "rg_name" { 2 | default = "" 3 | description = "The default name for the Resource Group" 4 | } 5 | 6 | variable "rg_location" { 7 | default = "" 8 | description = "The default name for the Resource Group" 9 | } 10 | 11 | variable "vn_name" { 12 | default = "" 13 | description = "The default name for the Virtual Network" 14 | } 15 | 16 | variable "vn_address_space" { 17 | default = "" 18 | description = "The default address space for the Virtual Network" 19 | } 20 | 21 | variable "sb_name" { 22 | default = "" 23 | description = "The default name for the subnet" 24 | } 25 | 26 | variable "sb_address_prefix" { 27 | default = "" 28 | description = "The default address prefix for the Subnet" 29 | } 30 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-azure/main.tf: -------------------------------------------------------------------------------- 1 | provider "azurerm" { 2 | subscription_id = "" 3 | client_id = "" 4 | client_secret = "" 5 | tenant_id = "" 6 | } 7 | 8 | resource "azurerm_resource_group" "demo_resource_group" { 9 | name = "${var.rg_name}" 10 | location = "${var.rg_location}" 11 | } 12 | 13 | resource "azurerm_virtual_network" "demo_virtual_network" { 14 | name = "${var.vn_name}" 15 | address_space = ["${var.vn_address_space}"] 16 | location = "${azurerm_resource_group.demo_resource_group.location}" 17 | resource_group_name = "${azurerm_resource_group.demo_resource_group.name}" 18 | } 19 | 20 | resource "azurerm_subnet" "demo_subnet" { 21 | name = "${var.sb_name}" 22 | resource_group_name = "${azurerm_resource_group.demo_virtual_network.name}" 23 | virtual_network_name = "${azurerm_virtual_network.demo_virtual_network.name}" 24 | address_prefix = "${var.sb_address_prefix}" 25 | } 26 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-azure/outputs.tf: -------------------------------------------------------------------------------- 1 | output "resource_group_consumable" { 2 | value = "${azurerm_resource_group.demo_resource_group.name}" 3 | description = "The Demo VPC Name for later use" 4 | } 5 | 6 | output "virtual_network_consumable_name" { 7 | value = "${azurerm_virtual_network.demo_virtual_network.name}" 8 | description = "The Demo Virtaul Network name for later use" 9 | } 10 | 11 | output "virtual_network_consumable_address_space" { 12 | value = "${azurerm_virtual_network.demo_virtual_network.address_space}" 13 | description = "The Demo Virtaul Network address space for later use" 14 | } 15 | 16 | output "subnet_consumable" { 17 | value = "${azurerm_subnet.demo_subnet.address_prefix}" 18 | description = "The Demo Subnet for later use" 19 | } 20 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-azure/terraform.auto.tfvars: -------------------------------------------------------------------------------- 1 | # name = "self-serve-getting-started-override" # Override "name" variable default 2 | # network_location = "westus" # Override "network_location" variable default 3 | # compute_location = "West US 2" # Override "compute_location" variable default 4 | # tags = { foo = "bar" fizz = "buzz" } # Override "tags" variable default 5 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-gcp/_interface.tf: -------------------------------------------------------------------------------- 1 | variable "gn_name" { 2 | default = "" 3 | description = "The default name for the Compute Network" 4 | } 5 | 6 | variable "sn_name" { 7 | default = "" 8 | description = "The default name for the subnet" 9 | } 10 | 11 | variable "sn_region" { 12 | default = "" 13 | description = "The default region for the subnet" 14 | } 15 | 16 | variable "sn_cidr_range" { 17 | default = "" 18 | description = "The default Subnet Cidr Range" 19 | } 20 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-gcp/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | project = "terraform-gcp-module-test" 3 | region = "us-central1" 4 | project = "terraform-gcp-module-test" 5 | } 6 | 7 | resource "google_compute_network" "demo_network" { 8 | name = "${var.gn_name}" 9 | auto_create_subnetworks = "false" 10 | } 11 | 12 | resource "google_compute_subnetwork" "demo_subnetwork" { 13 | network = "${google_compute_network.demo_network.name}" 14 | name = "${var.sn_name}" 15 | region = "${var.sn_region}" 16 | ip_cidr_range = "${var.sn_cidr_range}" 17 | } 18 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-gcp/outputs.tf: -------------------------------------------------------------------------------- 1 | output "compute_network_consumable" { 2 | value = "${google_compute_network.demo_network.name}" 3 | description = "The Network Name" 4 | } 5 | 6 | output "subnetwork_consumable_name" { 7 | value = "${google_compute_subnetwork.demo_subnetwork.name}" 8 | description = "The Subnet Name" 9 | } 10 | 11 | output "subnetwork_consumable_ip_cidr_range" { 12 | value = "${google_compute_subnetwork.demo_subnetwork.ip_cidr_range}" 13 | description = "The default Cidr Range" 14 | } 15 | -------------------------------------------------------------------------------- /self-serve-infrastructure/getting-started/terraform-gcp/terraform.auto.tfvars: -------------------------------------------------------------------------------- 1 | # name = "self-serve-getting-started-override" # Override "name" variable default 2 | # region = "us-west1" # Override "region" variable default 3 | # zone = "us-west1-a" # Override "zone" variable default 4 | # service_port = "80" # Override "service_port" variable default 5 | # tags = { foo = "bar" fizz = "buzz" } # Override "tags" variable default 6 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services-openshift/cats-and-dogs-secret-name: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-guides/38d077a6da77fffe5f8469e992fe79a852339871/self-serve-infrastructure/k8s-services-openshift/cats-and-dogs-secret-name -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services-openshift/cats-and-dogs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: cats-and-dogs 5 | namespace: cats-and-dogs 6 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services-openshift/openshift.tfvars.example: -------------------------------------------------------------------------------- 1 | tfe_organization = "" 2 | k8s_cluster_workspace = "k8s-cluster-openshift" 3 | private_key_data= "" 4 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services-openshift/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cats_and_dogs_dns" { 2 | value = "http://cats-and-dogs-frontend.${data.terraform_remote_state.k8s_cluster.master_public_ip}.xip.io" 3 | } 4 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services-openshift/variables.tf: -------------------------------------------------------------------------------- 1 | variable "tfe_organization" { 2 | description = "TFE organization" 3 | } 4 | 5 | variable "k8s_cluster_workspace" { 6 | description = "workspace to use for the k8s cluster" 7 | } 8 | 9 | variable "private_key_data" { 10 | description = "contents of the private key" 11 | } 12 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services/outputs.tf: -------------------------------------------------------------------------------- 1 | output "cats_and_dogs_ip" { 2 | value = "${kubernetes_service.cats-and-dogs-frontend.load_balancer_ingress.0.ip}" 3 | } 4 | -------------------------------------------------------------------------------- /self-serve-infrastructure/k8s-services/variables.tf: -------------------------------------------------------------------------------- 1 | variable "tfe_organization" { 2 | description = "TFE organization" 3 | default = "RogerBerlind" 4 | } 5 | 6 | variable "k8s_cluster_workspace" { 7 | description = "workspace to use for the k8s cluster" 8 | } 9 | 10 | variable "k8s_vault_config_workspace" { 11 | description = "workspace to use for the vault configuration" 12 | } 13 | 14 | variable "frontend_image" { 15 | default = "rberlind/cats-and-dogs-frontend:k8s-auth" 16 | description = "Docker image location of the frontend app" 17 | } 18 | 19 | variable "backend_image" { 20 | default = "rberlind/cats-and-dogs-backend:k8s-auth" 21 | description = "Docker image location of the frontend app" 22 | } 23 | --------------------------------------------------------------------------------