├── .github ├── CODEOWNERS └── workflows │ └── sentinel.yml ├── .gitignore ├── LICENSE ├── README.md ├── cis ├── aws │ └── networking │ │ ├── README.md │ │ ├── aws-cis-4.1-networking-deny-public-ssh-acl-rules │ │ ├── aws-cis-4.1-networking-deny-public-ssh-acl-rules.sentinel │ │ ├── test │ │ │ └── aws-cis-4.1-networking-deny-public-ssh-acl-rules │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ ├── aws-cis-4.2-networking-deny-public-rdp-acl-rules │ │ ├── aws-cis-4.2-networking-deny-public-rdp-acl-rules.sentinel │ │ ├── test │ │ │ └── aws-cis-4.2-networking-deny-public-rdp-acl-rules │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ └── aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules │ │ ├── aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules.sentinel │ │ ├── test │ │ └── aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel ├── azure │ ├── compute │ │ ├── README.md │ │ ├── azure-cis-7.1-compute-managed-disk-encryption-is-enabled │ │ │ ├── azure-cis-7.1-compute-managed-disk-encryption-is-enabled.sentinel │ │ │ ├── test │ │ │ │ └── azure-cis-7.1-compute-managed-disk-encryption-is-enabled │ │ │ │ │ ├── failure.hcl │ │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ │ └── mock-tfplan-success.sentinel │ │ └── azure-cis-7.4-compute-only-approved-extensions-are-installed │ │ │ ├── azure-cis-7.4-compute-only-approved-extensions-are-installed.sentinel │ │ │ ├── test │ │ │ └── azure-cis-7.4-compute-only-approved-extensions-are-installed │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── databases │ │ ├── README.md │ │ ├── azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled │ │ │ ├── azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled.sentinel │ │ │ ├── test │ │ │ │ └── azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled │ │ │ │ │ ├── failure.hcl │ │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ │ └── mock-tfplan-success.sentinel │ │ └── azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled │ │ │ ├── azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled.sentinel │ │ │ ├── test │ │ │ └── azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── networking │ │ ├── README.md │ │ ├── azure-cis-6.1-networking-deny-public-rdp-nsg-rules │ │ │ ├── azure-cis-6.1-networking-deny-public-rdp-nsg-rules.sentinel │ │ │ ├── test │ │ │ │ └── azure-cis-6.1-networking-deny-public-rdp-nsg-rules │ │ │ │ │ ├── failure.hcl │ │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ │ └── mock-tfplan-success.sentinel │ │ ├── azure-cis-6.2-networking-deny-public-ssh-nsg-rules │ │ │ ├── azure-cis-6.2-networking-deny-public-ssh-nsg-rules.sentinel │ │ │ ├── test │ │ │ │ └── azure-cis-6.2-networking-deny-public-ssh-nsg-rules │ │ │ │ │ ├── failure.hcl │ │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ │ └── mock-tfplan-success.sentinel │ │ ├── azure-cis-6.3-networking-deny-any-sql-database-ingress │ │ │ ├── azure-cis-6.3-networking-deny-any-sql-database-ingress.sentinel │ │ │ ├── test │ │ │ │ └── azure-cis-6.3-networking-deny-any-sql-database-ingress │ │ │ │ │ ├── failure.hcl │ │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ │ └── mock-tfplan-success.sentinel │ │ └── azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period │ │ │ ├── azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period.sentinel │ │ │ ├── test │ │ │ └── azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ └── storage │ │ ├── README.md │ │ ├── azure-cis-3.1-storage-secure-transfer-required-is-enabled │ │ ├── azure-cis-3.1-storage-secure-transfer-required-is-enabled.sentinel │ │ ├── test │ │ │ └── azure-cis-3.1-storage-secure-transfer-required-is-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ ├── azure-cis-3.3-storage-queue-logging-is-enabled │ │ ├── azure-cis-3.3-storage-queue-logging-is-enabled.sentinel │ │ ├── test │ │ │ └── azure-cis-3.3-storage-queue-logging-is-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ ├── azure-cis-3.6-storage-blob-public-access-level-set-to-private │ │ ├── azure-cis-3.6-storage-blob-public-access-level-set-to-private.sentinel │ │ ├── test │ │ │ └── azure-cis-3.6-storage-blob-public-access-level-set-to-private │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ ├── azure-cis-3.7-storage-default-network-access-rule-set-to-deny │ │ ├── azure-cis-3.7-storage-default-network-access-rule-set-to-deny.sentinel │ │ ├── test │ │ │ └── azure-cis-3.7-storage-default-network-access-rule-set-to-deny │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ │ └── azure-cis-3.8-storage-trusted-microsoft-services-is-enabled │ │ ├── azure-cis-3.8-storage-trusted-microsoft-services-is-enabled.sentinel │ │ ├── test │ │ └── azure-cis-3.8-storage-trusted-microsoft-services-is-enabled │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel └── gcp │ ├── compute │ ├── README.md │ ├── gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances │ │ ├── gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances.sentinel │ │ ├── test │ │ │ └── gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project │ │ ├── gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project.sentinel │ │ ├── test │ │ │ └── gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance │ │ ├── gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance.sentinel │ │ ├── test │ │ │ └── gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances │ │ ├── gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances.sentinel │ │ ├── test │ │ │ └── gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ └── gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys │ │ ├── gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys.sentinel │ │ ├── test │ │ └── gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel │ ├── databases │ ├── README.md │ ├── gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl │ │ ├── gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl.sentinel │ │ ├── test │ │ │ └── gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ └── gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world │ │ ├── gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world.sentinel │ │ ├── test │ │ └── gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel │ ├── kubernetes │ ├── README.md │ ├── gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled │ │ ├── gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled │ │ ├── gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters │ │ ├── gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled │ │ ├── gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters │ │ ├── gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access │ │ ├── gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters │ │ ├── gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels │ │ ├── gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters │ │ ├── gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes │ │ ├── gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes.sentinel │ │ ├── test │ │ │ └── gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ └── gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image │ │ ├── gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image.sentinel │ │ ├── test │ │ └── gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel │ ├── networking │ ├── README.md │ ├── gcp-cis-3.1-networking-deny-default-network-in-project │ │ ├── gcp-cis-3.1-networking-deny-default-network-in-project.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.1-networking-deny-default-network-in-project │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns │ │ ├── gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key │ │ ├── gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key │ │ ├── gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.6-networking-ssh-is-restricted-from-internet │ │ ├── gcp-cis-3.6-networking-ssh-is-restricted-from-internet.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.6-networking-ssh-is-restricted-from-internet │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.7-networking-rdp-is-restricted-from-internet │ │ ├── gcp-cis-3.7-networking-rdp-is-restricted-from-internet.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.7-networking-rdp-is-restricted-from-internet │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ ├── gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets │ │ ├── gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets.sentinel │ │ ├── test │ │ │ └── gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets │ │ │ │ ├── failure.hcl │ │ │ │ └── success.hcl │ │ └── testdata │ │ │ ├── mock-tfplan-failure.sentinel │ │ │ └── mock-tfplan-success.sentinel │ └── gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets │ │ ├── gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets.sentinel │ │ ├── test │ │ └── gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel │ └── storage │ ├── README.md │ ├── gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access │ ├── gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access.sentinel │ ├── test │ │ └── gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access │ │ │ ├── failure.hcl │ │ │ └── success.hcl │ └── testdata │ │ ├── mock-tfplan-failure.sentinel │ │ └── mock-tfplan-success.sentinel │ └── gcp-cis-5.3-storage-bucket-logging-is-enabled │ ├── gcp-cis-5.3-storage-bucket-logging-is-enabled.sentinel │ ├── test │ └── gcp-cis-5.3-storage-bucket-logging-is-enabled │ │ ├── failure.hcl │ │ └── success.hcl │ └── testdata │ ├── mock-tfplan-failure.sentinel │ └── mock-tfplan-success.sentinel └── images ├── policy-sets-create.png ├── policy-sets-navigate-1.png ├── policy-sets-navigate-2.png ├── policy-sets-navigate-3.png └── policy-sets-run.png /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Each line is a file pattern followed by one or more owners. 2 | # More on CODEOWNERS files: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 3 | 4 | # HashiCorp Maintained Paths # Maintainer 5 | * @hashicorp/team-sentinel -------------------------------------------------------------------------------- /.github/workflows/sentinel.yml: -------------------------------------------------------------------------------- 1 | name: sentinel 2 | on: 3 | push: 4 | pull_request: 5 | branches: 6 | - master 7 | jobs: 8 | sentinel-format: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v2 13 | - name: Install Sentinel 14 | uses: bloominlabs/setup-hashicorp-releases@v1 15 | with: 16 | package: sentinel 17 | version: ^0.18.11 18 | - name: Sentinel Format 19 | run: sentinel fmt -check=true $(find . -name "*.sentinel") 20 | sentinel-test: 21 | needs: sentinel-format 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v2 26 | - name: Install Sentinel 27 | uses: bloominlabs/setup-hashicorp-releases@v1 28 | with: 29 | package: sentinel 30 | version: ^0.18.11 31 | - name: Sentinel Test 32 | run: sentinel test $(find . -name "*.sentinel" ! -path "*/testdata/*") -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS Related Files 2 | *.DS_Store* 3 | -------------------------------------------------------------------------------- /cis/aws/networking/README.md: -------------------------------------------------------------------------------- 1 | # CIS Amazon Web Services Foundational Sentinel policies 2 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Amazon Web Services Foundations Benchmark version 1.2.0](https://www.cisecurity.org/benchmark/amazon_web_services/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 3 | 4 | ## CIS 4.1: Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 5 | 6 | ### Description 7 | Removing unfettered connectivity to remote console services, such as SSH, reduces a server's exposure to risk. 8 | 9 | ### Configuration 10 | 11 | ```hcl 12 | policy "aws-cis-4.1-networking-deny-public-ssh-acl-rules" { 13 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.1-networking-deny-public-ssh-acl-rules/aws-cis-4.1-networking-deny-public-ssh-acl-rules.sentinel" 14 | enforcement_level = "advisory" 15 | } 16 | ``` 17 | 18 | ## CIS 4.2: Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 19 | 20 | ### Description 21 | Removing unfettered connectivity to remote console services, such as RDP, reduces a server's exposure to risk. 22 | 23 | ### Configuration 24 | 25 | ```hcl 26 | policy "aws-cis-4.2-networking-deny-public-rdp-acl-rules" { 27 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.2-networking-deny-public-rdp-acl-rules/aws-cis-4.2-networking-deny-public-rdp-acl-rules.sentinel" 28 | enforcement_level = "advisory" 29 | } 30 | ``` 31 | 32 | ## CIS 4.3: Ensure the default security group of every VPC restricts all traffic 33 | 34 | ### Description 35 | Configuring all VPC default security groups to restrict all traffic will encourage least privilege security group development and mindful placement of AWS resources into security groups which will in-turn reduce the exposure of those resources. 36 | 37 | ### Configuration 38 | 39 | ```hcl 40 | policy "aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules" { 41 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules.sentinel" 42 | enforcement_level = "advisory" 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.1-networking-deny-public-ssh-acl-rules/aws-cis-4.1-networking-deny-public-ssh-acl-rules.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | aws_security_groups = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "aws_security_group" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) and 8 | (resource_changes.change.after.ingress else []) is not empty 9 | } 10 | 11 | aws_security_group_rules = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.mode is "managed" and 13 | resource_changes.type is "aws_security_group_rule" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) and 16 | resource_changes.change.after.type is "ingress" 17 | } 18 | 19 | ssh_security_groups = filter aws_security_groups as _, asg { 20 | any asg.change.after.ingress as _, ingress { 21 | ingress.to_port is 22 or 22 | (ingress.from_port <= 22 and 23 | ingress.to_port >= 22) 24 | } 25 | } 26 | 27 | ssh_security_group_rules = filter aws_security_group_rules as _, asgr { 28 | asgr.change.after.to_port is 22 or 29 | (asgr.change.after.from_port <= 22 and 30 | asgr.change.after.to_port >= 22) 31 | } 32 | 33 | protocol_security_groups = filter aws_security_groups as _, asg { 34 | all asg.change.after.ingress as _, ingress { 35 | ingress.protocol is "-1" 36 | } 37 | } 38 | 39 | protocol_security_group_rules = filter aws_security_group_rules as _, asgr { 40 | asgr.change.after.protocol is "-1" 41 | } 42 | 43 | print("CIS 4.1: Ensure no AWS security groups allow ingress from 0.0.0.0/0 to port 22") 44 | 45 | deny_public_ssh_security_groups = rule { 46 | all ssh_security_groups as _, ssg { 47 | all ssg.change.after.ingress as _, ingress { 48 | ingress.cidr_blocks not contains "0.0.0.0/0" 49 | } 50 | } 51 | } 52 | 53 | deny_public_ssh_security_group_rules = rule { 54 | all ssh_security_group_rules as _, ssgr { 55 | ssgr.change.after.cidr_blocks not contains "0.0.0.0/0" 56 | } 57 | } 58 | 59 | deny_all_open_protocol_security_groups = rule { 60 | all protocol_security_groups as _, psg { 61 | all psg.change.after.ingress as _, ingress { 62 | ingress.cidr_blocks not contains "0.0.0.0/0" 63 | } 64 | } 65 | } 66 | 67 | deny_all_open_protocol_security_group_rules = rule { 68 | all protocol_security_group_rules as _, psgr { 69 | psgr.change.after.cidr_blocks not contains "0.0.0.0/0" 70 | } 71 | } 72 | 73 | main = rule { 74 | deny_public_ssh_security_groups and 75 | deny_public_ssh_security_group_rules and 76 | deny_all_open_protocol_security_groups and 77 | deny_all_open_protocol_security_group_rules 78 | } 79 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.1-networking-deny-public-ssh-acl-rules/test/aws-cis-4.1-networking-deny-public-ssh-acl-rules/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.1-networking-deny-public-ssh-acl-rules/test/aws-cis-4.1-networking-deny-public-ssh-acl-rules/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.2-networking-deny-public-rdp-acl-rules/aws-cis-4.2-networking-deny-public-rdp-acl-rules.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | aws_security_groups = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "aws_security_group" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) and 8 | (resource_changes.change.after.ingress else []) is not empty 9 | } 10 | 11 | aws_security_group_rules = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.mode is "managed" and 13 | resource_changes.type is "aws_security_group_rule" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) and 16 | resource_changes.change.after.type is "ingress" 17 | } 18 | 19 | rdp_security_groups = filter aws_security_groups as _, asg { 20 | any asg.change.after.ingress as _, ingress { 21 | ingress.to_port is 3389 or 22 | (ingress.from_port <= 3389 and 23 | ingress.to_port >= 3389) 24 | } 25 | } 26 | 27 | rdp_security_group_rules = filter aws_security_group_rules as _, asgr { 28 | asgr.change.after.to_port is 3389 or 29 | (asgr.change.after.from_port <= 3389 and 30 | asgr.change.after.to_port >= 3389) 31 | } 32 | 33 | protocol_security_groups = filter aws_security_groups as _, asg { 34 | all asg.change.after.ingress as _, ingress { 35 | ingress.protocol is "-1" 36 | } 37 | } 38 | 39 | protocol_security_group_rules = filter aws_security_group_rules as _, asgr { 40 | asgr.change.after.protocol is "-1" 41 | } 42 | 43 | print("CIS 4.2: Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389") 44 | 45 | deny_public_rdp_security_groups = rule { 46 | all rdp_security_groups as _, rsg { 47 | all rsg.change.after.ingress as _, ingress { 48 | ingress.cidr_blocks not contains "0.0.0.0/0" 49 | } 50 | } 51 | } 52 | 53 | deny_public_rdp_security_group_rules = rule { 54 | all rdp_security_group_rules as _, rsgr { 55 | rsgr.change.after.cidr_blocks not contains "0.0.0.0/0" 56 | } 57 | } 58 | 59 | deny_all_open_protocol_security_groups = rule { 60 | all protocol_security_groups as _, psg { 61 | all psg.change.after.ingress as _, ingress { 62 | ingress.cidr_blocks not contains "0.0.0.0/0" 63 | } 64 | } 65 | } 66 | 67 | deny_all_open_protocol_security_group_rules = rule { 68 | all protocol_security_group_rules as _, psgr { 69 | psgr.change.after.cidr_blocks not contains "0.0.0.0/0" 70 | } 71 | } 72 | 73 | main = rule { 74 | deny_public_rdp_security_groups and 75 | deny_public_rdp_security_group_rules and 76 | deny_all_open_protocol_security_groups and 77 | deny_all_open_protocol_security_group_rules 78 | } 79 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.2-networking-deny-public-rdp-acl-rules/test/aws-cis-4.2-networking-deny-public-rdp-acl-rules/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.2-networking-deny-public-rdp-acl-rules/test/aws-cis-4.2-networking-deny-public-rdp-acl-rules/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allDefaultNetworkACLs = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "aws_default_network_acl" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 4.3: Ensure the default security group of every VPC restricts all traffic") 11 | 12 | deny_undefined_ingress_configuration = rule { 13 | all allDefaultNetworkACLs as _, acls { 14 | keys(acls.change.after) contains "ingress" 15 | } 16 | } 17 | 18 | deny_all_vpc_inbound_acls = rule when deny_undefined_ingress_configuration is true { 19 | all allDefaultNetworkACLs as _, acls { 20 | length(acls.change.after.ingress) == 0 21 | } 22 | } 23 | 24 | deny_undefined_egress_configuration = rule { 25 | all allDefaultNetworkACLs as _, acls { 26 | keys(acls.change.after) contains "egress" 27 | } 28 | } 29 | 30 | deny_all_vpc_outbound_acls = rule when deny_undefined_egress_configuration is true { 31 | all allDefaultNetworkACLs as _, acls { 32 | length(acls.change.after.egress) == 0 33 | } 34 | } 35 | 36 | main = rule { 37 | deny_undefined_ingress_configuration and 38 | deny_undefined_egress_configuration and 39 | deny_all_vpc_inbound_acls and 40 | deny_all_vpc_outbound_acls 41 | } 42 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/test/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/test/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/aws/networking/aws-cis-4.3-networking-restrict-all-vpc-traffic-acl-rules/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = {"module.vpc.aws_default_network_acl.this[0]": { 2 | "address": "module.vpc.aws_default_network_acl.this[0]", 3 | "change": { 4 | "actions": [ 5 | "update", 6 | ], 7 | "after": { 8 | "default_network_acl_id": "acl-04485783afe0c55b6", 9 | "egress": [], 10 | "id": "acl-04485783afe0c55b6", 11 | "ingress": [], 12 | "owner_id": "636767228507", 13 | "subnet_ids": [], 14 | "tags": { 15 | "Environment": "dev", 16 | "Name": "", 17 | "Owner": "user", 18 | }, 19 | "vpc_id": "vpc-0a1637d0e11a942bf", 20 | }, 21 | "after_unknown": {}, 22 | "before": { 23 | "default_network_acl_id": "acl-04485783afe0c55b6", 24 | "egress": [ 25 | { 26 | "action": "allow", 27 | "cidr_block": "", 28 | "from_port": 0, 29 | "icmp_code": 0, 30 | "icmp_type": 0, 31 | "ipv6_cidr_block": "::/0", 32 | "protocol": "-1", 33 | "rule_no": 101, 34 | "to_port": 0, 35 | }, 36 | { 37 | "action": "allow", 38 | "cidr_block": "0.0.0.0/0", 39 | "from_port": 0, 40 | "icmp_code": 0, 41 | "icmp_type": 0, 42 | "ipv6_cidr_block": "", 43 | "protocol": "-1", 44 | "rule_no": 100, 45 | "to_port": 0, 46 | }, 47 | ], 48 | "id": "acl-04485783afe0c55b6", 49 | "ingress": [ 50 | { 51 | "action": "allow", 52 | "cidr_block": "", 53 | "from_port": 0, 54 | "icmp_code": 0, 55 | "icmp_type": 0, 56 | "ipv6_cidr_block": "::/0", 57 | "protocol": "-1", 58 | "rule_no": 101, 59 | "to_port": 0, 60 | }, 61 | { 62 | "action": "allow", 63 | "cidr_block": "0.0.0.0/0", 64 | "from_port": 0, 65 | "icmp_code": 0, 66 | "icmp_type": 0, 67 | "ipv6_cidr_block": "", 68 | "protocol": "-1", 69 | "rule_no": 100, 70 | "to_port": 0, 71 | }, 72 | ], 73 | "owner_id": "636767228507", 74 | "subnet_ids": [], 75 | "tags": { 76 | "Environment": "dev", 77 | "Name": "", 78 | "Owner": "user", 79 | }, 80 | "vpc_id": "vpc-0a1637d0e11a942bf", 81 | }, 82 | }, 83 | "deposed": "", 84 | "index": 0, 85 | "mode": "managed", 86 | "module_address": "module.vpc", 87 | "name": "this", 88 | "provider_name": "aws", 89 | "type": "aws_default_network_acl", 90 | }, 91 | } 92 | -------------------------------------------------------------------------------- /cis/azure/compute/README.md: -------------------------------------------------------------------------------- 1 | # CIS Microsoft Azure Foundational Sentinel policies 2 | 3 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Microsoft Azure Foundations Benchmark version 1.1.0](https://www.cisecurity.org/benchmark/azure/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 4 | 5 | ## CIS 7.1: Ensure that all managed disks (OS and Data) are encrypted 6 | 7 | ### Overview 8 | Encrypting the VM's OS and data disks ensures that all content is fully unrecoverable without a key and thus protects the volumes from unwarranted reads. 9 | 10 | ### Configuration 11 | 12 | ```hcl 13 | policy "azure-cis-7.1-compute-managed-disk-encryption-is-enabled" { 14 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/azure-cis-7.1-compute-managed-disk-encryption-is-enabled.sentinel" 15 | enforcement_level = "advisory" 16 | } 17 | ``` 18 | 19 | ## CIS 7.4: Ensure that only approved extensions are installed 20 | 21 | ### Overview 22 | Azure virtual machine extensions are small applications that run with administrative privileges on Azure virtual machines. These extensions could potentially access anything on a virtual machine and therefore only approved extensions should be used within an organizations Azure subscriptions. 23 | 24 | ### Configuration 25 | 26 | ```hcl 27 | policy "azure-cis-7.4-compute-only-approved-extensions-are-installed" { 28 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/compute/azure-cis-7.4-compute-only-approved-extensions-are-installed/azure-cis-7.4-compute-only-approved-extensions-are-installed.sentinel" 29 | enforcement_level = "advisory" 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/azure-cis-7.1-compute-managed-disk-encryption-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allManagedDisks = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "azurerm_managed_disk" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.1: Ensure that managed disks are encrypted") 11 | 12 | deny_undefined_encryption_settings = rule { 13 | all allManagedDisks as _, disks { 14 | keys(disks.change.after) contains "encryption_settings" and 15 | length(disks.change.after.encryption_settings) != 0 16 | } 17 | } 18 | 19 | deny_unencrypted_managed_disk = rule when deny_undefined_encryption_settings is true { 20 | all allManagedDisks as _, disks { 21 | all disks.change.after.encryption_settings as encryption_settings { 22 | encryption_settings.enabled is true 23 | } 24 | } 25 | } 26 | 27 | main = rule { 28 | deny_undefined_encryption_settings and 29 | deny_unencrypted_managed_disk 30 | } 31 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/test/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/test/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_managed_disk.insecure": { 3 | "address": "azurerm_managed_disk.insecure", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "create_option": "Empty", 10 | "disk_encryption_set_id": null, 11 | "disk_size_gb": 1, 12 | "encryption_settings": [], 13 | "image_reference_id": null, 14 | "location": "", 15 | "name": "insecuredisk", 16 | "os_type": null, 17 | "resource_group_name": "Sentinel-Foundations-Azure", 18 | "source_resource_id": null, 19 | "storage_account_id": null, 20 | "storage_account_type": "Standard_LRS", 21 | "tags": { 22 | "environment": "Production", 23 | }, 24 | "zones": null, 25 | }, 26 | "after_unknown": {}, 27 | "before": null, 28 | }, 29 | "deposed": "", 30 | "index": null, 31 | "mode": "managed", 32 | "module_address": "", 33 | "name": "insecure", 34 | "provider_name": "azurerm", 35 | "type": "azurerm_managed_disk", 36 | }, 37 | "azurerm_managed_disk.secure": { 38 | "address": "azurerm_managed_disk.secure", 39 | "change": { 40 | "actions": [ 41 | "create", 42 | ], 43 | "after": { 44 | "create_option": "Empty", 45 | "disk_encryption_set_id": null, 46 | "disk_size_gb": 1, 47 | "encryption_settings": [ 48 | { 49 | "disk_encryption_key": [ 50 | {}, 51 | ], 52 | "enabled": true, 53 | "key_encryption_key": [ 54 | {}, 55 | ], 56 | }, 57 | ], 58 | "image_reference_id": null, 59 | "location": "", 60 | "name": "securedisk", 61 | "os_type": null, 62 | "resource_group_name": "Sentinel-Foundations-Azure", 63 | "source_resource_id": null, 64 | "storage_account_id": null, 65 | "storage_account_type": "Standard_LRS", 66 | "tags": { 67 | "environment": "Production", 68 | }, 69 | "zones": null, 70 | }, 71 | "after_unknown": {}, 72 | "before": null, 73 | }, 74 | "deposed": "", 75 | "index": null, 76 | "mode": "managed", 77 | "module_address": "", 78 | "name": "secure", 79 | "provider_name": "azurerm", 80 | "type": "azurerm_managed_disk", 81 | }, 82 | } 83 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.1-compute-managed-disk-encryption-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_managed_disk.secure": { 3 | "address": "azurerm_managed_disk.secure", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "create_option": "Empty", 10 | "disk_encryption_set_id": null, 11 | "disk_size_gb": 1, 12 | "encryption_settings": [ 13 | { 14 | "disk_encryption_key": [ 15 | {}, 16 | ], 17 | "enabled": true, 18 | "key_encryption_key": [ 19 | {}, 20 | ], 21 | }, 22 | ], 23 | "image_reference_id": null, 24 | "location": "", 25 | "name": "securedisk", 26 | "os_type": null, 27 | "resource_group_name": "Sentinel-Foundations-Azure", 28 | "source_resource_id": null, 29 | "storage_account_id": null, 30 | "storage_account_type": "Standard_LRS", 31 | "tags": { 32 | "environment": "Production", 33 | }, 34 | "zones": null, 35 | }, 36 | "after_unknown": {}, 37 | "before": null, 38 | }, 39 | "deposed": "", 40 | "index": null, 41 | "mode": "managed", 42 | "module_address": "", 43 | "name": "secure", 44 | "provider_name": "azurerm", 45 | "type": "azurerm_managed_disk", 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.4-compute-only-approved-extensions-are-installed/azure-cis-7.4-compute-only-approved-extensions-are-installed.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | deniedVMExtensionTypes = [ 4 | "CustomScriptExtension", 5 | "CustomScript", 6 | "CustomScriptForLinux", 7 | ] 8 | 9 | allVMExtensions = filter tfplan.resource_changes as _, resource_changes { 10 | resource_changes.type is "azurerm_virtual_machine_extension" and 11 | resource_changes.mode is "managed" and 12 | (resource_changes.change.actions contains "create" or 13 | resource_changes.change.actions is ["update"]) 14 | } 15 | 16 | print("CIS 7.4: Ensure that only approved extensions are installed") 17 | 18 | deny_unsupported_virtual_machine_extensions = rule { 19 | all allVMExtensions as _, extension { 20 | extension.change.after.type not in deniedVMExtensionTypes 21 | } 22 | } 23 | 24 | main = rule { 25 | deny_unsupported_virtual_machine_extensions 26 | } 27 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.4-compute-only-approved-extensions-are-installed/test/azure-cis-7.4-compute-only-approved-extensions-are-installed/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.4-compute-only-approved-extensions-are-installed/test/azure-cis-7.4-compute-only-approved-extensions-are-installed/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/compute/azure-cis-7.4-compute-only-approved-extensions-are-installed/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_virtual_machine_extension.encryption": { 3 | "address": "azurerm_virtual_machine_extension.encryption", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "auto_upgrade_minor_version": null, 10 | "name": "hostname", 11 | "protected_settings": null, 12 | "publisher": "Microsoft.Azure.Security", 13 | "settings": "", 14 | "tags": { 15 | "environment": "Production", 16 | }, 17 | "type": "AzureDiskEncryption", 18 | "type_handler_version": "2.2", 19 | }, 20 | "after_unknown": {}, 21 | "before": null, 22 | }, 23 | "deposed": "", 24 | "index": null, 25 | "mode": "managed", 26 | "module_address": "", 27 | "name": "encryption", 28 | "provider_name": "azurerm", 29 | "type": "azurerm_virtual_machine_extension", 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /cis/azure/databases/README.md: -------------------------------------------------------------------------------- 1 | # CIS Microsoft Azure Foundational Sentinel policies 2 | 3 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Microsoft Azure Foundations Benchmark version 1.1.0](https://www.cisecurity.org/benchmark/azure/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 4 | 5 | ## CIS 4.11: Ensure 'Enforce SSL connection' is set to 'ENABLED' for MySQL Database Server 6 | 7 | ### Overview 8 | Enforcing SSL connections between database server and client applications helps protect against "man in the middle" attacks by encrypting the data stream between the server and application. 9 | 10 | ### Configuration 11 | 12 | ```hcl 13 | policy "azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled" { 14 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled.sentinel" 15 | enforcement_level = "advisory" 16 | } 17 | ``` 18 | 19 | ## CIS 4.13: Ensure 'Enforce SSL connection' is set to 'ENABLED' for PostgreSQL Database Server 20 | 21 | ### Overview 22 | Enforcing SSL connections between database server and client applications helps protect against "man in the middle" attacks by encrypting the data stream between the server and application. 23 | 24 | ### Configuration 25 | 26 | ```hcl 27 | policy "azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled" { 28 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled.sentinel" 29 | enforcement_level = "advisory" 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allMYSQLServers = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_mysql_server" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 4.11: Ensure 'Enforce SSL connection' is set to 'ENABLED' for MySQL Database Server") 11 | 12 | ssl_enforcement_is_enabled = rule { 13 | all allMYSQLServers as _, servers { 14 | servers.change.after.ssl_enforcement is "Enabled" 15 | } 16 | } 17 | 18 | main = rule { 19 | ssl_enforcement_is_enabled 20 | } 21 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/test/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/test/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_mysql_server.this": { 3 | "address": "azurerm_mysql_server.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "administrator_login": "secretadmin", 10 | "administrator_login_password": "password", 11 | "location": "australiaeast", 12 | "name": "test", 13 | "resource_group_name": "Sentinel-Foundations-Azure", 14 | "sku_name": "B_Gen5_2", 15 | "ssl_enforcement": "Disabled", 16 | "storage_profile": [ 17 | { 18 | "auto_grow": "Enabled", 19 | "backup_retention_days": null, 20 | "geo_redundant_backup": null, 21 | "storage_mb": 5120, 22 | }, 23 | ], 24 | "version": "5.7", 25 | }, 26 | "after_unknown": {}, 27 | "before": null, 28 | }, 29 | "deposed": "", 30 | "index": null, 31 | "mode": "managed", 32 | "module_address": "", 33 | "name": "this", 34 | "provider_name": "azurerm", 35 | "type": "azurerm_mysql_server", 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.11-databases-mysql-enforce-ssl-connection-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_mysql_server.this": { 3 | "address": "azurerm_mysql_server.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "administrator_login": "secretadmin", 10 | "administrator_login_password": "password", 11 | "location": "australiaeast", 12 | "name": "test", 13 | "resource_group_name": "Sentinel-Foundations-Azure", 14 | "sku_name": "B_Gen5_2", 15 | "ssl_enforcement": "Enabled", 16 | "storage_profile": [ 17 | { 18 | "auto_grow": "Enabled", 19 | "backup_retention_days": null, 20 | "geo_redundant_backup": null, 21 | "storage_mb": 5120, 22 | }, 23 | ], 24 | "version": "5.7", 25 | }, 26 | "after_unknown": {}, 27 | "before": null, 28 | }, 29 | "deposed": "", 30 | "index": null, 31 | "mode": "managed", 32 | "module_address": "", 33 | "name": "this", 34 | "provider_name": "azurerm", 35 | "type": "azurerm_mysql_server", 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allPGSQLServers = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_postgresql_server" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 4.11: Ensure 'Enforce SSL connection' is set to 'ENABLED' for MySQL Database Server") 11 | 12 | ssl_enforcement_is_enabled = rule { 13 | all allPGSQLServers as _, servers { 14 | servers.change.after.ssl_enforcement is "Enabled" 15 | } 16 | } 17 | 18 | main = rule { 19 | ssl_enforcement_is_enabled 20 | } 21 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/test/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/test/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_postgresql_server.this": { 3 | "address": "azurerm_postgresql_server.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "administrator_login": "psqladmin", 10 | "administrator_login_password": "password", 11 | "location": "australiaeast", 12 | "name": "postgresql-server-1", 13 | "resource_group_name": "Sentinel-Foundations-Azure", 14 | "sku_name": "B_Gen5_2", 15 | "ssl_enforcement": "Disabled", 16 | "storage_profile": [ 17 | { 18 | "auto_grow": "Enabled", 19 | "backup_retention_days": 7, 20 | "geo_redundant_backup": "Disabled", 21 | "storage_mb": 5120, 22 | }, 23 | ], 24 | "version": "9.5", 25 | }, 26 | "after_unknown": {}, 27 | "before": null, 28 | }, 29 | "deposed": "", 30 | "index": null, 31 | "mode": "managed", 32 | "module_address": "", 33 | "name": "this", 34 | "provider_name": "azurerm", 35 | "type": "azurerm_postgresql_server", 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /cis/azure/databases/azure-cis-4.13-databases-psql-enforce-ssl-connection-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_postgresql_server.this": { 3 | "address": "azurerm_postgresql_server.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "administrator_login": "psqladmin", 10 | "administrator_login_password": "password", 11 | "location": "australiaeast", 12 | "name": "postgresql-server-1", 13 | "resource_group_name": "Sentinel-Foundations-Azure", 14 | "sku_name": "B_Gen5_2", 15 | "ssl_enforcement": "Enabled", 16 | "storage_profile": [ 17 | { 18 | "auto_grow": "Enabled", 19 | "backup_retention_days": 7, 20 | "geo_redundant_backup": "Disabled", 21 | "storage_mb": 5120, 22 | }, 23 | ], 24 | "version": "9.5", 25 | }, 26 | "after_unknown": {}, 27 | "before": null, 28 | }, 29 | "deposed": "", 30 | "index": null, 31 | "mode": "managed", 32 | "module_address": "", 33 | "name": "this", 34 | "provider_name": "azurerm", 35 | "type": "azurerm_postgresql_server", 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /cis/azure/networking/README.md: -------------------------------------------------------------------------------- 1 | # CIS Microsoft Azure Foundational Sentinel policies 2 | 3 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Microsoft Azure Foundations Benchmark version 1.1.0](https://www.cisecurity.org/benchmark/azure/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 4 | 5 | ## CIS 6.1: Ensure that RDP access is restricted from the internet 6 | 7 | ### Overview 8 | The potential security problem with using RDP over the Internet is that attackers can use various brute force techniques to gain access to Azure Virtual Machines. This policy evaluates whether RDP access is disabled from the Internet. 9 | 10 | ### Configuration 11 | 12 | ```hcl 13 | policy "azure-cis-6.1-networking-deny-public-rdp-nsg-rules" { 14 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/networking/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/azure-cis-6.1-networking-deny-public-rdp-nsg-rules.sentinel" 15 | enforcement_level = "advisory" 16 | } 17 | ``` 18 | 19 | ## CIS 6.2: Ensure that SSH access is restricted from the internet 20 | 21 | ### Overview 22 | The potential security problem with using SSH over the Internet is that attackers can use various brute force techniques to gain access to Azure Virtual Machines. This policy evaluates whether SSH access is disabled from the Internet. 23 | 24 | ### Configuration 25 | 26 | ```hcl 27 | policy "azure-cis-6.2-networking-deny-public-ssh-nsg-rules" { 28 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/networking/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/azure-cis-6.2-networking-deny-public-ssh-nsg-rules.sentinel" 29 | enforcement_level = "advisory" 30 | } 31 | ``` 32 | 33 | ## CIS 6.3: Ensure no SQL Databases allow ingress 0.0.0.0/0 (ANY IP) 34 | 35 | ### Overview 36 | By default, for a SQL server, a Firewall exists with StartIp of 0.0.0.0 and EndIP of 0.0.0.0 allowing access to all the Azure services. In order to reduce the potential attack surface for a SQL server, firewall rules should be defined with more granular IP addresses by referencing the range of addresses available from specific datacenters. 37 | 38 | ### Configuration 39 | 40 | ```hcl 41 | policy "azure-cis-6.3-networking-deny-any-sql-database-ingress" { 42 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/networking/azure-cis-6.3-networking-deny-any-sql-database-ingress/azure-cis-6.3-networking-deny-any-sql-database-ingress.sentinel" 43 | enforcement_level = "advisory" 44 | } 45 | ``` 46 | 47 | ## CIS 6.4: Ensure that Network Security Group Flow Log retention period is 'greater than 90 days' 48 | 49 | ### Overview 50 | Flow logs enable capturing information about IP traffic flowing in and out of network security groups. Logs can be used to check for anomalies and give insight into suspected breaches. 51 | 52 | ### Configuration 53 | 54 | ```hcl 55 | policy "azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period" { 56 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period.sentinel" 57 | enforcement_level = "advisory" 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/azure-cis-6.1-networking-deny-public-rdp-nsg-rules.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | restricted_source_address_prefixes = ["*", "internet", "any", "0.0.0.0", "/0"] 5 | 6 | allNetworkSecurityGroups = filter tfplan.resource_changes as _, resource_changes { 7 | resource_changes.type is "azurerm_network_security_group" and 8 | resource_changes.mode is "managed" and 9 | (resource_changes.change.actions contains "create" or 10 | resource_changes.change.actions is ["update"]) 11 | } 12 | 13 | allNetworkSecurityRules = filter tfplan.resource_changes as _, resource_changes { 14 | resource_changes.type is "azurerm_network_security_rule" and 15 | resource_changes.mode is "managed" and 16 | (resource_changes.change.actions contains "create" or 17 | resource_changes.change.actions is ["update"]) 18 | } 19 | 20 | getNetworkSecurityGroupCompliance = func(groups, port) { 21 | mapSecurityRules = {} 22 | for groups as _, group { 23 | if keys(group.change.after) not contains "security_rule" { 24 | # Check if standalone Network Security Rule block(s) was defined. 25 | # 26 | # Terraform currently provides both a standalone Network Security 27 | # Rule resource, and allows for Network Security Rules to be 28 | # defined in-line within the Network Security Group resource. 29 | # At this time you cannot use a Network Security Group with 30 | # in-line Network Security Rules in conjunction with any 31 | # Network Security Rule resources. Doing so will cause a 32 | # conflict of rule settings and will overwrite rules. 33 | # 34 | # https://www.terraform.io/docs/providers/azurerm/r/network_security_rule.html 35 | for allNetworkSecurityRules as sr { 36 | destinationPortRange = allNetworkSecurityRules[sr]["change"]["after"]["destination_port_range"] 37 | sourceAddressPrefix = allNetworkSecurityRules[sr]["change"]["after"]["source_address_prefix"] 38 | securityRuleName = allNetworkSecurityRules[sr]["change"]["after"]["name"] 39 | if destinationPortRange is "*" or destinationPortRange is port { 40 | if sourceAddressPrefix in restricted_source_address_prefixes { 41 | mapSecurityRules[securityRuleName] = sr 42 | } 43 | } else if destinationPortRange matches "-" { 44 | listPortRange = strings.split(destinationPortRange, "-") 45 | if int(listPortRange[0]) < int(port) and int(listPortRange[1]) > int(port) { 46 | mapSecurityRules[securityRuleName] = sr 47 | } 48 | } 49 | } 50 | return length(mapSecurityRules) 51 | } 52 | 53 | for group.change.after.security_rule as sr { 54 | if sr.destination_port_range is "*" or sr.destination_port_range is port { 55 | if sr.source_address_prefix in restricted_source_address_prefixes { 56 | mapSecurityRules[sr.name] = sr 57 | } 58 | } else if sr.destination_port_range matches "-" { 59 | listPortRange = strings.split(sr.destination_port_range, "-") 60 | if int(listPortRange[0]) < int(port) and int(listPortRange[1]) > int(port) { 61 | mapSecurityRules[sr.name] = sr 62 | } 63 | } 64 | } 65 | } 66 | return length(mapSecurityRules) 67 | } 68 | 69 | print("CIS 6.1: Ensure that RDP access is restricted from the internet") 70 | 71 | main = rule { 72 | getNetworkSecurityGroupCompliance(allNetworkSecurityGroups, "3389") == 0 73 | } 74 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/test/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/test/azure-cis-6.1-networking-deny-public-rdp-nsg-rules/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/azure-cis-6.2-networking-deny-public-ssh-nsg-rules.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | restricted_source_address_prefixes = ["*", "internet", "any", "0.0.0.0", "/0"] 5 | 6 | allNetworkSecurityGroups = filter tfplan.resource_changes as _, resource_changes { 7 | resource_changes.type is "azurerm_network_security_group" and 8 | resource_changes.mode is "managed" and 9 | (resource_changes.change.actions contains "create" or 10 | resource_changes.change.actions is ["update"]) 11 | } 12 | 13 | allNetworkSecurityRules = filter tfplan.resource_changes as _, resource_changes { 14 | resource_changes.type is "azurerm_network_security_rule" and 15 | resource_changes.mode is "managed" and 16 | (resource_changes.change.actions contains "create" or 17 | resource_changes.change.actions is ["update"]) 18 | } 19 | 20 | getNetworkSecurityGroupCompliance = func(groups, port) { 21 | mapSecurityRules = {} 22 | for groups as _, group { 23 | if keys(group.change.after) not contains "security_rule" { 24 | # Check if standalone Network Security Rule block(s) was defined. 25 | # 26 | # Terraform currently provides both a standalone Network Security 27 | # Rule resource, and allows for Network Security Rules to be 28 | # defined in-line within the Network Security Group resource. 29 | # At this time you cannot use a Network Security Group with 30 | # in-line Network Security Rules in conjunction with any 31 | # Network Security Rule resources. Doing so will cause a 32 | # conflict of rule settings and will overwrite rules. 33 | # 34 | # https://www.terraform.io/docs/providers/azurerm/r/network_security_rule.html 35 | for allNetworkSecurityRules as sr { 36 | destinationPortRange = allNetworkSecurityRules[sr]["change"]["after"]["destination_port_range"] 37 | sourceAddressPrefix = allNetworkSecurityRules[sr]["change"]["after"]["source_address_prefix"] 38 | securityRuleName = allNetworkSecurityRules[sr]["change"]["after"]["name"] 39 | if destinationPortRange is "*" or destinationPortRange is port { 40 | if sourceAddressPrefix in restricted_source_address_prefixes { 41 | mapSecurityRules[securityRuleName] = sr 42 | } 43 | } else if destinationPortRange matches "-" { 44 | listPortRange = strings.split(destinationPortRange, "-") 45 | if int(listPortRange[0]) < int(port) and int(listPortRange[1]) > int(port) { 46 | mapSecurityRules[securityRuleName] = sr 47 | } 48 | } 49 | } 50 | return length(mapSecurityRules) 51 | } 52 | 53 | for group.change.after.security_rule as sr { 54 | if sr.destination_port_range is "*" or sr.destination_port_range is port { 55 | if sr.source_address_prefix in restricted_source_address_prefixes { 56 | mapSecurityRules[sr.name] = sr 57 | } 58 | } else if sr.destination_port_range matches "-" { 59 | listPortRange = strings.split(sr.destination_port_range, "-") 60 | if int(listPortRange[0]) < int(port) and int(listPortRange[1]) > int(port) { 61 | mapSecurityRules[sr.name] = sr 62 | } 63 | } 64 | } 65 | } 66 | return length(mapSecurityRules) 67 | } 68 | 69 | print("CIS 6.2: Ensure that SSH access is restricted from the internet") 70 | 71 | main = rule { 72 | getNetworkSecurityGroupCompliance(allNetworkSecurityGroups, "22") == 0 73 | } 74 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/test/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/test/azure-cis-6.2-networking-deny-public-ssh-nsg-rules/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.3-networking-deny-any-sql-database-ingress/azure-cis-6.3-networking-deny-any-sql-database-ingress.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allSQLFirewallRules = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "azurerm_sql_firewall_rule" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 6.3: Ensure no SQL Databases allow ingress 0.0.0.0/0") 11 | 12 | deny_access_to_azure_services = rule { 13 | all allSQLFirewallRules as _, firewall_rule { 14 | firewall_rule.change.after.start_ip_address is not "0.0.0.0" and 15 | firewall_rule.change.after.end_ip_address is not "0.0.0.0" 16 | } 17 | } 18 | 19 | deny_any_local_start_ip_address = rule { 20 | all allSQLFirewallRules as _, firewall_rule { 21 | firewall_rule.change.after.start_ip_address is not "0.0.0.0" 22 | } 23 | } 24 | 25 | main = rule { 26 | deny_any_local_start_ip_address and 27 | deny_access_to_azure_services 28 | } 29 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.3-networking-deny-any-sql-database-ingress/test/azure-cis-6.3-networking-deny-any-sql-database-ingress/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.3-networking-deny-any-sql-database-ingress/test/azure-cis-6.3-networking-deny-any-sql-database-ingress/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.3-networking-deny-any-sql-database-ingress/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_resource_group.this": { 3 | "address": "azurerm_resource_group.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "location": "australiaeast", 10 | "name": "Sentinel-Foundations-Azure", 11 | }, 12 | "after_unknown": { 13 | "id": true, 14 | "tags": true, 15 | }, 16 | "before": null, 17 | }, 18 | "deposed": "", 19 | "index": null, 20 | "mode": "managed", 21 | "module_address": "", 22 | "name": "this", 23 | "provider_name": "azurerm", 24 | "type": "azurerm_resource_group", 25 | }, 26 | "azurerm_sql_firewall_rule.pass": { 27 | "address": "azurerm_sql_firewall_rule.pass", 28 | "change": { 29 | "actions": [ 30 | "create", 31 | ], 32 | "after": { 33 | "end_ip_address": "10.0.17.62", 34 | "name": "pass", 35 | "resource_group_name": "Sentinel-Foundations-Azure", 36 | "server_name": "mysqlserver", 37 | "start_ip_address": "10.0.17.62", 38 | }, 39 | "after_unknown": { 40 | "id": true, 41 | }, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "pass", 49 | "provider_name": "azurerm", 50 | "type": "azurerm_sql_firewall_rule", 51 | }, 52 | "azurerm_sql_server.this": { 53 | "address": "azurerm_sql_server.this", 54 | "change": { 55 | "actions": [ 56 | "create", 57 | ], 58 | "after": { 59 | "administrator_login": "4dm1n157r470r", 60 | "administrator_login_password": "4-v3ry-53cr37-p455w0rd", 61 | "identity": [], 62 | "location": "australiaeast", 63 | "name": "mysqlserver", 64 | "resource_group_name": "Sentinel-Foundations-Azure", 65 | "version": "12.0", 66 | }, 67 | "after_unknown": { 68 | "fully_qualified_domain_name": true, 69 | "id": true, 70 | "identity": [], 71 | "tags": true, 72 | }, 73 | "before": null, 74 | }, 75 | "deposed": "", 76 | "index": null, 77 | "mode": "managed", 78 | "module_address": "", 79 | "name": "this", 80 | "provider_name": "azurerm", 81 | "type": "azurerm_sql_server", 82 | }, 83 | } 84 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allNetworkWatcherFlowLogs = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "azurerm_network_watcher_flow_log" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 6.4: Ensure that Network Security Group Flow Log retention period is greater than 90 days") 11 | 12 | deny_short_retention_policy = rule { 13 | all allNetworkWatcherFlowLogs as _, log { 14 | all log.change.after.retention_policy as retention_policy { 15 | retention_policy.days >= 90 16 | } 17 | } 18 | } 19 | 20 | main = rule { 21 | deny_short_retention_policy 22 | } 23 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/test/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/test/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_network_watcher_flow_log.this": { 3 | "address": "azurerm_network_watcher_flow_log.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "enabled": true, 10 | "network_watcher_name": "accthisnw", 11 | "resource_group_name": "Sentinel-Foundations-Azure", 12 | "retention_policy": [ 13 | { 14 | "days": 7, 15 | "enabled": true, 16 | }, 17 | ], 18 | "traffic_analytics": [ 19 | { 20 | "enabled": true, 21 | "workspace_region": "australiaeast", 22 | }, 23 | ], 24 | }, 25 | "after_unknown": { 26 | "id": true, 27 | "network_security_group_id": true, 28 | "retention_policy": [ 29 | {}, 30 | ], 31 | "storage_account_id": true, 32 | "traffic_analytics": [ 33 | { 34 | "workspace_id": true, 35 | "workspace_resource_id": true, 36 | }, 37 | ], 38 | "version": true, 39 | }, 40 | "before": null, 41 | }, 42 | "deposed": "", 43 | "index": null, 44 | "mode": "managed", 45 | "module_address": "", 46 | "name": "this", 47 | "provider_name": "azurerm", 48 | "type": "azurerm_network_watcher_flow_log", 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /cis/azure/networking/azure-cis-6.4-networking-enforce-network-watcher-flow-log-retention-period/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_network_watcher_flow_log.this": { 3 | "address": "azurerm_network_watcher_flow_log.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "enabled": true, 10 | "network_watcher_name": "accthisnw", 11 | "resource_group_name": "Sentinel-Foundations-Azure", 12 | "retention_policy": [ 13 | { 14 | "days": 180, 15 | "enabled": true, 16 | }, 17 | ], 18 | "traffic_analytics": [ 19 | { 20 | "enabled": true, 21 | "workspace_region": "australiaeast", 22 | }, 23 | ], 24 | }, 25 | "after_unknown": { 26 | "id": true, 27 | "network_security_group_id": true, 28 | "retention_policy": [ 29 | {}, 30 | ], 31 | "storage_account_id": true, 32 | "traffic_analytics": [ 33 | { 34 | "workspace_id": true, 35 | "workspace_resource_id": true, 36 | }, 37 | ], 38 | "version": true, 39 | }, 40 | "before": null, 41 | }, 42 | "deposed": "", 43 | "index": null, 44 | "mode": "managed", 45 | "module_address": "", 46 | "name": "this", 47 | "provider_name": "azurerm", 48 | "type": "azurerm_network_watcher_flow_log", 49 | }, 50 | } 51 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.1-storage-secure-transfer-required-is-enabled/azure-cis-3.1-storage-secure-transfer-required-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageAccounts = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_storage_account" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.1: Ensure that 'Secure transfer required' is set to Enabled") 11 | 12 | enable_https_traffic_only_is_true = rule { 13 | all allStorageAccounts as _, accounts { 14 | accounts.change.after.enable_https_traffic_only is true 15 | } 16 | } 17 | 18 | main = rule { 19 | enable_https_traffic_only_is_true 20 | } 21 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.1-storage-secure-transfer-required-is-enabled/test/azure-cis-3.1-storage-secure-transfer-required-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.1-storage-secure-transfer-required-is-enabled/test/azure-cis-3.1-storage-secure-transfer-required-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.1-storage-secure-transfer-required-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "account_encryption_source": "Microsoft.Storage", 10 | "account_kind": "Storage", 11 | "account_replication_type": "LRS", 12 | "account_tier": "Standard", 13 | "custom_domain": [], 14 | "enable_blob_encryption": true, 15 | "enable_file_encryption": true, 16 | "enable_https_traffic_only": false, 17 | "is_hns_enabled": false, 18 | "location": "australiaeast", 19 | "name": "656053124", 20 | "queue_properties": [ 21 | { 22 | "cors_rule": [], 23 | "hour_metrics": [ 24 | { 25 | "enabled": true, 26 | "include_apis": true, 27 | "retention_policy_days": 10, 28 | "version": "1.0", 29 | }, 30 | ], 31 | "logging": [ 32 | { 33 | "delete": true, 34 | "read": true, 35 | "retention_policy_days": 10, 36 | "version": "1.0", 37 | "write": true, 38 | }, 39 | ], 40 | "minute_metrics": [ 41 | { 42 | "enabled": true, 43 | "include_apis": true, 44 | "retention_policy_days": 10, 45 | "version": "1.0", 46 | }, 47 | ], 48 | }, 49 | ], 50 | "resource_group_name": "sentinel-foundational-azure", 51 | }, 52 | "after_unknown": {}, 53 | "before": null, 54 | }, 55 | "deposed": "", 56 | "index": null, 57 | "mode": "managed", 58 | "module_address": "", 59 | "name": "this", 60 | "provider_name": "azurerm", 61 | "type": "azurerm_storage_account", 62 | }, 63 | } 64 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.1-storage-secure-transfer-required-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "account_encryption_source": "Microsoft.Storage", 10 | "account_kind": "Storage", 11 | "account_replication_type": "LRS", 12 | "account_tier": "Standard", 13 | "custom_domain": [], 14 | "enable_blob_encryption": true, 15 | "enable_file_encryption": true, 16 | "enable_https_traffic_only": true, 17 | "is_hns_enabled": false, 18 | "location": "australiaeast", 19 | "name": "656053124", 20 | "queue_properties": [ 21 | { 22 | "cors_rule": [], 23 | "hour_metrics": [ 24 | { 25 | "enabled": true, 26 | "include_apis": true, 27 | "retention_policy_days": 10, 28 | "version": "1.0", 29 | }, 30 | ], 31 | "logging": [ 32 | { 33 | "delete": true, 34 | "read": true, 35 | "retention_policy_days": 10, 36 | "version": "1.0", 37 | "write": true, 38 | }, 39 | ], 40 | "minute_metrics": [ 41 | { 42 | "enabled": true, 43 | "include_apis": true, 44 | "retention_policy_days": 10, 45 | "version": "1.0", 46 | }, 47 | ], 48 | }, 49 | ], 50 | "resource_group_name": "sentinel-foundational-azure", 51 | }, 52 | "after_unknown": {}, 53 | "before": null, 54 | }, 55 | "deposed": "", 56 | "index": null, 57 | "mode": "managed", 58 | "module_address": "", 59 | "name": "this", 60 | "provider_name": "azurerm", 61 | "type": "azurerm_storage_account", 62 | }, 63 | } 64 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.3-storage-queue-logging-is-enabled/azure-cis-3.3-storage-queue-logging-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageAccounts = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_storage_account" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.3: Ensure Storage logging is enabled for Queue service for read, write, and delete requests") 11 | 12 | deny_undefined_queue_properties = rule { 13 | all allStorageAccounts as _, accounts { 14 | keys(accounts.change.after) contains "queue_properties" and 15 | length(accounts.change.after.queue_properties else []) != 0 16 | } 17 | } 18 | 19 | deny_undefined_queue_logging = rule when deny_undefined_queue_properties is true { 20 | all allStorageAccounts as _, accounts { 21 | all accounts.change.after.queue_properties as _, queue_properties { 22 | keys(queue_properties) contains "logging" 23 | } 24 | } 25 | } 26 | 27 | queue_properties_logging_is_enabled = rule when deny_undefined_queue_logging is true { 28 | all allStorageAccounts as _, accounts { 29 | all accounts.change.after.queue_properties as _, queue_properties { 30 | all queue_properties.logging as logging { 31 | logging.delete is true and 32 | logging.read is true and 33 | logging.write is true 34 | } 35 | } 36 | } 37 | } 38 | 39 | main = rule { 40 | deny_undefined_queue_properties and 41 | deny_undefined_queue_logging and 42 | queue_properties_logging_is_enabled 43 | } 44 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.3-storage-queue-logging-is-enabled/test/azure-cis-3.3-storage-queue-logging-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.3-storage-queue-logging-is-enabled/test/azure-cis-3.3-storage-queue-logging-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.3-storage-queue-logging-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "account_encryption_source": "Microsoft.Storage", 10 | "account_kind": "Storage", 11 | "account_replication_type": "LRS", 12 | "account_tier": "Standard", 13 | "custom_domain": [], 14 | "enable_blob_encryption": true, 15 | "enable_file_encryption": true, 16 | "enable_https_traffic_only": false, 17 | "is_hns_enabled": false, 18 | "location": "australiaeast", 19 | "name": "656053124", 20 | "queue_properties": [ 21 | { 22 | "cors_rule": [], 23 | "hour_metrics": [ 24 | { 25 | "enabled": true, 26 | "include_apis": true, 27 | "retention_policy_days": 10, 28 | "version": "1.0", 29 | }, 30 | ], 31 | "logging": [ 32 | { 33 | "delete": false, 34 | "read": false, 35 | "retention_policy_days": 10, 36 | "version": "1.0", 37 | "write": false, 38 | }, 39 | ], 40 | "minute_metrics": [ 41 | { 42 | "enabled": true, 43 | "include_apis": true, 44 | "retention_policy_days": 10, 45 | "version": "1.0", 46 | }, 47 | ], 48 | }, 49 | ], 50 | "resource_group_name": "sentinel-foundational-azure", 51 | }, 52 | "after_unknown": {}, 53 | "before": null, 54 | }, 55 | "deposed": "", 56 | "index": null, 57 | "mode": "managed", 58 | "module_address": "", 59 | "name": "this", 60 | "provider_name": "azurerm", 61 | "type": "azurerm_storage_account", 62 | }, 63 | } 64 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.3-storage-queue-logging-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "account_encryption_source": "Microsoft.Storage", 10 | "account_kind": "Storage", 11 | "account_replication_type": "LRS", 12 | "account_tier": "Standard", 13 | "custom_domain": [], 14 | "enable_blob_encryption": true, 15 | "enable_file_encryption": true, 16 | "enable_https_traffic_only": true, 17 | "is_hns_enabled": false, 18 | "location": "australiaeast", 19 | "name": "656053124", 20 | "queue_properties": [ 21 | { 22 | "cors_rule": [], 23 | "hour_metrics": [ 24 | { 25 | "enabled": true, 26 | "include_apis": true, 27 | "retention_policy_days": 10, 28 | "version": "1.0", 29 | }, 30 | ], 31 | "logging": [ 32 | { 33 | "delete": true, 34 | "read": true, 35 | "retention_policy_days": 10, 36 | "version": "1.0", 37 | "write": true, 38 | }, 39 | ], 40 | "minute_metrics": [ 41 | { 42 | "enabled": true, 43 | "include_apis": true, 44 | "retention_policy_days": 10, 45 | "version": "1.0", 46 | }, 47 | ], 48 | }, 49 | ], 50 | "resource_group_name": "sentinel-foundational-azure", 51 | }, 52 | "after_unknown": {}, 53 | "before": null, 54 | }, 55 | "deposed": "", 56 | "index": null, 57 | "mode": "managed", 58 | "module_address": "", 59 | "name": "this", 60 | "provider_name": "azurerm", 61 | "type": "azurerm_storage_account", 62 | }, 63 | } 64 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.6-storage-blob-public-access-level-set-to-private/azure-cis-3.6-storage-blob-public-access-level-set-to-private.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageContainers = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_storage_container" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.6: Ensure that 'Public access level' is set to Private for blob containers") 11 | 12 | container_access_type_is_private = rule { 13 | all allStorageContainers as _, containers { 14 | containers.change.after.container_access_type is "private" 15 | } 16 | } 17 | 18 | main = rule { 19 | container_access_type_is_private 20 | } 21 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.6-storage-blob-public-access-level-set-to-private/test/azure-cis-3.6-storage-blob-public-access-level-set-to-private/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.6-storage-blob-public-access-level-set-to-private/test/azure-cis-3.6-storage-blob-public-access-level-set-to-private/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.6-storage-blob-public-access-level-set-to-private/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_container.this": { 3 | "address": "azurerm_storage_container.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "container_access_type": "blob", 10 | "name": "test", 11 | "storage_account_name": "656053124", 12 | }, 13 | "after_unknown": {}, 14 | "before": null, 15 | }, 16 | "deposed": "", 17 | "index": null, 18 | "mode": "managed", 19 | "module_address": "", 20 | "name": "this", 21 | "provider_name": "azurerm", 22 | "type": "azurerm_storage_container", 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.6-storage-blob-public-access-level-set-to-private/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_container.this": { 3 | "address": "azurerm_storage_container.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "container_access_type": "private", 10 | "name": "test", 11 | "storage_account_name": "656053124", 12 | }, 13 | "after_unknown": {}, 14 | "before": null, 15 | }, 16 | "deposed": "", 17 | "index": null, 18 | "mode": "managed", 19 | "module_address": "", 20 | "name": "this", 21 | "provider_name": "azurerm", 22 | "type": "azurerm_storage_container", 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/azure-cis-3.7-storage-default-network-access-rule-set-to-deny.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageAccounts = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_storage_account" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.7: Ensure default network access rule for Storage Accounts is set to deny") 11 | 12 | deny_undefined_network_rules = rule { 13 | all allStorageAccounts as _, accounts { 14 | keys(accounts.change.after) contains "network_rules" 15 | } 16 | } 17 | 18 | network_rules_default_action_is_deny = rule when deny_undefined_network_rules is true { 19 | all allStorageAccounts as _, accounts { 20 | all accounts.change.after.network_rules as network_rules { 21 | network_rules.default_action is "Deny" 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | deny_undefined_network_rules and 28 | network_rules_default_action_is_deny 29 | } 30 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/test/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/test/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "access_tier": "", 10 | "account_encryption_source": "Microsoft.Storage", 11 | "account_kind": "Storage", 12 | "account_replication_type": "LRS", 13 | "account_tier": "Standard", 14 | "account_type": "Standard_LRS", 15 | "custom_domain": [], 16 | "enable_advanced_threat_protection": false, 17 | "enable_blob_encryption": true, 18 | "enable_file_encryption": true, 19 | "enable_https_traffic_only": true, 20 | "identity": [], 21 | "is_hns_enabled": false, 22 | "location": "australiaeast", 23 | "name": "656053124", 24 | "network_rules": [ 25 | { 26 | "bypass": [ 27 | "None", 28 | ], 29 | "default_action": "Allow", 30 | "ip_rules": [], 31 | "virtual_network_subnet_ids": [], 32 | }, 33 | ], 34 | "queue_properties": [ 35 | { 36 | "cors_rule": [], 37 | "hour_metrics": [ 38 | { 39 | "enabled": true, 40 | "include_apis": true, 41 | "retention_policy_days": 10, 42 | "version": "1.0", 43 | }, 44 | ], 45 | "logging": [ 46 | { 47 | "delete": true, 48 | "read": true, 49 | "retention_policy_days": 10, 50 | "version": "1.0", 51 | "write": true, 52 | }, 53 | ], 54 | "minute_metrics": [ 55 | { 56 | "enabled": true, 57 | "include_apis": true, 58 | "retention_policy_days": 10, 59 | "version": "1.0", 60 | }, 61 | ], 62 | }, 63 | ], 64 | "resource_group_name": "sentinel-foundational-azure", 65 | }, 66 | "after_unknown": {}, 67 | "before": {}, 68 | }, 69 | "deposed": "", 70 | "index": null, 71 | "mode": "managed", 72 | "module_address": "", 73 | "name": "this", 74 | "provider_name": "azurerm", 75 | "type": "azurerm_storage_account", 76 | }, 77 | } 78 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.7-storage-default-network-access-rule-set-to-deny/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "access_tier": "", 10 | "account_encryption_source": "Microsoft.Storage", 11 | "account_kind": "Storage", 12 | "account_replication_type": "LRS", 13 | "account_tier": "Standard", 14 | "account_type": "Standard_LRS", 15 | "custom_domain": [], 16 | "enable_advanced_threat_protection": false, 17 | "enable_blob_encryption": true, 18 | "enable_file_encryption": true, 19 | "enable_https_traffic_only": true, 20 | "identity": [], 21 | "is_hns_enabled": false, 22 | "location": "australiaeast", 23 | "name": "656053124", 24 | "network_rules": [ 25 | { 26 | "bypass": [ 27 | "AzureServices", 28 | ], 29 | "default_action": "Deny", 30 | "ip_rules": [], 31 | "virtual_network_subnet_ids": [], 32 | }, 33 | ], 34 | "queue_properties": [ 35 | { 36 | "cors_rule": [], 37 | "hour_metrics": [ 38 | { 39 | "enabled": true, 40 | "include_apis": true, 41 | "retention_policy_days": 10, 42 | "version": "1.0", 43 | }, 44 | ], 45 | "logging": [ 46 | { 47 | "delete": true, 48 | "read": true, 49 | "retention_policy_days": 10, 50 | "version": "1.0", 51 | "write": true, 52 | }, 53 | ], 54 | "minute_metrics": [ 55 | { 56 | "enabled": true, 57 | "include_apis": true, 58 | "retention_policy_days": 10, 59 | "version": "1.0", 60 | }, 61 | ], 62 | }, 63 | ], 64 | "resource_group_name": "sentinel-foundational-azure", 65 | }, 66 | "after_unknown": {}, 67 | "before": {}, 68 | }, 69 | "deposed": "", 70 | "index": null, 71 | "mode": "managed", 72 | "module_address": "", 73 | "name": "this", 74 | "provider_name": "azurerm", 75 | "type": "azurerm_storage_account", 76 | }, 77 | } 78 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageAccounts = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.mode is "managed" and 5 | resource_changes.type is "azurerm_storage_account" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.8: Ensure 'Trusted Microsoft Services' is enabled for Storage Account access") 11 | 12 | deny_undefined_network_rules = rule { 13 | all allStorageAccounts as _, accounts { 14 | keys(accounts.change.after) contains "network_rules" 15 | } 16 | } 17 | 18 | deny_undefined_network_rules_bypass = rule when deny_undefined_network_rules is true { 19 | all allStorageAccounts as _, accounts { 20 | all accounts.change.after.network_rules as network_rules { 21 | keys(network_rules) contains "bypass" 22 | } 23 | } 24 | } 25 | 26 | network_rules_default_action_is_deny = rule when deny_undefined_network_rules_bypass is true { 27 | all allStorageAccounts as _, accounts { 28 | all accounts.change.after.network_rules as network_rules { 29 | any network_rules.bypass as bypass { 30 | bypass is "AzureServices" 31 | } 32 | } 33 | } 34 | } 35 | 36 | main = rule { 37 | deny_undefined_network_rules and 38 | deny_undefined_network_rules_bypass and 39 | network_rules_default_action_is_deny 40 | } 41 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/test/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/test/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "access_tier": "", 10 | "account_encryption_source": "Microsoft.Storage", 11 | "account_kind": "Storage", 12 | "account_replication_type": "LRS", 13 | "account_tier": "Standard", 14 | "account_type": "Standard_LRS", 15 | "custom_domain": [], 16 | "enable_advanced_threat_protection": false, 17 | "enable_blob_encryption": true, 18 | "enable_file_encryption": true, 19 | "enable_https_traffic_only": true, 20 | "identity": [], 21 | "is_hns_enabled": false, 22 | "location": "australiaeast", 23 | "name": "656053124", 24 | "network_rules": [ 25 | { 26 | "bypass": [ 27 | "None", 28 | ], 29 | "default_action": "Allow", 30 | "ip_rules": [], 31 | "virtual_network_subnet_ids": [], 32 | }, 33 | ], 34 | "queue_properties": [ 35 | { 36 | "cors_rule": [], 37 | "hour_metrics": [ 38 | { 39 | "enabled": true, 40 | "include_apis": true, 41 | "retention_policy_days": 10, 42 | "version": "1.0", 43 | }, 44 | ], 45 | "logging": [ 46 | { 47 | "delete": true, 48 | "read": true, 49 | "retention_policy_days": 10, 50 | "version": "1.0", 51 | "write": true, 52 | }, 53 | ], 54 | "minute_metrics": [ 55 | { 56 | "enabled": true, 57 | "include_apis": true, 58 | "retention_policy_days": 10, 59 | "version": "1.0", 60 | }, 61 | ], 62 | }, 63 | ], 64 | "resource_group_name": "sentinel-foundational-azure", 65 | "tags": {}, 66 | }, 67 | "after_unknown": {}, 68 | "before": {}, 69 | }, 70 | "deposed": "", 71 | "index": null, 72 | "mode": "managed", 73 | "module_address": "", 74 | "name": "this", 75 | "provider_name": "azurerm", 76 | "type": "azurerm_storage_account", 77 | }, 78 | } 79 | -------------------------------------------------------------------------------- /cis/azure/storage/azure-cis-3.8-storage-trusted-microsoft-services-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "azurerm_storage_account.this": { 3 | "address": "azurerm_storage_account.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "access_tier": "", 10 | "account_encryption_source": "Microsoft.Storage", 11 | "account_kind": "Storage", 12 | "account_replication_type": "LRS", 13 | "account_tier": "Standard", 14 | "account_type": "Standard_LRS", 15 | "custom_domain": [], 16 | "enable_advanced_threat_protection": false, 17 | "enable_blob_encryption": true, 18 | "enable_file_encryption": true, 19 | "enable_https_traffic_only": true, 20 | "identity": [], 21 | "is_hns_enabled": false, 22 | "location": "australiaeast", 23 | "name": "656053124", 24 | "network_rules": [ 25 | { 26 | "bypass": [ 27 | "AzureServices", 28 | ], 29 | "default_action": "Deny", 30 | "ip_rules": [], 31 | "virtual_network_subnet_ids": [], 32 | }, 33 | ], 34 | "queue_properties": [ 35 | { 36 | "cors_rule": [], 37 | "hour_metrics": [ 38 | { 39 | "enabled": true, 40 | "include_apis": true, 41 | "retention_policy_days": 10, 42 | "version": "1.0", 43 | }, 44 | ], 45 | "logging": [ 46 | { 47 | "delete": true, 48 | "read": true, 49 | "retention_policy_days": 10, 50 | "version": "1.0", 51 | "write": true, 52 | }, 53 | ], 54 | "minute_metrics": [ 55 | { 56 | "enabled": true, 57 | "include_apis": true, 58 | "retention_policy_days": 10, 59 | "version": "1.0", 60 | }, 61 | ], 62 | }, 63 | ], 64 | "resource_group_name": "sentinel-foundational-azure", 65 | "tags": {}, 66 | }, 67 | "after_unknown": {}, 68 | "before": {}, 69 | }, 70 | "deposed": "", 71 | "index": null, 72 | "mode": "managed", 73 | "module_address": "", 74 | "name": "this", 75 | "provider_name": "azurerm", 76 | "type": "azurerm_storage_account", 77 | }, 78 | } 79 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | allComputeInstances = filter tfplan.resource_changes as _, resource_changes { 5 | resource_changes.type is "google_compute_instance" and 6 | resource_changes.mode is "managed" and 7 | (resource_changes.change.actions contains "create" or 8 | resource_changes.change.actions is ["update"]) 9 | } 10 | 11 | allComputeInstanceTemplates = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.type is "google_compute_instance_template" and 13 | resource_changes.mode is "managed" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) 16 | } 17 | 18 | print("CIS 4.2: Ensure 'Block Project-wide SSH keys' are enabled for VM instances") 19 | 20 | deny_undefined_compute_instance_metadata = rule { 21 | all allComputeInstances as _, instances { 22 | instances.change.after.metadata is not null 23 | } 24 | } 25 | 26 | deny_undefined_compute_instance_block_project_ssh_keys = rule when deny_undefined_compute_instance_metadata is true { 27 | all allComputeInstances as _, instances { 28 | keys(instances.change.after.metadata) contains "block-project-ssh-keys" 29 | } 30 | } 31 | 32 | block_project_ssh_keys_is_enabled_in_compute_instance_metadata = rule when deny_undefined_compute_instance_block_project_ssh_keys is true { 33 | all allComputeInstances as _, instances { 34 | strings.to_lower(instances.change.after.metadata["block-project-ssh-keys"]) is "true" 35 | } 36 | } 37 | 38 | deny_undefined_compute_instance_template_metadata = rule { 39 | all allComputeInstanceTemplates as _, templates { 40 | keys(templates.change.after) contains "metadata" 41 | } 42 | } 43 | 44 | deny_undefined_compute_instance_template_block_project_ssh_keys = rule when deny_undefined_compute_instance_template_metadata is true { 45 | all allComputeInstanceTemplates as _, templates { 46 | keys(templates.change.after.metadata) contains "block-project-ssh-keys" 47 | } 48 | } 49 | 50 | block_project_ssh_keys_is_enabled_in_compute_instance_template_metadata = rule when deny_undefined_compute_instance_template_block_project_ssh_keys is true { 51 | all allComputeInstanceTemplates as _, templates { 52 | strings.to_lower(templates.change.after.metadata["block-project-ssh-keys"]) is "true" 53 | } 54 | } 55 | 56 | main = rule { 57 | deny_undefined_compute_instance_metadata and 58 | deny_undefined_compute_instance_block_project_ssh_keys and 59 | deny_undefined_compute_instance_template_metadata and 60 | deny_undefined_compute_instance_template_block_project_ssh_keys and 61 | block_project_ssh_keys_is_enabled_in_compute_instance_metadata and 62 | block_project_ssh_keys_is_enabled_in_compute_instance_template_metadata 63 | } 64 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances/test/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances/test/gcp-cis-4.2-compute-block-project-wide-ssh-keys-enabled-for-vm-instances/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | allComputeInstances = filter tfplan.resource_changes as _, resource_changes { 5 | resource_changes.type is "google_compute_instance" and 6 | resource_changes.mode is "managed" and 7 | (resource_changes.change.actions contains "create" or 8 | resource_changes.change.actions is ["update"]) 9 | } 10 | 11 | allComputeInstanceTemplates = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.type is "google_compute_instance_template" and 13 | resource_changes.mode is "managed" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) 16 | } 17 | 18 | print("CIS 4.3: Ensure oslogin is enabled for a project") 19 | 20 | deny_undefined_compute_instance_metadata = rule { 21 | all allComputeInstances as _, instances { 22 | instances.change.after.metadata is not null 23 | } 24 | } 25 | 26 | deny_undefined_compute_instance_enable_oslogin = rule when deny_undefined_compute_instance_metadata is true { 27 | all allComputeInstances as _, instances { 28 | keys(instances.change.after.metadata) contains "enable-oslogin" 29 | } 30 | } 31 | 32 | enable_oslogin_is_enabled_in_compute_instance_metadata = rule when deny_undefined_compute_instance_metadata is true { 33 | all allComputeInstances as _, instance { 34 | strings.to_lower(instance.change.after.metadata["enable-oslogin"]) is "true" 35 | } 36 | } 37 | 38 | deny_undefined_compute_instance_template_metadata = rule { 39 | all allComputeInstanceTemplates as _, templates { 40 | keys(templates.change.after) contains "metadata" 41 | } 42 | } 43 | 44 | deny_undefined_compute_instance_template_enable_oslogin = rule when deny_undefined_compute_instance_template_metadata is true { 45 | all allComputeInstanceTemplates as _, templates { 46 | keys(templates.change.after.metadata) contains "enable-oslogin" 47 | } 48 | } 49 | 50 | enable_oslogin_is_enabled_in_compute_instance_template_metadata = rule when deny_undefined_compute_instance_template_enable_oslogin is true { 51 | all allComputeInstanceTemplates as _, template { 52 | strings.to_lower(template.change.after.metadata["enable-oslogin"]) is "true" 53 | } 54 | } 55 | 56 | main = rule { 57 | deny_undefined_compute_instance_metadata and 58 | deny_undefined_compute_instance_enable_oslogin and 59 | deny_undefined_compute_instance_template_metadata and 60 | deny_undefined_compute_instance_template_enable_oslogin and 61 | enable_oslogin_is_enabled_in_compute_instance_metadata and 62 | enable_oslogin_is_enabled_in_compute_instance_template_metadata 63 | } 64 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project/test/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project/test/gcp-cis-4.3-compute-ensure-oslogin-is-enabled-for-a-project/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | allComputeInstances = filter tfplan.resource_changes as _, resource_changes { 5 | resource_changes.type is "google_compute_instance" and 6 | resource_changes.mode is "managed" and 7 | (resource_changes.change.actions contains "create" or 8 | resource_changes.change.actions is ["update"]) 9 | } 10 | 11 | allComputeInstanceTemplates = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.type is "google_compute_instance_template" and 13 | resource_changes.mode is "managed" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) 16 | } 17 | 18 | print("CIS 4.4: Ensure 'Enable connecting to serial ports' is not enabled for VM Instance") 19 | 20 | deny_undefined_compute_instance_metadata = rule { 21 | all allComputeInstances as _, instances { 22 | instances.change.after.metadata is not null 23 | } 24 | } 25 | 26 | deny_undefined_compute_instance_serial_port_enable = rule when deny_undefined_compute_instance_metadata is true { 27 | all allComputeInstances as _, instances { 28 | keys(instances.change.after.metadata) contains "serial-port-enable" 29 | } 30 | } 31 | 32 | serial_port_enable_is_disabled_in_compute_instance_metadata = rule when deny_undefined_compute_instance_serial_port_enable is true { 33 | all allComputeInstances as _, instance { 34 | strings.to_lower(instance.change.after.metadata["serial-port-enable"]) is "false" 35 | } 36 | } 37 | 38 | deny_undefined_compute_instance_template_metadata = rule { 39 | all allComputeInstanceTemplates as _, templates { 40 | keys(templates.change.after) contains "metadata" 41 | } 42 | } 43 | 44 | deny_undefined_compute_instance_template_serial_port_enable = rule when deny_undefined_compute_instance_template_metadata is true { 45 | all allComputeInstanceTemplates as _, templates { 46 | keys(templates.change.after.metadata) contains "serial-port-enable" 47 | } 48 | } 49 | 50 | serial_port_enable_is_disabled_in_compute_instance_template_metadata = rule when deny_undefined_compute_instance_template_serial_port_enable is true { 51 | all allComputeInstanceTemplates as _, template { 52 | strings.to_lower(template.change.after.metadata["serial-port-enable"]) is "false" 53 | } 54 | } 55 | 56 | main = rule { 57 | deny_undefined_compute_instance_metadata and 58 | deny_undefined_compute_instance_serial_port_enable and 59 | deny_undefined_compute_instance_template_metadata and 60 | deny_undefined_compute_instance_template_serial_port_enable and 61 | serial_port_enable_is_disabled_in_compute_instance_metadata and 62 | serial_port_enable_is_disabled_in_compute_instance_template_metadata 63 | } 64 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance/test/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance/test/gcp-cis-4.4-compute-enable-connecting-to-serial-ports-is-not-enabled-for-vm-instance/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allComputeInstances = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_compute_instance" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | allComputeInstanceTemplates = filter tfplan.resource_changes as _, resource_changes { 11 | resource_changes.type is "google_compute_instance_template" and 12 | resource_changes.mode is "managed" and 13 | (resource_changes.change.actions contains "create" or 14 | resource_changes.change.actions is ["update"]) 15 | } 16 | 17 | print("CIS 4.5: Ensure that IP forwarding is not enabled on Instances") 18 | 19 | can_ip_forward_is_disabled_in_compute_instance = rule { 20 | all allComputeInstances as _, instance { 21 | instance.change.after.can_ip_forward is false 22 | } 23 | } 24 | 25 | can_ip_forward_is_disabled_in_compute_instance_template = rule { 26 | all allComputeInstanceTemplates as _, template { 27 | template.change.after.can_ip_forward is false 28 | } 29 | } 30 | 31 | main = rule { 32 | can_ip_forward_is_disabled_in_compute_instance and 33 | can_ip_forward_is_disabled_in_compute_instance_template 34 | } 35 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances/test/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances/test/gcp-cis-4.5-compute-ensure-that-ip-forwarding-is-not-enabled-on-instances/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "types" 3 | 4 | allComputeDisks = filter tfplan.resource_changes as _, resource_changes { 5 | resource_changes.type is "google_compute_disk" and 6 | resource_changes.mode is "managed" and 7 | (resource_changes.change.actions contains "create" or 8 | resource_changes.change.actions is ["update"]) 9 | } 10 | 11 | allComputeInstances = filter tfplan.resource_changes as _, resource_changes { 12 | resource_changes.type is "google_compute_instance" and 13 | resource_changes.mode is "managed" and 14 | (resource_changes.change.actions contains "create" or 15 | resource_changes.change.actions is ["update"]) 16 | } 17 | 18 | allComputeInstanceTemplates = filter tfplan.resource_changes as _, resource_changes { 19 | resource_changes.type is "google_compute_instance_template" and 20 | resource_changes.mode is "managed" and 21 | (resource_changes.change.actions contains "create" or 22 | resource_changes.change.actions is ["update"]) 23 | } 24 | 25 | getDiskEncryptionStatus = func(property) { 26 | case { 27 | when types.type_of(property.disk_encryption_key_raw) is "null": 28 | if keys(property) contains "kms_key_self_link" { 29 | return length(property.kms_key_self_link) != 0 30 | } else { 31 | return false 32 | } 33 | when types.type_of(property.disk_encryption_key_raw) is "string": 34 | return length(property.disk_encryption_key_raw) != 0 35 | when types.type_of(property.disk_encryption_key) is "list": 36 | return length(property.disk_encryption_key) != 0 37 | else: 38 | return false 39 | } 40 | } 41 | 42 | print("CIS 4.6: Ensure VM disks for critical VMs are encrypted with Customer-Supplied Encryption Keys (CSEK)") 43 | 44 | disk_encryption_is_enabled_in_compute_disks = rule { 45 | all allComputeDisks as _, disk { 46 | length(disk.change.after.disk_encryption_key) != 0 47 | } 48 | } 49 | 50 | disk_encryption_is_enabled_in_compute_instance_boot_disk = rule { 51 | all allComputeInstances as _, instance { 52 | all instance.change.after.boot_disk as _, boot_disk { 53 | getDiskEncryptionStatus(boot_disk) 54 | } 55 | } 56 | } 57 | 58 | disk_encryption_is_enabled_in_compute_instance_attached_disk = rule { 59 | all allComputeInstances as _, instance { 60 | all instance.change.after.attached_disk as _, attached_disk { 61 | getDiskEncryptionStatus(attached_disk) 62 | } 63 | } 64 | } 65 | 66 | disk_encryption_is_enabled_in_compute_instance_template_disk = rule { 67 | all allComputeInstanceTemplates as _, template { 68 | all template.change.after.disk as _, disk { 69 | getDiskEncryptionStatus(disk) 70 | } 71 | } 72 | } 73 | 74 | main = rule { 75 | disk_encryption_is_enabled_in_compute_disks and 76 | disk_encryption_is_enabled_in_compute_instance_boot_disk and 77 | disk_encryption_is_enabled_in_compute_instance_attached_disk and 78 | disk_encryption_is_enabled_in_compute_instance_template_disk 79 | } 80 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys/test/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/compute/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys/test/gcp-cis-4.6-compute-ensure-vm-disks-for-critical-vms-are-encrypted-with-customer-supplied-encryption-keys/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/databases/README.md: -------------------------------------------------------------------------------- 1 | # CIS Google Cloud Computing Foundational Sentinel policies 2 | 3 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Google Cloud Computing Platform Foundations Benchmark v.1.0.0](https://www.cisecurity.org/benchmark/google_cloud_computing_platform/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 4 | 5 | ## CIS 6.1: Ensure that Cloud SQL database instance requires all incoming connections to use SSL 6 | 7 | ### Description 8 | For security, it is recommended to always use SSL encryption when connecting to your instance. This recommendation is applicable for Postgresql, MySql generation 1 and MySql generation 2 Instances. 9 | 10 | ### Configuration 11 | 12 | ```hcl 13 | policy "gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl" { 14 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/gcp/databases/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl.sentinel" 15 | enforcement_level = "advisory" 16 | } 17 | ``` 18 | 19 | ## CIS 6.2: Ensure that Cloud SQL database Instances are not open to the world 20 | 21 | 22 | ### Description 23 | To minimize attack surface on a Database server Instance, only trusted/known and required IP(s) should be white-listed to connect to it. 24 | 25 | ### Configuration 26 | 27 | ```hcl 28 | policy "gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world" { 29 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/gcp/databases/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world.sentinel" 30 | enforcement_level = "advisory" 31 | } 32 | ``` -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allSQLDatabaseResources = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_sql_database_instance" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 6.1: Ensure that Cloud SQL database instance requires all incoming connections to use SSL") 11 | 12 | deny_undefined_ip_configuration = rule { 13 | all filter allSQLDatabaseResources as _, resources { 14 | resources.change.after.database_version not contains "SQLSERVER" 15 | } as _, resources { 16 | all resources.change.after.settings as _, settings { 17 | keys(settings) contains "ip_configuration" and 18 | length(settings.ip_configuration else []) != 0 19 | } 20 | } 21 | } 22 | 23 | ip_configuration_require_ssl_is_true = rule when deny_undefined_ip_configuration is true { 24 | all filter allSQLDatabaseResources as _, resources { 25 | resources.change.after.database_version not contains "SQLSERVER" 26 | } as _, instances { 27 | all instances.change.after.settings as _, setting { 28 | all setting.ip_configuration as _, config { 29 | config.require_ssl is true 30 | } 31 | } 32 | } 33 | } 34 | 35 | main = rule { 36 | deny_undefined_ip_configuration and 37 | ip_configuration_require_ssl_is_true 38 | } 39 | -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/test/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/test/gcp-cis-6.1-databases-cloud-sql-databases-instance-requires-all-incoming-connections-to-use-ssl/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allSQLDatabaseResources = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_sql_database_instance" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 6.2: Ensure that Cloud SQL database Instances are not open to the world") 11 | 12 | deny_undefined_ip_configuration = rule { 13 | all allSQLDatabaseResources as _, resources { 14 | all resources.change.after.settings as _, settings { 15 | keys(settings) contains "ip_configuration" 16 | } 17 | } 18 | } 19 | 20 | deny_undefined_ip_configuration_authorized_networks = rule when deny_undefined_ip_configuration is true { 21 | all allSQLDatabaseResources as _, resources { 22 | all resources.change.after.settings as _, settings { 23 | all settings.ip_configuration as _, ip_configuration { 24 | keys(ip_configuration) contains "authorized_networks" 25 | } 26 | } 27 | } 28 | } 29 | 30 | ip_configuration_authorized_networks = rule when deny_undefined_ip_configuration_authorized_networks is true { 31 | all allSQLDatabaseResources as _, resources { 32 | all resources.change.after.settings as _, settings { 33 | all settings.ip_configuration as _, ip_configuration { 34 | all ip_configuration.authorized_networks as _, authorized_networks { 35 | authorized_networks.value is not "0.0.0.0" and 36 | authorized_networks.value not contains "/0" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | 43 | main = rule { 44 | deny_undefined_ip_configuration_authorized_networks and 45 | ip_configuration_authorized_networks 46 | } 47 | -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/test/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/databases/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/test/gcp-cis-6.2-databases-cloud-sql-databases-instances-are-not-open-to-the-world/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | supportedLoggingServices = [ 4 | "logging.googleapis.com/kubernetes", 5 | "logging.googleapis.com", 6 | ] 7 | 8 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 9 | resource_changes.type is "google_container_cluster" and 10 | resource_changes.mode is "managed" and 11 | (resource_changes.change.actions contains "create" or 12 | resource_changes.change.actions is ["update"]) 13 | } 14 | 15 | print("CIS 7.1: Ensure Stackdriver Logging is set to Enabled on Kubernetes Engine Clusters") 16 | 17 | logging_service_is_enabled = rule { 18 | all allContainerClusters as _, cluster { 19 | cluster.change.after.logging_service in supportedLoggingServices 20 | } 21 | } 22 | 23 | main = rule { 24 | logging_service_is_enabled 25 | } 26 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.1-kubernetes-ensure-stackdriver-logging-is-set-to-enabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.10: Ensure Basic Authentication is disabled on Kubernetes Engine Clusters") 11 | 12 | master_auth_is_defined = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "master_auth" 15 | } 16 | } 17 | 18 | basic_authentication_is_disabled = rule when master_auth_is_defined is true { 19 | all allContainerClusters as _, cluster { 20 | all cluster.change.after.master_auth as _, master_auth { 21 | keys(master_auth) contains "username" and 22 | length(master_auth.username) == 0 and 23 | keys(master_auth) contains "password" and 24 | length(master_auth.password) == 0 25 | } 26 | } 27 | } 28 | 29 | main = rule { 30 | master_auth_is_defined and 31 | basic_authentication_is_disabled 32 | } 33 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters/test/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters/test/gcp-cis-7.10-kubernetes-ensure-basic-authentication-is-disabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.11: Ensure Network policy is enabled on Kubernetes Engine Clusters") 11 | 12 | deny_undefined_network_policy = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "network_policy" 15 | } 16 | } 17 | 18 | network_policy_is_enabled = rule when deny_undefined_network_policy is true { 19 | all allContainerClusters as _, cluster { 20 | all cluster.change.after.network_policy as _, network_policy { 21 | network_policy.enabled is true 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | deny_undefined_network_policy and 28 | network_policy_is_enabled 29 | } 30 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.11-kubernetes-ensure-network-policy-is-enabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.12: Ensure Kubernetes Cluster is created with Client Certificate enabled") 11 | 12 | deny_undefined_master_auth = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "master_auth" 15 | } 16 | } 17 | 18 | deny_undefined_client_certificate_config = rule when deny_undefined_master_auth is true { 19 | all allContainerClusters as _, cluster { 20 | all cluster.change.after.master_auth as _, master_auth { 21 | keys(master_auth) contains "client_certificate_config" 22 | } 23 | } 24 | } 25 | 26 | client_certificate_is_enabled = rule when deny_undefined_client_certificate_config is true { 27 | all allContainerClusters as _, cluster { 28 | all cluster.change.after.master_auth as _, master_auth { 29 | all master_auth.client_certificate_config as _, client_certificate_config { 30 | client_certificate_config.issue_client_certificate is true 31 | } 32 | } 33 | } 34 | } 35 | 36 | main = rule { 37 | deny_undefined_master_auth and 38 | deny_undefined_client_certificate_config and 39 | client_certificate_is_enabled 40 | } 41 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled/test/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled/test/gcp-cis-7.12-kubernetes-ensure-kubernetes-cluster-is-created-with-client-certificate-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.13: Ensure Kubernetes Cluster is created with Alias IP ranges enabled") 11 | 12 | cluster_alias_ip_ranges_is_enabled = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "ip_allocation_policy" and 15 | length(cluster.change.after.ip_allocation_policy) > 0 16 | } 17 | } 18 | 19 | main = rule { 20 | cluster_alias_ip_ranges_is_enabled 21 | } 22 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled/test/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled/test/gcp-cis-7.13-kubernetes-ensure-kubernetes-cluster-is-created-with-alias-ip-ranges-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.14: Ensure PodSecurityPolicy controller is enabled on the Kubernetes Engine Clusters") 11 | 12 | deny_undefined_pod_security_policy_config = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "pod_security_policy_config" 15 | } 16 | } 17 | 18 | pod_security_policy_controller_is_enabled = rule when deny_undefined_pod_security_policy_config is true { 19 | all allContainerClusters as _, cluster { 20 | all cluster.change.after.pod_security_policy_config as _, pod_security_policy_config { 21 | pod_security_policy_config.enabled is true 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | deny_undefined_pod_security_policy_config and 28 | pod_security_policy_controller_is_enabled 29 | } 30 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters/test/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters/test/gcp-cis-7.14-kubernetes-ensure-podsecuritypolicy-controller-is-enabled-on-the-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.15: Ensure Kubernetes Cluster is created with Private cluster enabled") 11 | 12 | private_cluster_config_is_enabled = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "private_cluster_config" and 15 | length(cluster.change.after.private_cluster_config) > 0 16 | } 17 | } 18 | 19 | main = rule { 20 | private_cluster_config_is_enabled 21 | } 22 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled/test/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled/test/gcp-cis-7.15-kubernetes-ensure-kubernetes-cluster-is-created-with-private-cluster-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 11 | resource_changes.type is "google_container_node_pool" and 12 | resource_changes.mode is "managed" and 13 | (resource_changes.change.actions contains "create" or 14 | resource_changes.change.actions is ["update"]) 15 | } 16 | 17 | print("CIS 7.17: Ensure default Service account is not used for Project access in Kubernetes Clusters") 18 | 19 | deny_undefined_cluster_node_config = rule { 20 | all allContainerClusters as _, cluster { 21 | keys(cluster.change.after) contains "node_config" 22 | } 23 | } 24 | 25 | cluster_service_account_is_enabled = rule when deny_undefined_cluster_node_config is true { 26 | all allContainerClusters as _, cluster { 27 | all cluster.change.after.node_config as _, node_config { 28 | keys(node_config) contains "service_account" 29 | } 30 | } 31 | } 32 | 33 | deny_undefined_pool_node_config = rule { 34 | all allNodePools as _, pool { 35 | keys(pool.change.after) contains "node_config" 36 | } 37 | } 38 | 39 | pool_service_account_is_enabled = rule when deny_undefined_pool_node_config is true { 40 | all allNodePools as _, pool { 41 | all pool.change.after.node_config as _, node_config { 42 | keys(node_config) contains "service_account" 43 | } 44 | } 45 | } 46 | 47 | main = rule { 48 | deny_undefined_cluster_node_config and 49 | deny_undefined_pool_node_config and 50 | cluster_service_account_is_enabled and 51 | pool_service_account_is_enabled 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters/test/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters/test/gcp-cis-7.17-kubernetes-ensure-default-service-account-is-not-used-for-project-access-in-kubernetes-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | supportedAccessScopes = [ 4 | "https://www.googleapis.com/auth/logging.write", 5 | "https://www.googleapis.com/auth/monitoring", 6 | "https://www.googleapis.com/auth/devstorage.read_only", 7 | "storage-ro", 8 | "logging-write", 9 | "monitoring", 10 | ] 11 | 12 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 13 | resource_changes.type is "google_container_cluster" and 14 | resource_changes.mode is "managed" and 15 | (resource_changes.change.actions contains "create" or 16 | resource_changes.change.actions is ["update"]) 17 | } 18 | 19 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 20 | resource_changes.type is "google_container_node_pool" and 21 | resource_changes.mode is "managed" and 22 | (resource_changes.change.actions contains "create" or 23 | resource_changes.change.actions is ["update"]) 24 | } 25 | 26 | print("CIS 7.18: Ensure Kubernetes Clusters created with limited service account Access scopes for Project access") 27 | 28 | deny_undefined_cluster_node_config = rule { 29 | all allContainerClusters as _, cluster { 30 | keys(cluster.change.after) contains "node_config" 31 | } 32 | } 33 | 34 | cluster_supported_access_scope_is_configured = rule when deny_undefined_cluster_node_config is true { 35 | all allContainerClusters as _, cluster { 36 | all cluster.change.after.node_config as _, node_config { 37 | all node_config.oauth_scopes as oauth_scopes { 38 | oauth_scopes in supportedAccessScopes 39 | } 40 | } 41 | } 42 | } 43 | 44 | deny_undefined_pool_node_config = rule { 45 | all allNodePools as _, pool { 46 | keys(pool.change.after) contains "node_config" 47 | } 48 | } 49 | 50 | pool_supported_access_scope_is_configured = rule when deny_undefined_pool_node_config is true { 51 | all allNodePools as _, pool { 52 | all pool.change.after.node_config as _, node_config { 53 | all node_config.oauth_scopes as oauth_scopes { 54 | oauth_scopes in supportedAccessScopes 55 | } 56 | } 57 | } 58 | } 59 | 60 | main = rule { 61 | deny_undefined_cluster_node_config and 62 | deny_undefined_pool_node_config and 63 | cluster_supported_access_scope_is_configured and 64 | pool_supported_access_scope_is_configured 65 | } 66 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access/test/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access/test/gcp-cis-7.18-kubernetes-ensure-kubernetes-clusters-created-with-limited-service-account-access-scopes-for-project-access/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | supportedMonitoringServices = [ 4 | "monitoring.googleapis.com/kubernetes", 5 | "monitoring.googleapis.com", 6 | ] 7 | 8 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 9 | resource_changes.type is "google_container_cluster" and 10 | resource_changes.mode is "managed" and 11 | (resource_changes.change.actions contains "create" or 12 | resource_changes.change.actions is ["update"]) 13 | } 14 | 15 | print("CIS 7.2: Ensure Stackdriver Monitoring is set to Enabled on Kubernetes Engine Clusters") 16 | 17 | monitoring_service_is_enabled = rule { 18 | all allContainerClusters as _, cluster { 19 | cluster.change.after.monitoring_service in supportedMonitoringServices 20 | } 21 | } 22 | 23 | main = rule { 24 | monitoring_service_is_enabled 25 | } 26 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.2-kubernetes-ensure-stackdriver-monitoring-is-set-to-enabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.3: Ensure Legacy Authorization is set to Disabled on Kubernetes Engine Clusters") 11 | 12 | enable_legacy_abac_is_disabled = rule { 13 | all allContainerClusters as _, cluster { 14 | cluster.change.after.enable_legacy_abac is false 15 | } 16 | } 17 | 18 | main = rule { 19 | enable_legacy_abac_is_disabled 20 | } 21 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters/test/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters/test/gcp-cis-7.3-kubernetes-ensure-legacy-authorization-is-set-to-disabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.4: Ensure Master authorized networks is set to Enabled on Kubernetes Engine Clusters") 11 | 12 | deny_undefined_master_authorized_networks_config = rule { 13 | all allContainerClusters as _, cluster { 14 | keys(cluster.change.after) contains "master_authorized_networks_config" 15 | } 16 | } 17 | 18 | master_authorized_networks_config_is_configured = rule when deny_undefined_master_authorized_networks_config is true { 19 | all allContainerClusters as _, cluster { 20 | length(cluster.change.after.master_authorized_networks_config) > 0 21 | } 22 | } 23 | 24 | main = rule { 25 | deny_undefined_master_authorized_networks_config and 26 | master_authorized_networks_config_is_configured 27 | } 28 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters/test/gcp-cis-7.4-kubernetes-ensure-master-authorized-networks-is-set-to-enabled-on-kubernetes-engine-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_cluster" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 11 | resource_changes.type is "google_container_node_pool" and 12 | resource_changes.mode is "managed" and 13 | (resource_changes.change.actions contains "create" or 14 | resource_changes.change.actions is ["update"]) 15 | } 16 | 17 | print("CIS 7.5: Ensure Kubernetes Clusters are configured with Labels") 18 | 19 | deny_undefined_cluster_node_config = rule { 20 | all allContainerClusters as _, cluster { 21 | keys(cluster.change.after) contains "node_config" 22 | } 23 | } 24 | 25 | cluster_node_config_is_labelled = rule when deny_undefined_cluster_node_config is true { 26 | all allContainerClusters as _, cluster { 27 | all cluster.change.after.node_config as _, node_config { 28 | keys(node_config) contains "labels" 29 | } 30 | } 31 | } 32 | 33 | deny_undefined_pool_node_config = rule { 34 | all allNodePools as _, pool { 35 | keys(pool.change.after) contains "node_config" 36 | } 37 | } 38 | 39 | pool_node_config_is_labelled = rule when deny_undefined_pool_node_config is true { 40 | all allNodePools as _, pool { 41 | all pool.change.after.node_config as _, node_config { 42 | keys(node_config) contains "labels" 43 | } 44 | } 45 | } 46 | 47 | main = rule { 48 | deny_undefined_cluster_node_config and 49 | deny_undefined_pool_node_config and 50 | cluster_node_config_is_labelled and 51 | pool_node_config_is_labelled 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels/test/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels/test/gcp-cis-7.5-kubernetes-ensure-kubernetes-clusters-are-configured-with-labels/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_node_pool" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.7: Ensure `Automatic node repair` is enabled for Kubernetes Clusters") 11 | 12 | deny_undefined_management = rule { 13 | all allNodePools as _, pool { 14 | keys(pool.change.after) contains "management" 15 | } 16 | } 17 | 18 | node_auto_repair_is_enabled = rule when deny_undefined_management is true { 19 | all allNodePools as _, pool { 20 | all pool.change.after.management as _, management { 21 | management.auto_repair is true 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | deny_undefined_management and 28 | node_auto_repair_is_enabled 29 | } 30 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters/test/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters/test/gcp-cis-7.7-kubernetes-ensure-automatic-node-repair-is-enabled-for-kubernetes-clusters/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_container_node_pool" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 7.8: Ensure Automatic node upgrades is enabled on Kubernetes Engine Clusters nodes") 11 | 12 | deny_undefined_management = rule { 13 | all allNodePools as _, pool { 14 | keys(pool.change.after) contains "management" 15 | } 16 | } 17 | 18 | node_auto_upgrade_is_enabled = rule when deny_undefined_management is true { 19 | all allNodePools as _, pool { 20 | all pool.change.after.management as _, management { 21 | management.auto_upgrade is true 22 | } 23 | } 24 | } 25 | 26 | main = rule { 27 | deny_undefined_management and 28 | node_auto_upgrade_is_enabled 29 | } 30 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes/test/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes/test/gcp-cis-7.8-kubernetes-ensure-automatic-node-upgrades-is-enabled-on-kubernetes-engine-clusters-nodes/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "strings" 3 | 4 | supportedImageTypes = [ 5 | "cos", 6 | "cos_containerd", 7 | ] 8 | 9 | allContainerClusters = filter tfplan.resource_changes as _, resource_changes { 10 | resource_changes.type is "google_container_cluster" and 11 | resource_changes.mode is "managed" and 12 | (resource_changes.change.actions contains "create" or 13 | resource_changes.change.actions is ["update"]) 14 | } 15 | 16 | allNodePools = filter tfplan.resource_changes as _, resource_changes { 17 | resource_changes.type is "google_container_node_pool" and 18 | resource_changes.mode is "managed" and 19 | (resource_changes.change.actions contains "create" or 20 | resource_changes.change.actions is ["update"]) 21 | } 22 | 23 | print("CIS 7.9: Ensure Container-Optimized OS (cos) is used for Kubernetes Engine Clusters Node image") 24 | 25 | deny_undefined_cluster_node_config = rule { 26 | all allContainerClusters as _, cluster { 27 | keys(cluster.change.after) contains "node_config" 28 | } 29 | } 30 | 31 | cluster_node_config_image_type_is_cos = rule when deny_undefined_cluster_node_config is true { 32 | all allContainerClusters as _, cluster { 33 | all cluster.change.after.node_config as _, node_config { 34 | strings.to_lower(node_config.image_type) in supportedImageTypes 35 | } 36 | } 37 | } 38 | 39 | deny_undefined_pool_node_config = rule { 40 | all allNodePools as _, pool { 41 | keys(pool.change.after) contains "node_config" 42 | } 43 | } 44 | 45 | pool_node_config_image_type_is_cos = rule when deny_undefined_pool_node_config is true { 46 | all allNodePools as _, pool { 47 | all pool.change.after.node_config as _, node_config { 48 | strings.to_lower(node_config.image_type) in supportedImageTypes 49 | } 50 | } 51 | } 52 | 53 | main = rule { 54 | deny_undefined_cluster_node_config and 55 | deny_undefined_pool_node_config and 56 | cluster_node_config_image_type_is_cos and 57 | pool_node_config_image_type_is_cos 58 | } 59 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image/test/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/kubernetes/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image/test/gcp-cis-7.9-kubernetes-ensure-container-optimized-osis-used-for-kubernetes-engine-clusters-node-image/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.1-networking-deny-default-network-in-project/gcp-cis-3.1-networking-deny-default-network-in-project.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allProjectResources = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_project" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.1: Ensure the default network does not exist in a project") 11 | 12 | deny_default_network_creation_in_project = rule { 13 | all allProjectResources as _, project { 14 | project.change.after.auto_create_network is false 15 | } 16 | } 17 | 18 | main = rule { 19 | deny_default_network_creation_in_project 20 | } 21 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.1-networking-deny-default-network-in-project/test/gcp-cis-3.1-networking-deny-default-network-in-project/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.1-networking-deny-default-network-in-project/test/gcp-cis-3.1-networking-deny-default-network-in-project/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.1-networking-deny-default-network-in-project/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_project.my_project": { 3 | "address": "google_project.my_project", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "auto_create_network": true, 10 | "billing_account": null, 11 | "labels": null, 12 | "name": "My Project", 13 | "org_id": "1234567", 14 | "project_id": "your-project-id", 15 | "timeouts": null, 16 | }, 17 | "after_unknown": {}, 18 | "before": null, 19 | }, 20 | "deposed": "", 21 | "index": null, 22 | "mode": "managed", 23 | "module_address": "", 24 | "name": "my_project", 25 | "provider_name": "google", 26 | "type": "google_project", 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.1-networking-deny-default-network-in-project/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_project.my_project": { 3 | "address": "google_project.my_project", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "auto_create_network": false, 10 | "billing_account": null, 11 | "labels": null, 12 | "name": "My Project", 13 | "org_id": "1234567", 14 | "project_id": "your-project-id", 15 | "timeouts": null, 16 | }, 17 | "after_unknown": {}, 18 | "before": null, 19 | }, 20 | "deposed": "", 21 | "index": null, 22 | "mode": "managed", 23 | "module_address": "", 24 | "name": "my_project", 25 | "provider_name": "google", 26 | "type": "google_project", 27 | }, 28 | } 29 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allDNSManagedZones = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_dns_managed_zone" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("3.3: Ensure that DNSSEC is enabled for Cloud DNS") 11 | 12 | deny_undefined_dnssec_config = rule { 13 | all allDNSManagedZones as _, zone { 14 | keys(zone.change.after) contains "dnssec_config" and 15 | length(zone.change.after.dnssec_config else []) != 0 16 | } 17 | } 18 | 19 | deny_insecure_dns_managed_zones = rule when deny_undefined_dnssec_config is true { 20 | all allDNSManagedZones as _, zone { 21 | all zone.change.after.dnssec_config as _, dnssec_config { 22 | dnssec_config.state is "on" 23 | } 24 | } 25 | } 26 | 27 | main = rule { 28 | deny_undefined_dnssec_config and 29 | deny_insecure_dns_managed_zones 30 | } 31 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/test/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/test/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "rsasha1", 16 | "key_length": 1024, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "rsasha1", 22 | "key_length": 1024, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "off", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.3-networking-dnssec-is-enabled-for-cloud-dns/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "ecdsap256sha256", 16 | "key_length": 256, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "ecdsap256sha256", 22 | "key_length": 256, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "on", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allDNSManagedZones = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_dns_managed_zone" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.4: Ensure that RSASHA1 is not used for key-signing key in Cloud DNS DNSSEC") 11 | 12 | deny_undefined_dnssec_config = rule { 13 | all allDNSManagedZones as _, zone { 14 | keys(zone.change.after) contains "dnssec_config" and 15 | length(zone.change.after.dnssec_config else []) != 0 16 | } 17 | } 18 | 19 | deny_rsasha1_key_signing = rule when deny_undefined_dnssec_config is true { 20 | all allDNSManagedZones as _, zone { 21 | all zone.change.after.dnssec_config as _, dnssec_config { 22 | all filter dnssec_config.default_key_specs as default_key_spec { 23 | default_key_spec.key_type is "keySigning" 24 | } as dks { 25 | dks.algorithm is not "rsasha1" 26 | } 27 | } 28 | } 29 | } 30 | 31 | main = rule { 32 | deny_undefined_dnssec_config and 33 | deny_rsasha1_key_signing 34 | } 35 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/test/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/test/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "rsasha1", 16 | "key_length": 1024, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "rsasha1", 22 | "key_length": 1024, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "off", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.4-networking-dnssec-rsasha1-is-not-key-signing-key/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "ecdsap256sha256", 16 | "key_length": 256, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "ecdsap256sha256", 22 | "key_length": 256, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "on", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allDNSManagedZones = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_dns_managed_zone" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.5: Ensure that RSASHA1 is not used for zone-signing key in Cloud DNS DNSSEC") 11 | 12 | deny_undefined_dnssec_config = rule { 13 | all allDNSManagedZones as _, zone { 14 | keys(zone.change.after) contains "dnssec_config" and 15 | length(zone.change.after.dnssec_config else []) != 0 16 | } 17 | } 18 | 19 | deny_rsasha1_zone_signing = rule when deny_undefined_dnssec_config is true { 20 | all allDNSManagedZones as _, zone { 21 | all zone.change.after.dnssec_config as _, dnssec_config { 22 | all filter dnssec_config.default_key_specs as default_key_spec { 23 | default_key_spec.key_type is "zoneSigning" 24 | } as dks { 25 | dks.algorithm is not "rsasha1" 26 | } 27 | } 28 | } 29 | } 30 | 31 | main = rule { 32 | deny_rsasha1_zone_signing 33 | } 34 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/test/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/test/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "rsasha1", 16 | "key_length": 1024, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "rsasha1", 22 | "key_length": 1024, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "off", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.5-networking-dnssec-rsasha1-is-not-used-for-zone-signing-key/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_dns_managed_zone.peering-zone": { 3 | "address": "google_dns_managed_zone.peering-zone", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": "example private dns peering zone", 10 | "dns_name": "peering.example.com.", 11 | "dnssec_config": [ 12 | { 13 | "default_key_specs": [ 14 | { 15 | "algorithm": "ecdsap256sha256", 16 | "key_length": 256, 17 | "key_type": "keySigning", 18 | "kind": "dns#dnsKeySpec", 19 | }, 20 | { 21 | "algorithm": "ecdsap256sha256", 22 | "key_length": 256, 23 | "key_type": "zoneSigning", 24 | "kind": "dns#dnsKeySpec", 25 | }, 26 | ], 27 | "kind": "dns#managedZoneDnsSecConfig", 28 | "non_existence": "nsec3", 29 | "state": "on", 30 | }, 31 | ], 32 | "forwarding_config": [], 33 | "labels": null, 34 | "name": "peering-zone", 35 | "peering_config": [], 36 | "private_visibility_config": [], 37 | "reverse_lookup": null, 38 | "timeouts": null, 39 | "visibility": "public", 40 | }, 41 | "after_unknown": {}, 42 | "before": null, 43 | }, 44 | "deposed": "", 45 | "index": null, 46 | "mode": "managed", 47 | "module_address": "", 48 | "name": "peering-zone", 49 | "provider_name": "google-beta", 50 | "type": "google_dns_managed_zone", 51 | }, 52 | } 53 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/gcp-cis-3.6-networking-ssh-is-restricted-from-internet.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allUnsupportedSourceRanges = [ 4 | "/0", 5 | "0.0.0.0", 6 | "0.0.0.0/0", 7 | ] 8 | 9 | allFirewallResources = filter tfplan.resource_changes as _, resource_changes { 10 | resource_changes.type is "google_compute_firewall" and 11 | resource_changes.mode is "managed" and 12 | (resource_changes.change.actions contains "create" or 13 | resource_changes.change.actions is ["update"]) 14 | } 15 | 16 | print("CIS 3.6: Ensure that SSH access is restricted from the internet") 17 | 18 | deny_public_ssh_access = rule { 19 | all allFirewallResources as _, firewall { 20 | all filter firewall.change.after.allow as _, allow { 21 | allow.ports contains "22" 22 | } as _ { 23 | all firewall.change.after.source_ranges as _, range { 24 | range not in allUnsupportedSourceRanges 25 | } 26 | } 27 | } 28 | } 29 | 30 | main = rule { 31 | deny_public_ssh_access 32 | } 33 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/test/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/test/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.6-networking-ssh-is-restricted-from-internet/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_compute_firewall.http": { 3 | "address": "google_compute_firewall.http", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "allow": [ 10 | { 11 | "ports": [ 12 | "80", 13 | ], 14 | "protocol": "tcp", 15 | }, 16 | ], 17 | "deny": [], 18 | "description": null, 19 | "disabled": null, 20 | "enable_logging": null, 21 | "name": "this-firewall-http", 22 | "network": "test-network", 23 | "priority": 1000, 24 | "source_ranges": [ 25 | "0.0.0.0/0", 26 | ], 27 | "source_service_accounts": null, 28 | "source_tags": null, 29 | "target_service_accounts": null, 30 | "target_tags": [ 31 | "this-firewall-http", 32 | ], 33 | "timeouts": null, 34 | }, 35 | "after_unknown": {}, 36 | "before": null, 37 | }, 38 | "deposed": "", 39 | "index": null, 40 | "mode": "managed", 41 | "module_address": "", 42 | "name": "http", 43 | "provider_name": "google", 44 | "type": "google_compute_firewall", 45 | }, 46 | "google_compute_firewall.https": { 47 | "address": "google_compute_firewall.https", 48 | "change": { 49 | "actions": [ 50 | "create", 51 | ], 52 | "after": { 53 | "allow": [ 54 | { 55 | "ports": [ 56 | "443", 57 | ], 58 | "protocol": "tcp", 59 | }, 60 | ], 61 | "deny": [], 62 | "description": null, 63 | "disabled": null, 64 | "enable_logging": null, 65 | "name": "this-firewall-https", 66 | "network": "test-network", 67 | "priority": 1000, 68 | "source_ranges": [ 69 | "0.0.0.0/0", 70 | ], 71 | "source_service_accounts": null, 72 | "source_tags": null, 73 | "target_service_accounts": null, 74 | "target_tags": [ 75 | "this-firewall-https", 76 | ], 77 | "timeouts": null, 78 | }, 79 | "after_unknown": {}, 80 | "before": null, 81 | }, 82 | "deposed": "", 83 | "index": null, 84 | "mode": "managed", 85 | "module_address": "", 86 | "name": "https", 87 | "provider_name": "google", 88 | "type": "google_compute_firewall", 89 | }, 90 | "google_compute_firewall.ssh-pass": { 91 | "address": "google_compute_firewall.ssh-pass", 92 | "change": { 93 | "actions": [ 94 | "create", 95 | ], 96 | "after": { 97 | "allow": [ 98 | { 99 | "ports": [ 100 | "22", 101 | ], 102 | "protocol": "tcp", 103 | }, 104 | ], 105 | "deny": [], 106 | "description": null, 107 | "disabled": null, 108 | "enable_logging": null, 109 | "name": "pass-firewall-ssh", 110 | "network": "test-network", 111 | "priority": 1000, 112 | "source_ranges": [ 113 | "172.16.0.0/0", 114 | ], 115 | "source_service_accounts": null, 116 | "source_tags": null, 117 | "target_service_accounts": null, 118 | "target_tags": [ 119 | "pass-firewall-ssh", 120 | ], 121 | "timeouts": null, 122 | }, 123 | "after_unknown": {}, 124 | "before": null, 125 | }, 126 | "deposed": "", 127 | "index": null, 128 | "mode": "managed", 129 | "module_address": "", 130 | "name": "ssh-pass", 131 | "provider_name": "google", 132 | "type": "google_compute_firewall", 133 | }, 134 | } 135 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.7-networking-rdp-is-restricted-from-internet/gcp-cis-3.7-networking-rdp-is-restricted-from-internet.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allUnsupportedSourceRanges = [ 4 | "/0", 5 | "0.0.0.0", 6 | "0.0.0.0/0", 7 | ] 8 | 9 | allFirewallResources = filter tfplan.resource_changes as _, resource_changes { 10 | resource_changes.type is "google_compute_firewall" and 11 | resource_changes.mode is "managed" and 12 | (resource_changes.change.actions contains "create" or 13 | resource_changes.change.actions is ["update"]) 14 | } 15 | 16 | print("CIS 3.7: Ensure that RDP access is restricted from the internet") 17 | 18 | deny_public_rdp_access = rule { 19 | all allFirewallResources as _, firewall { 20 | all filter firewall.change.after.allow as _, allow { 21 | allow.ports contains "3389" 22 | } as _ { 23 | all firewall.change.after.source_ranges as _, range { 24 | range not in allUnsupportedSourceRanges 25 | } 26 | } 27 | } 28 | } 29 | 30 | main = rule { 31 | deny_public_rdp_access 32 | } 33 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.7-networking-rdp-is-restricted-from-internet/test/gcp-cis-3.7-networking-rdp-is-restricted-from-internet/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.7-networking-rdp-is-restricted-from-internet/test/gcp-cis-3.7-networking-rdp-is-restricted-from-internet/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allSubnetworkResources = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_compute_subnetwork" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.8: Ensure Private Google Access is enabled for all subnetwork in VPC Network") 11 | 12 | deny_undefined_private_ip_google_access = rule { 13 | all allSubnetworkResources as _, subnetwork { 14 | keys(subnetwork.change.after) contains "private_ip_google_access" 15 | } 16 | } 17 | 18 | verify_private_ip_google_access_is_enabled = rule when deny_undefined_private_ip_google_access is true { 19 | all allSubnetworkResources as _, subnetwork { 20 | subnetwork.change.after.private_ip_google_access is true 21 | } 22 | } 23 | 24 | main = rule { 25 | deny_undefined_private_ip_google_access and 26 | verify_private_ip_google_access_is_enabled 27 | } 28 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/test/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/test/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_compute_subnetwork.this": { 3 | "address": "google_compute_subnetwork.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": null, 10 | "ip_cidr_range": "10.2.0.0/16", 11 | "log_config": [], 12 | "name": "test-subnetwork", 13 | "private_ip_google_access": null, 14 | "region": "us-central1", 15 | "secondary_ip_range": [ 16 | { 17 | "ip_cidr_range": "172.16.0.0/24", 18 | "range_name": "range", 19 | }, 20 | ], 21 | "timeouts": null, 22 | }, 23 | "after_unknown": {}, 24 | "before": null, 25 | }, 26 | "deposed": "", 27 | "index": null, 28 | "mode": "managed", 29 | "module_address": "", 30 | "name": "this", 31 | "provider_name": "google", 32 | "type": "google_compute_subnetwork", 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.8-networking-private-google-access-is-enabled-for-all-vpc-subnets/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_compute_subnetwork.this": { 3 | "address": "google_compute_subnetwork.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": null, 10 | "ip_cidr_range": "10.2.0.0/16", 11 | "log_config": [ 12 | { 13 | "aggregation_interval": "INTERVAL_10_MIN", 14 | "flow_sampling": 0.5, 15 | "metadata": "INCLUDE_ALL_METADATA", 16 | }, 17 | ], 18 | "name": "test-subnetwork", 19 | "private_ip_google_access": true, 20 | "region": "us-central1", 21 | "secondary_ip_range": [ 22 | { 23 | "ip_cidr_range": "172.16.0.0/24", 24 | "range_name": "range", 25 | }, 26 | ], 27 | "timeouts": null, 28 | }, 29 | "after_unknown": {}, 30 | "before": null, 31 | }, 32 | "deposed": "", 33 | "index": null, 34 | "mode": "managed", 35 | "module_address": "", 36 | "name": "this", 37 | "provider_name": "google", 38 | "type": "google_compute_subnetwork", 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allSubnetworkResources = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_compute_subnetwork" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 3.9: Ensure VPC Flow logs is enabled for every subnet in VPC Network") 11 | 12 | deny_undefined_log_config = rule { 13 | all allSubnetworkResources as _, subnetwork { 14 | keys(subnetwork.change.after) contains "log_config" 15 | } 16 | } 17 | 18 | subnetwork_log_config_is_enabled = rule when deny_undefined_log_config is true { 19 | all allSubnetworkResources as _, subnetwork { 20 | length(subnetwork.change.after.log_config) > 0 21 | } 22 | } 23 | 24 | main = rule { 25 | deny_undefined_log_config and 26 | subnetwork_log_config_is_enabled 27 | } 28 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/test/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/test/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_compute_subnetwork.this": { 3 | "address": "google_compute_subnetwork.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": null, 10 | "ip_cidr_range": "10.2.0.0/16", 11 | "log_config": [], 12 | "name": "test-subnetwork", 13 | "private_ip_google_access": null, 14 | "region": "us-central1", 15 | "secondary_ip_range": [ 16 | { 17 | "ip_cidr_range": "172.16.0.0/24", 18 | "range_name": "range", 19 | }, 20 | ], 21 | "timeouts": null, 22 | }, 23 | "after_unknown": {}, 24 | "before": null, 25 | }, 26 | "deposed": "", 27 | "index": null, 28 | "mode": "managed", 29 | "module_address": "", 30 | "name": "this", 31 | "provider_name": "google", 32 | "type": "google_compute_subnetwork", 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /cis/gcp/networking/gcp-cis-3.9-networking-vpc-flow-logs-is-enabled-for-all-vpc-subnets/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_compute_subnetwork.this": { 3 | "address": "google_compute_subnetwork.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "description": null, 10 | "ip_cidr_range": "10.2.0.0/16", 11 | "log_config": [ 12 | { 13 | "aggregation_interval": "INTERVAL_10_MIN", 14 | "flow_sampling": 0.5, 15 | "metadata": "INCLUDE_ALL_METADATA", 16 | }, 17 | ], 18 | "name": "test-subnetwork", 19 | "private_ip_google_access": true, 20 | "region": "us-central1", 21 | "secondary_ip_range": [ 22 | { 23 | "ip_cidr_range": "172.16.0.0/24", 24 | "range_name": "range", 25 | }, 26 | ], 27 | "timeouts": null, 28 | }, 29 | "after_unknown": {}, 30 | "before": null, 31 | }, 32 | "deposed": "", 33 | "index": null, 34 | "mode": "managed", 35 | "module_address": "", 36 | "name": "this", 37 | "provider_name": "google", 38 | "type": "google_compute_subnetwork", 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /cis/gcp/storage/README.md: -------------------------------------------------------------------------------- 1 | # CIS Google Cloud Computing Foundational Sentinel policies 2 | 3 | The following code snippets show the configuration settings that are required to successfully deploy Sentinel policies that follow the security recommendations that are provided in the [CIS Google Cloud Computing Platform Foundations Benchmark v.1.0.0](https://www.cisecurity.org/benchmark/google_cloud_computing_platform/). We cover policy configuration in more details in the [Managing Sentinel Policies](https://www.terraform.io/docs/cloud/sentinel/manage-policies.html) section in the Terraform Cloud [documentation](https://www.terraform.io/docs/cloud/index.html). 4 | 5 | ## CIS 5.1: Ensure that Cloud Storage bucket is not anonymously or publicly accessible 6 | 7 | ### Description 8 | Allowing anonymous and/or public access grants permissions to anyone to access bucket content. Such access might not be desired if you are storing any sensitive data. Hence, ensure that anonymous and/or public access to a bucket is not allowed. 9 | 10 | ### Configuration 11 | 12 | ```hcl 13 | policy "gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access" { 14 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access.sentinel" 15 | enforcement_level = "advisory" 16 | } 17 | ``` 18 | 19 | ## CIS 5.3: Ensure that logging is enabled for Cloud storage buckets 20 | 21 | ### Description 22 | By enabling access and storage logs on target Storage buckets, it is possible to capture all events which may affect objects within target buckets. Configuring logs to be placed in a separate bucket allows access to log information which can be useful in security and incident response workflows. 23 | 24 | ### Configuration 25 | 26 | ```hcl 27 | policy "gcp-cis-5.3-storage-bucket-logging-is-enabled" { 28 | source = "https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/master/cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/gcp-cis-5.3-storage-bucket-logging-is-enabled.sentinel" 29 | enforcement_level = "advisory" 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | import "json" 3 | 4 | allUnsupportedMembers = [ 5 | "allUsers", 6 | "allAuthenticatedUsers", 7 | ] 8 | 9 | allBucketIAMMembers = filter tfplan.resource_changes as _, resource_changes { 10 | resource_changes.type is "google_storage_bucket_iam_member" and 11 | resource_changes.mode is "managed" and 12 | (resource_changes.change.actions contains "create" or 13 | resource_changes.change.actions is ["update"]) 14 | } 15 | 16 | allBucketIAMBindings = filter tfplan.resource_changes as _, resource_changes { 17 | resource_changes.type is "google_storage_bucket_iam_binding" and 18 | resource_changes.mode is "managed" and 19 | (resource_changes.change.actions contains "create" or 20 | resource_changes.change.actions is ["update"]) 21 | } 22 | 23 | allBucketIAMPolicies = filter tfplan.resource_changes as _, resource_changes { 24 | resource_changes.type is "google_storage_bucket_iam_policy" and 25 | resource_changes.mode is "managed" and 26 | (resource_changes.change.actions contains "create" or 27 | resource_changes.change.actions is ["update"]) 28 | } 29 | 30 | print("CIS 5.1: Ensure that Cloud Storage bucket is not anonymously or publicly accessible") 31 | 32 | deny_unsupported_bucket_iam_members = rule { 33 | all allBucketIAMMembers as _, member { 34 | member.change.after.member not in allUnsupportedMembers 35 | } 36 | } 37 | 38 | deny_unsupported_bucket_iam_bindings = rule { 39 | all allBucketIAMBindings as _, binding { 40 | all binding.change.after.members as _, member { 41 | member not in allUnsupportedMembers 42 | } 43 | } 44 | } 45 | 46 | deny_unsupported_bucket_iam_policies = rule { 47 | all allBucketIAMPolicies as _, policy { 48 | all json.unmarshal(policy.change.after.policy_data).bindings as _, binding { 49 | all binding.members as _, member { 50 | member not in allUnsupportedMembers 51 | } 52 | } 53 | } 54 | } 55 | 56 | main = rule { 57 | deny_unsupported_bucket_iam_policies and 58 | deny_unsupported_bucket_iam_bindings and 59 | deny_unsupported_bucket_iam_members 60 | } 61 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/test/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/test/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_storage_bucket_iam_binding.this": { 3 | "address": "google_storage_bucket_iam_binding.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "bucket": "example-bucket", 10 | "members": [ 11 | "allAuthenticatedUsers", 12 | "allUsers", 13 | "user:user@example.com", 14 | ], 15 | "role": "roles/storage.admin", 16 | }, 17 | "after_unknown": {}, 18 | "before": null, 19 | }, 20 | "deposed": "", 21 | "index": null, 22 | "mode": "managed", 23 | "module_address": "", 24 | "name": "this", 25 | "provider_name": "google", 26 | "type": "google_storage_bucket_iam_binding", 27 | }, 28 | "google_storage_bucket_iam_member.allauthenticatedusers": { 29 | "address": "google_storage_bucket_iam_member.allauthenticatedusers", 30 | "change": { 31 | "actions": [ 32 | "create", 33 | ], 34 | "after": { 35 | "bucket": "example-bucket", 36 | "member": "allAuthenticatedUsers", 37 | "role": "roles/storage.admin", 38 | }, 39 | "after_unknown": {}, 40 | "before": null, 41 | }, 42 | "deposed": "", 43 | "index": null, 44 | "mode": "managed", 45 | "module_address": "", 46 | "name": "allauthenticatedusers", 47 | "provider_name": "google", 48 | "type": "google_storage_bucket_iam_member", 49 | }, 50 | "google_storage_bucket_iam_member.allusers": { 51 | "address": "google_storage_bucket_iam_member.allusers", 52 | "change": { 53 | "actions": [ 54 | "create", 55 | ], 56 | "after": { 57 | "bucket": "example-bucket", 58 | "member": "allUsers", 59 | "role": "roles/storage.admin", 60 | }, 61 | "after_unknown": {}, 62 | "before": null, 63 | }, 64 | "deposed": "", 65 | "index": null, 66 | "mode": "managed", 67 | "module_address": "", 68 | "name": "allusers", 69 | "provider_name": "google", 70 | "type": "google_storage_bucket_iam_member", 71 | }, 72 | "google_storage_bucket_iam_member.user": { 73 | "address": "google_storage_bucket_iam_member.user", 74 | "change": { 75 | "actions": [ 76 | "create", 77 | ], 78 | "after": { 79 | "bucket": "example-bucket", 80 | "member": "user:user@example.com", 81 | "role": "roles/storage.admin", 82 | }, 83 | "after_unknown": {}, 84 | "before": null, 85 | }, 86 | "deposed": "", 87 | "index": null, 88 | "mode": "managed", 89 | "module_address": "", 90 | "name": "user", 91 | "provider_name": "google", 92 | "type": "google_storage_bucket_iam_member", 93 | }, 94 | "google_storage_bucket_iam_policy.this": { 95 | "address": "google_storage_bucket_iam_policy.this", 96 | "change": { 97 | "actions": [ 98 | "create", 99 | ], 100 | "after": { 101 | "bucket": "example-bucket", 102 | "policy_data": "{\"bindings\":[{\"members\":[\"allAuthenticatedUsers\",\"allUsers\",\"user:user@example.com\"],\"role\":\"roles/storage.admin\"}]}", 103 | }, 104 | "after_unknown": {}, 105 | "before": null, 106 | }, 107 | "deposed": "", 108 | "index": null, 109 | "mode": "managed", 110 | "module_address": "", 111 | "name": "this", 112 | "provider_name": "google", 113 | "type": "google_storage_bucket_iam_policy", 114 | }, 115 | } 116 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.1-storage-deny-anonymous-or-public-bucket-access/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_storage_bucket_iam_binding.this": { 3 | "address": "google_storage_bucket_iam_binding.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "bucket": "example-bucket", 10 | "members": [ 11 | "user:user@example.com", 12 | ], 13 | "role": "roles/storage.admin", 14 | }, 15 | "after_unknown": {}, 16 | "before": null, 17 | }, 18 | "deposed": "", 19 | "index": null, 20 | "mode": "managed", 21 | "module_address": "", 22 | "name": "this", 23 | "provider_name": "google", 24 | "type": "google_storage_bucket_iam_binding", 25 | }, 26 | "google_storage_bucket_iam_member.user": { 27 | "address": "google_storage_bucket_iam_member.user", 28 | "change": { 29 | "actions": [ 30 | "create", 31 | ], 32 | "after": { 33 | "bucket": "example-bucket", 34 | "member": "user:user@example.com", 35 | "role": "roles/storage.admin", 36 | }, 37 | "after_unknown": {}, 38 | "before": null, 39 | }, 40 | "deposed": "", 41 | "index": null, 42 | "mode": "managed", 43 | "module_address": "", 44 | "name": "user", 45 | "provider_name": "google", 46 | "type": "google_storage_bucket_iam_member", 47 | }, 48 | "google_storage_bucket_iam_policy.this": { 49 | "address": "google_storage_bucket_iam_policy.this", 50 | "change": { 51 | "actions": [ 52 | "create", 53 | ], 54 | "after": { 55 | "bucket": "example-bucket", 56 | "policy_data": "{\"bindings\":[{\"members\":[\"user:user@example.com\"],\"role\":\"roles/storage.admin\"}]}", 57 | }, 58 | "after_unknown": {}, 59 | "before": null, 60 | }, 61 | "deposed": "", 62 | "index": null, 63 | "mode": "managed", 64 | "module_address": "", 65 | "name": "this", 66 | "provider_name": "google", 67 | "type": "google_storage_bucket_iam_policy", 68 | }, 69 | } 70 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/gcp-cis-5.3-storage-bucket-logging-is-enabled.sentinel: -------------------------------------------------------------------------------- 1 | import "tfplan/v2" as tfplan 2 | 3 | allStorageBuckets = filter tfplan.resource_changes as _, resource_changes { 4 | resource_changes.type is "google_storage_bucket" and 5 | resource_changes.mode is "managed" and 6 | (resource_changes.change.actions contains "create" or 7 | resource_changes.change.actions is ["update"]) 8 | } 9 | 10 | print("CIS 5.3: Ensure that logging is enabled for Cloud storage buckets") 11 | 12 | deny_undefined_logging = rule { 13 | all allStorageBuckets as _, bucket { 14 | keys(bucket.change.after) contains "logging" 15 | } 16 | } 17 | 18 | ensure_storage_bucket_logging_is_enabled = rule when deny_undefined_logging is true { 19 | all allStorageBuckets as _, bucket { 20 | length(bucket.change.after.logging) > 0 21 | } 22 | } 23 | 24 | main = rule { 25 | deny_undefined_logging and 26 | ensure_storage_bucket_logging_is_enabled 27 | } 28 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/test/gcp-cis-5.3-storage-bucket-logging-is-enabled/failure.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-failure.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = false 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/test/gcp-cis-5.3-storage-bucket-logging-is-enabled/success.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) HashiCorp, Inc. 2 | # SPDX-License-Identifier: MPL-2.0 3 | 4 | mock "tfplan/v2" { 5 | module { 6 | source = "../../testdata/mock-tfplan-success.sentinel" 7 | } 8 | } 9 | 10 | test { 11 | rules = { 12 | main = true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/testdata/mock-tfplan-failure.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_storage_bucket.that": { 3 | "address": "google_storage_bucket.that", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "cors": [], 10 | "default_event_based_hold": null, 11 | "encryption": [], 12 | "force_destroy": true, 13 | "labels": null, 14 | "lifecycle_rule": [], 15 | "location": "US", 16 | "logging": [], 17 | "name": "example-that", 18 | "requester_pays": null, 19 | "retention_policy": [], 20 | "storage_class": "STANDARD", 21 | "versioning": [], 22 | "website": [], 23 | }, 24 | "after_unknown": {}, 25 | "before": null, 26 | }, 27 | "deposed": "", 28 | "index": null, 29 | "mode": "managed", 30 | "module_address": "", 31 | "name": "that", 32 | "provider_name": "google", 33 | "type": "google_storage_bucket", 34 | }, 35 | "google_storage_bucket.this": { 36 | "address": "google_storage_bucket.this", 37 | "change": { 38 | "actions": [ 39 | "create", 40 | ], 41 | "after": { 42 | "cors": [], 43 | "default_event_based_hold": null, 44 | "encryption": [], 45 | "force_destroy": true, 46 | "labels": null, 47 | "lifecycle_rule": [], 48 | "location": "US", 49 | "logging": [ 50 | { 51 | "log_bucket": "example-logs-bucket", 52 | "log_object_prefix": "bcktl", 53 | }, 54 | ], 55 | "name": "example-this", 56 | "requester_pays": null, 57 | "retention_policy": [], 58 | "storage_class": "STANDARD", 59 | "versioning": [], 60 | "website": [], 61 | }, 62 | "after_unknown": {}, 63 | "before": null, 64 | }, 65 | "deposed": "", 66 | "index": null, 67 | "mode": "managed", 68 | "module_address": "", 69 | "name": "this", 70 | "provider_name": "google", 71 | "type": "google_storage_bucket", 72 | }, 73 | } 74 | -------------------------------------------------------------------------------- /cis/gcp/storage/gcp-cis-5.3-storage-bucket-logging-is-enabled/testdata/mock-tfplan-success.sentinel: -------------------------------------------------------------------------------- 1 | resource_changes = { 2 | "google_storage_bucket.this": { 3 | "address": "google_storage_bucket.this", 4 | "change": { 5 | "actions": [ 6 | "create", 7 | ], 8 | "after": { 9 | "cors": [], 10 | "default_event_based_hold": null, 11 | "encryption": [], 12 | "force_destroy": true, 13 | "labels": null, 14 | "lifecycle_rule": [], 15 | "location": "US", 16 | "logging": [ 17 | { 18 | "log_bucket": "example-logs-bucket", 19 | "log_object_prefix": "bcktl", 20 | }, 21 | ], 22 | "name": "example-this", 23 | "requester_pays": null, 24 | "retention_policy": [], 25 | "storage_class": "STANDARD", 26 | "versioning": [], 27 | "website": [], 28 | }, 29 | "after_unknown": {}, 30 | "before": null, 31 | }, 32 | "deposed": "", 33 | "index": null, 34 | "mode": "managed", 35 | "module_address": "", 36 | "name": "this", 37 | "provider_name": "google", 38 | "type": "google_storage_bucket", 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /images/policy-sets-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/6a0ab90f955b899c5d51a916a86a7aa46054f138/images/policy-sets-create.png -------------------------------------------------------------------------------- /images/policy-sets-navigate-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/6a0ab90f955b899c5d51a916a86a7aa46054f138/images/policy-sets-navigate-1.png -------------------------------------------------------------------------------- /images/policy-sets-navigate-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/6a0ab90f955b899c5d51a916a86a7aa46054f138/images/policy-sets-navigate-2.png -------------------------------------------------------------------------------- /images/policy-sets-navigate-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/6a0ab90f955b899c5d51a916a86a7aa46054f138/images/policy-sets-navigate-3.png -------------------------------------------------------------------------------- /images/policy-sets-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hashicorp/terraform-foundational-policies-library/6a0ab90f955b899c5d51a916a86a7aa46054f138/images/policy-sets-run.png --------------------------------------------------------------------------------