Skip to content

Commit

Permalink
Merge pull request #150 from nirmata/add-ecs-config-policies
Browse files Browse the repository at this point in the history
feat: add `ecs` best practices terraform config policies
  • Loading branch information
anusha94 authored Jul 24, 2024
2 parents 6e49d0d + 6b96e3f commit b63d9d3
Show file tree
Hide file tree
Showing 48 changed files with 2,753 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# 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 config file, follow the steps outlined below:

For testing this policy you will need to:
- Make sure you have `nctl` installed on the machine

1. **Test the Policy with nctl:**
```
nctl scan terraform --resources tf-config.tf --policy policy.yaml
```

a. **Test Policy Against Valid Terraform Config File:**
```
nctl scan terraform --resources test/good.tf --policies check-awsvpc-network-mode.yaml
```

This produces the output:
```
Version: 4.0.1
Fetching policies...
Loading policies...
• found 1 policies
Running analysis...
• no errors
Results...
+---------------------------+---------------------------+--------------+---------+--------+
| POLICY | RULE | RESOURCE | MESSAGE | RESULT |
+---------------------------+---------------------------+--------------+---------+--------+
| check-awsvpc-network-mode | check-awsvpc-network-mode | test/good.tf | | pass |
+---------------------------+---------------------------+--------------+---------+--------+
Done
```

b. **Test Against Invalid Terraform Config File:**
```
nctl scan terraform --resources test/bad-01.tf --policies check-awsvpc-network-mode.yaml
```

This produces the output:
```
Version: 4.0.1
Fetching policies...
Loading policies...
• found 1 policies
Running analysis...
• no errors
Results...
+---------------------------+---------------------------+----------------+--------------------------------------------------------------------------------+--------+
| POLICY | RULE | RESOURCE | MESSAGE | RESULT |
+---------------------------+---------------------------+----------------+--------------------------------------------------------------------------------+--------+
| check-awsvpc-network-mode | check-awsvpc-network-mode | test/bad-01.tf | ECS services and tasks are required to use awsvpc network mode.: | fail |
| | | | all[0].check.~.(resource.aws_ecs_task_definition.values(@)[])[0].network_mode: | |
| | | | Invalid value: "bridge": Expected value: "awsvpc" | |
+---------------------------+---------------------------+----------------+--------------------------------------------------------------------------------+--------+
Done
```

---

These instructions are designed to systematically assess the compliance of Terraform config files with the defined policy. Following these steps ensures a thorough examination of the `awsvpc` network mode presence in the terraform config file, allowing for effective validation and adherence to the specified policy.
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,11 @@ spec:
- name: check-awsvpc-network-mode
match:
all:
- ($analyzer):
resource:
type: terraform-config
- (resource.aws_ecs_task_definition && length(resource.aws_ecs_task_definition) > `0`): true
- ($analyzer.resource.type): terraform-config
- (resource.aws_ecs_task_definition != null): true
assert:
all:
- message: ECS services and tasks are required to use awsvpc network mode.
check:
resource:
~.(aws_ecs_task_definition):
~.(@):
network_mode: awsvpc
~.(resource.aws_ecs_task_definition.values(@)[]):
network_mode: awsvpc
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"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
resource "aws_ecs_task_definition" "good_task" {
family = "service"
network_mode = "awsvpc"
requires_compatibilities = ["EC2"]
cpu = 512
memory = 2048
container_definitions = <<DEFINITION
[
{
"name" : "foo-task-1",
"image" : "nginx:1.23.1",
"cpu" : 512,
"memory" : 2048,
"essential" : true,
"portMappings" : [
{
"containerPort" : 80,
"hostPort" : 80
}
]
}
]
DEFINITION
}

resource "aws_ecs_task_definition" "bad_task" {
family = "service"
network_mode = "bridge"
requires_compatibilities = ["EC2"]
cpu = 512
memory = 2048
container_definitions = <<DEFINITION
[
{
"name" : "foo-task-2",
"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"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"provider": {
"aws": [
{
"region": "us-west-1"
}
],
"docker": [
{}
]
},
"resource": {
"aws_ecs_task_definition": {
"task": [
{
"container_definitions": " [\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": 512,
"family": "service",
"memory": 2048,
"network_mode": "bridge",
"requires_compatibilities": [
"EC2"
]
}
]
}
},
"terraform": [
{
"required_providers": [
{
"aws": {
"source": "hashicorp/aws",
"version": "~\u003e 4.0"
},
"docker": {
"source": "kreuzwerker/docker",
"version": "~\u003e2.20.0"
}
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"provider": {
"aws": [
{
"region": "us-west-1"
}
],
"docker": [
{}
]
},
"resource": {
"aws_ecs_task_definition": {
"bad_task": [
{
"container_definitions": " [\n {\n \"name\" : \"foo-task-2\",\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": 512,
"family": "service",
"memory": 2048,
"network_mode": "bridge",
"requires_compatibilities": [
"EC2"
]
}
],
"good_task": [
{
"container_definitions": " [\n {\n \"name\" : \"foo-task-1\",\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": 512,
"family": "service",
"memory": 2048,
"network_mode": "awsvpc",
"requires_compatibilities": [
"EC2"
]
}
]
}
},
"terraform": [
{
"required_providers": [
{
"aws": {
"source": "hashicorp/aws",
"version": "~\u003e 4.0"
},
"docker": {
"source": "kreuzwerker/docker",
"version": "~\u003e2.20.0"
}
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
analyzer:
resource:
type: terraform-config
Loading

0 comments on commit b63d9d3

Please sign in to comment.