[Add] Updated conftest to latest version, policies updated, precommit hook also updated

This commit is contained in:
2025-05-23 22:21:21 +03:00
parent 8a0ae2e8fb
commit 5f39f381c1
28 changed files with 838 additions and 126 deletions

15
terraform/LICENSE Normal file
View File

@@ -0,0 +1,15 @@
Conftest - Write tests against your config files
Copyright (C) 2019 Gareth Rushgrove
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,66 +1,52 @@
# Terraform Security as Code
# Conftest
This directory contains Terraform configurations for creating a Kubernetes cluster on Proxmox VMs. Security is implemented as code through policy checks.
[![Go Report Card](https://goreportcard.com/badge/open-policy-agent/opa)](https://goreportcard.com/report/open-policy-agent/conftest) [![Netlify](https://api.netlify.com/api/v1/badges/2d928746-3380-4123-b0eb-1fd74ba390db/deploy-status)](https://app.netlify.com/sites/vibrant-villani-65041c/deploys)
## Security Policies
Conftest helps you write tests against structured configuration data. Using Conftest you can
write tests for your Kubernetes configuration, Tekton pipeline definitions, Terraform code,
Serverless configs or any other config files.
Security policies are defined as Open Policy Agent (OPA) Rego files in the `policy/` directory:
Conftest uses the Rego language from [Open Policy Agent](https://www.openpolicyagent.org/) for writing
the assertions. You can read more about Rego in [How do I write policies](https://www.openpolicyagent.org/docs/how-do-i-write-policies.html)
in the Open Policy Agent documentation.
- **main.rego**: Combined security policy file that includes:
- VM security (password auth, root login, qemu-agent)
- Network security (bridge configuration, IPv6, DNS)
- Provider security (TLS verification, version pinning)
Here's a quick example. Save the following as `policy/deployment.rego`:
## Running Security Checks
```rego
package main
### Prerequisites
deny[msg] {
input.kind == "Deployment"
not input.spec.template.spec.securityContext.runAsNonRoot
1. Install OPA CLI and Conftest:
```bash
# Install OPA
curl -L -o opa https://openpolicy.io/downloads/latest/opa_linux_amd64
chmod 755 opa
sudo mv opa /usr/local/bin
# Install Conftest
wget https://github.com/open-policy-agent/conftest/releases/download/v0.42.1/conftest_0.42.1_Linux_x86_64.tar.gz
tar xzf conftest_0.42.1_Linux_x86_64.tar.gz
sudo mv conftest /usr/local/bin
```
msg := "Containers must not run as root"
}
2. Install Trivy:
```bash
# For Debian/Ubuntu
sudo apt-get install trivy
deny[msg] {
input.kind == "Deployment"
not input.spec.selector.matchLabels.app
# For other systems, see: https://aquasecurity.github.io/trivy/latest/getting-started/installation/
```
msg := "Containers must provide app label for pod selectors"
}
```
3. Install Checkov:
```bash
pip install checkov
```
Assuming you have a Kubernetes deployment in `deployment.yaml` you can run Conftest like so:
### Running Policy Checks
```console
$ conftest test deployment.yaml
FAIL - deployment.yaml - Containers must not run as root
FAIL - deployment.yaml - Containers must provide app label for pod selectors
1. Generate a Terraform plan and convert to JSON:
```bash
cd terraform
terraform init
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
```
2 tests, 0 passed, 0 warnings, 2 failures, 0 exceptions
```
2. Run Conftest with OPA policies:
```bash
conftest test tfplan.json -p policy/
```
Conftest isn't specific to Kubernetes. It will happily let you write tests for any configuration files in a variety of different formats. See the [documentation](https://www.conftest.dev/) for [installation instructions](https://www.conftest.dev/install/) and
more details about the features.
3. Run Trivy IaC security scan:
```bash
# Skip AWS policies and use variables file
trivy config --severity HIGH,CRITICAL --skip-policy "aws.*" --tf-vars="variables.tfvars" .
```
## Want to contribute to Conftest?
4. Run Checkov:
```
* See [DEVELOPMENT.md](DEVELOPMENT.md) to build and test Conftest itself.
* See [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
For discussions and questions join us on the [Open Policy Agent Slack](https://slack.openpolicyagent.org/)
in the `#opa-conftest` channel.

View File

@@ -17,8 +17,8 @@ resource "proxmox_vm_qemu" "proxmox_vm_master" {
nameserver = "1.1.1.1 8.8.8.8"
ipconfig0 = "ip=${var.master_ips[count.index]}/${var.networkrange},gw=${var.gateway}"
skip_ipv6 = true
ciuser = "debian"
cipassword = ""
ciuser = "root"
cipassword = "test_passwd"
sshkeys = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXXnm9Hl4fPCt/Xjd/8E5tKY+edtM/BvdMOXpx40oWG iac@proxmox.vadzik-iot.ru"
# Most cloud-init images require a serial device for their display

View File

@@ -7,7 +7,7 @@ import input
vms := [r | r := input.planned_values.root_module.resources[_]; r.type == "proxmox_vm_qemu"]
# Helper function to check if a value is empty or undefined
is_empty(value) {
is_empty(value) if {
value == ""
} {
value == null
@@ -19,28 +19,28 @@ is_empty(value) {
min_memory = 512
# Deny if VM allows password authentication
deny[msg] {
deny contains msg if {
some vm in vms
not is_empty(vm.values.cipassword)
msg := sprintf("VM '%s' uses password authentication. Use SSH keys only.", [vm.name])
}
# Deny if VM allows root login
deny[msg] {
deny contains msg if {
some vm in vms
vm.values.ciuser == "root"
msg := sprintf("VM '%s' allows root login. Use a non-root user.", [vm.name])
}
# Deny if qemu-agent is not enabled
deny[msg] {
deny contains msg if {
some vm in vms
vm.values.agent != 1
msg := sprintf("VM '%s' does not have qemu-agent enabled (agent = 1).", [vm.name])
}
# Deny if VM uses insecure network bridge
deny[msg] {
deny contains msg if {
some vm in vms
net := vm.values.network[_]
net.bridge != "vmbr2"
@@ -48,28 +48,28 @@ deny[msg] {
}
# Deny if IPv6 is not disabled
deny[msg] {
deny contains msg if {
some vm in vms
not vm.values.skip_ipv6
msg := sprintf("VM '%s' does not have IPv6 disabled (skip_ipv6 = true).", [vm.name])
}
# Deny if TLS verification is disabled
deny[msg] {
deny contains msg if {
tls_enabled := input.variables.pm_tls_insecure.value
tls_enabled == true
msg := "TLS verification must be enabled (pm_tls_insecure = false)"
}
# Deny if provider version is not pinned
deny[msg] {
deny contains msg if {
provider := input.configuration.terraform.required_providers.proxmox
not startswith(provider.version_constraint, "=")
msg := "Provider version must be pinned with '=' constraint"
}
# Deny if VM memory is below minimum requirement
deny[msg] {
deny contains msg if {
some vm in vms
memory := to_number(vm.values.memory)
memory < min_memory
@@ -77,20 +77,20 @@ deny[msg] {
}
# Deny if VM does not have a description
deny[msg] {
deny contains msg if {
some vm in vms
is_empty(vm.values.desc)
msg := sprintf("VM '%s' must have a description for documentation purposes.", [vm.name])
}
# Deny if VM uses default SCSI controller
deny[msg] {
deny contains msg if {
some vm in vms
vm.values.scsihw == "lsi"
msg := sprintf("VM '%s' uses default SCSI controller. Use virtio-scsi-pci for better performance.", [vm.name])
}
# Test rule to verify policy is loaded
test_policy_loaded {
test_policy_loaded if {
true
}

View File

@@ -109,47 +109,46 @@ mock_input_insecure := {
}
# Test secure configuration passes
test_secure_config {
input := mock_input_secure
count(deny) == 0
test_secure_config if {
count(deny) == 0 with input as mock_input_secure
}
# Test password authentication
test_password_auth {
test_password_auth if {
deny["VM 'insecure_vm' uses password authentication. Use SSH keys only."] with input as mock_input_insecure
}
# Test qemu agent
test_qemu_agent {
test_qemu_agent if {
deny["VM 'insecure_vm' does not have qemu-agent enabled (agent = 1)."] with input as mock_input_insecure
}
# Test network bridge
test_network_bridge {
test_network_bridge if {
deny["VM 'insecure_vm' uses insecure network bridge 'vmbr0'. Use 'vmbr2'."] with input as mock_input_insecure
}
# Test TLS verification
test_tls_verification {
test_tls_verification if {
deny["TLS verification must be enabled (pm_tls_insecure = false)"] with input as mock_input_insecure
}
# Test provider version pinning
test_provider_version {
test_provider_version if {
deny["Provider version must be pinned with '=' constraint"] with input as mock_input_insecure
}
# Test minimum memory requirement
test_minimum_memory {
test_minimum_memory if {
deny["VM 'insecure_vm' has insufficient memory (256MB). Minimum required: 512MB."] with input as mock_input_insecure
}
# Test VM description requirement
test_vm_description {
test_vm_description if {
deny["VM 'insecure_vm' must have a description for documentation purposes."] with input as mock_input_insecure
}
# Test SCSI controller requirement
test_scsi_controller {
test_scsi_controller if {
deny["VM 'insecure_vm' uses default SCSI controller. Use virtio-scsi-pci for better performance."] with input as mock_input_insecure
}

View File

@@ -1,47 +0,0 @@
{
"planned_values": {
"root_module": {
"resources": [
{
"type": "proxmox_vm_qemu",
"name": "insecure_vm",
"values": {
"cipassword": "password123",
"ciuser": "root",
"agent": 0,
"network": [
{
"bridge": "vmbr0"
}
],
"skip_ipv6": false,
"memory": 256,
"desc": "",
"scsihw": "lsi",
"cpu": "",
"backup": false,
"tags": ""
}
}
]
}
},
"configuration": {
"provider_config": {
"proxmox": {
"expressions": {
"pm_tls_insecure": {
"constant_value": true
}
}
}
},
"terraform": {
"required_providers": {
"proxmox": {
"version_constraint": "~2.9.14"
}
}
}
}
}

View File

@@ -3,8 +3,6 @@
# Security Check Script for Terraform
# This script runs all security checks on your Terraform configuration
set -e
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
@@ -65,7 +63,7 @@ terraform show -json tfplan | jq > tfplan.json
echo -e "\n${YELLOW}Running OPA policy checks...${NC}"
if [ -d "policy" ]; then
conftest test tfplan.json -p policy/
conftest test -p policy/ tfplan.json
CONFTEST_EXIT=$?
if [ $CONFTEST_EXIT -eq 0 ]; then
echo -e "${GREEN}✅ OPA policy checks passed.${NC}"