Skip to content

Commit

Permalink
add ecs best practices
Browse files Browse the repository at this point in the history
Signed-off-by: Chandan-DK <[email protected]>
  • Loading branch information
Chandan-DK committed Jul 24, 2024
1 parent 6e49d0d commit d274e01
Show file tree
Hide file tree
Showing 48 changed files with 2,796 additions and 0 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
@@ -0,0 +1,28 @@
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:
all:
- ($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.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 d274e01

Please sign in to comment.