-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #109 from fykaa/aws-ecs
feat: Terraform Best Practices `kyverno-json-policies` for AWS ECS
- Loading branch information
Showing
30 changed files
with
3,775 additions
and
0 deletions.
There are no files selected for viewing
75 changes: 75 additions & 0 deletions
75
terraform-best-practices/aws/ecs/check-aws-vpc-network-mode/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Check `awsvpc` network mode | ||
|
||
When you're running containers on AWS, managing the networking becomes crucial, especially when leveraging the benefits of hosting multiple containers on a single host. There are various network modes to choose from: | ||
|
||
1. **Host mode:** This is the most basic network mode in Amazon ECS. It essentially shares the host's networking stack with the containers. | ||
|
||
2. **Bridge mode:** This mode employs a virtual network bridge to establish a layer between the host and the container's networking. | ||
|
||
3. **AWSVPC mode:** Here, Amazon ECS generates and oversees an Elastic Network Interface (ENI) for each task, providing each task with a distinct private IP address within the VPC. | ||
|
||
By default, the network mode for ECS tasks is set to `bridge`. However, we will opt for the `awsvpc` network mode here. This choice is strategic, as it facilitates controlled traffic flow between tasks and enhances security. `awsvpc` offers task-level network isolation for tasks running on Amazon EC2. Importantly, it's the exclusive network mode allowing the assignment of security groups to tasks. | ||
|
||
To formalize our approach, it's prudent to establish a policy that ensures the usage of 'awsvpc' network mode. This policy aligns with our security strategy by adding an extra layer of protection through task-level isolation and the ability to apply security groups at the task level. Therefore, adopting and enforcing this policy safeguards our containerized infrastructure while optimizing networking capabilities on AWS. | ||
|
||
### Policy Validation Testing Instructions | ||
|
||
To evaluate and test the policy ensuring the presence of the `awsvpc` network mode in the Terraform plan payload, follow the steps outlined below: | ||
|
||
For testing this policy you will need to: | ||
- Make sure you have `kyverno-json` installed on the machine | ||
- Properly authenticate with AWS | ||
|
||
1. **Initialize Terraform:** | ||
```bash | ||
terraform init | ||
``` | ||
|
||
2. **Create Binary Terraform Plan:** | ||
```bash | ||
terraform plan -out tfplan.binary | ||
``` | ||
|
||
3. **Convert Binary to JSON Payload:** | ||
```bash | ||
terraform show -json tfplan.binary | jq > payload.json | ||
``` | ||
|
||
4. **Test the Policy with Kyverno:** | ||
``` | ||
kyverno-json scan --payload payload.json --policy policy.yaml | ||
``` | ||
|
||
a. **Test Policy Against Valid Payload:** | ||
``` | ||
kyverno-json scan --policy check-aws-vpc-network-mode.yaml --payload policy-test/good-payload.json | ||
``` | ||
|
||
This produces the output: | ||
``` | ||
Loading policies ... | ||
Loading payload ... | ||
Pre processing ... | ||
Running ( evaluating 1 resource against 1 policy ) ... | ||
- check-awsvpc-network-mode / check-awsvpc-network-mode / PASSED | ||
Done | ||
``` | ||
|
||
b. **Test Against Invalid Payload:** | ||
``` | ||
kyverno-json scan --policy check-aws-vpc-network-mode.yaml --payload policy-test/bad-payload.json | ||
``` | ||
|
||
This produces the output: | ||
``` | ||
Loading policies ... | ||
Loading payload ... | ||
Pre processing ... | ||
Running ( evaluating 1 resource against 1 policy ) ... | ||
- check-awsvpc-network-mode / check-awsvpc-network-mode / FAILED: ECS services and tasks are required to use awsvpc network mode.: all[0].check.values.(network_mode=='awsvpc'): Invalid value: false: Expected value: true | ||
Done | ||
``` | ||
|
||
--- | ||
|
||
These instructions are designed to systematically assess the compliance of Terraform plans with the defined policy. Following these steps ensures a thorough examination of the `awsvpc` network mode presence in the payload, allowing for effective validation and adherence to the specified policy. |
27 changes: 27 additions & 0 deletions
27
terraform-best-practices/aws/ecs/check-aws-vpc-network-mode/check-aws-vpc-network-mode.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
apiVersion: json.kyverno.io/v1alpha1 | ||
kind: ValidatingPolicy | ||
metadata: | ||
name: check-awsvpc-network-mode | ||
labels: | ||
ecs.aws.network.kyverno.io: awsvpc | ||
annotations: | ||
policies.kyverno.io/title: Check awsvpc network mode | ||
policies.kyverno.io/category: ECS Best Practices | ||
policies.kyverno.io/severity: medium | ||
policies.kyverno.io/description: >- | ||
The awsvpc network mode restricts the flow of traffic between different | ||
tasks or between your tasks and other services that run within your Amazon VPC. | ||
The awsvpc network mode provides task-level network isolation for tasks | ||
that run on Amazon EC2. | ||
spec: | ||
rules: | ||
- name: check-awsvpc-network-mode | ||
match: | ||
any: | ||
- (planned_values.root_module.resources[?type=='aws_ecs_task_definition'] | length(@) > `0`): true | ||
assert: | ||
all: | ||
- message: ECS services and tasks are required to use awsvpc network mode. | ||
check: | ||
~.(planned_values.root_module.resources[?type=='aws_ecs_task_definition'].values): | ||
network_mode: awsvpc |
173 changes: 173 additions & 0 deletions
173
terraform-best-practices/aws/ecs/check-aws-vpc-network-mode/test/bad-payload.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
{ | ||
"format_version": "1.2", | ||
"terraform_version": "1.6.6-dev", | ||
"planned_values": { | ||
"root_module": { | ||
"resources": [ | ||
{ | ||
"address": "aws_ecs_task_definition.task", | ||
"mode": "managed", | ||
"type": "aws_ecs_task_definition", | ||
"name": "task", | ||
"provider_name": "registry.terraform.io/hashicorp/aws", | ||
"schema_version": 1, | ||
"values": { | ||
"container_definitions": "[{\"cpu\":512,\"essential\":true,\"image\":\"nginx:1.23.1\",\"memory\":2048,\"name\":\"foo-task\",\"portMappings\":[{\"containerPort\":80,\"hostPort\":80}]}]", | ||
"cpu": "512", | ||
"ephemeral_storage": [], | ||
"execution_role_arn": null, | ||
"family": "service", | ||
"inference_accelerator": [], | ||
"ipc_mode": null, | ||
"memory": "2048", | ||
"network_mode": "bridge", | ||
"pid_mode": null, | ||
"placement_constraints": [], | ||
"proxy_configuration": [], | ||
"requires_compatibilities": [ | ||
"EC2" | ||
], | ||
"runtime_platform": [], | ||
"skip_destroy": false, | ||
"tags": null, | ||
"task_role_arn": null, | ||
"volume": [] | ||
}, | ||
"sensitive_values": { | ||
"ephemeral_storage": [], | ||
"inference_accelerator": [], | ||
"placement_constraints": [], | ||
"proxy_configuration": [], | ||
"requires_compatibilities": [ | ||
false | ||
], | ||
"runtime_platform": [], | ||
"tags_all": {}, | ||
"volume": [] | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"resource_changes": [ | ||
{ | ||
"address": "aws_ecs_task_definition.task", | ||
"mode": "managed", | ||
"type": "aws_ecs_task_definition", | ||
"name": "task", | ||
"provider_name": "registry.terraform.io/hashicorp/aws", | ||
"change": { | ||
"actions": [ | ||
"create" | ||
], | ||
"before": null, | ||
"after": { | ||
"container_definitions": "[{\"cpu\":512,\"essential\":true,\"image\":\"nginx:1.23.1\",\"memory\":2048,\"name\":\"foo-task\",\"portMappings\":[{\"containerPort\":80,\"hostPort\":80}]}]", | ||
"cpu": "512", | ||
"ephemeral_storage": [], | ||
"execution_role_arn": null, | ||
"family": "service", | ||
"inference_accelerator": [], | ||
"ipc_mode": null, | ||
"memory": "2048", | ||
"network_mode": "awsvpc", | ||
"pid_mode": null, | ||
"placement_constraints": [], | ||
"proxy_configuration": [], | ||
"requires_compatibilities": [ | ||
"EC2" | ||
], | ||
"runtime_platform": [], | ||
"skip_destroy": false, | ||
"tags": null, | ||
"task_role_arn": null, | ||
"volume": [] | ||
}, | ||
"after_unknown": { | ||
"arn": true, | ||
"arn_without_revision": true, | ||
"ephemeral_storage": [], | ||
"id": true, | ||
"inference_accelerator": [], | ||
"placement_constraints": [], | ||
"proxy_configuration": [], | ||
"requires_compatibilities": [ | ||
false | ||
], | ||
"revision": true, | ||
"runtime_platform": [], | ||
"tags_all": true, | ||
"volume": [] | ||
}, | ||
"before_sensitive": false, | ||
"after_sensitive": { | ||
"ephemeral_storage": [], | ||
"inference_accelerator": [], | ||
"placement_constraints": [], | ||
"proxy_configuration": [], | ||
"requires_compatibilities": [ | ||
false | ||
], | ||
"runtime_platform": [], | ||
"tags_all": {}, | ||
"volume": [] | ||
} | ||
} | ||
} | ||
], | ||
"configuration": { | ||
"provider_config": { | ||
"aws": { | ||
"name": "aws", | ||
"full_name": "registry.terraform.io/hashicorp/aws", | ||
"version_constraint": "~> 4.0", | ||
"expressions": { | ||
"region": { | ||
"constant_value": "us-west-1" | ||
} | ||
} | ||
}, | ||
"docker": { | ||
"name": "docker", | ||
"full_name": "registry.terraform.io/kreuzwerker/docker", | ||
"version_constraint": "~> 2.20.0" | ||
} | ||
}, | ||
"root_module": { | ||
"resources": [ | ||
{ | ||
"address": "aws_ecs_task_definition.task", | ||
"mode": "managed", | ||
"type": "aws_ecs_task_definition", | ||
"name": "task", | ||
"provider_config_key": "aws", | ||
"expressions": { | ||
"container_definitions": { | ||
"constant_value": " [\n {\n \"name\" : \"foo-task\",\n \"image\" : \"nginx:1.23.1\",\n \"cpu\" : 512,\n \"memory\" : 2048,\n \"essential\" : true,\n \"portMappings\" : [\n {\n \"containerPort\" : 80,\n \"hostPort\" : 80\n }\n ]\n }\n ]\n" | ||
}, | ||
"cpu": { | ||
"constant_value": 512 | ||
}, | ||
"family": { | ||
"constant_value": "service" | ||
}, | ||
"memory": { | ||
"constant_value": 2048 | ||
}, | ||
"network_mode": { | ||
"constant_value": "awsvpc" | ||
}, | ||
"requires_compatibilities": { | ||
"constant_value": [ | ||
"EC2" | ||
] | ||
} | ||
}, | ||
"schema_version": 1 | ||
} | ||
] | ||
} | ||
}, | ||
"timestamp": "2024-01-15T13:25:27Z", | ||
"errored": false | ||
} |
46 changes: 46 additions & 0 deletions
46
terraform-best-practices/aws/ecs/check-aws-vpc-network-mode/test/bad.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
resource "aws_ecs_task_definition" "task" { | ||
family = "service" | ||
network_mode = "bridge" | ||
requires_compatibilities = ["EC2"] | ||
cpu = 512 | ||
memory = 2048 | ||
container_definitions = <<DEFINITION | ||
[ | ||
{ | ||
"name" : "foo-task", | ||
"image" : "nginx:1.23.1", | ||
"cpu" : 512, | ||
"memory" : 2048, | ||
"essential" : true, | ||
"portMappings" : [ | ||
{ | ||
"containerPort" : 80, | ||
"hostPort" : 80 | ||
} | ||
] | ||
} | ||
] | ||
DEFINITION | ||
} | ||
|
||
# Setting up the configuration for using Docker and AWS providers | ||
|
||
terraform { | ||
required_providers { | ||
docker = { | ||
source = "kreuzwerker/docker" | ||
version = "~>2.20.0" | ||
} | ||
aws = { | ||
source = "hashicorp/aws" | ||
version = "~> 4.0" | ||
} | ||
} | ||
} | ||
|
||
# Configuring docker and AWS as providers | ||
provider "docker" {} | ||
|
||
provider "aws" { | ||
region = "us-west-1" | ||
} |
Oops, something went wrong.