Skip to content

Commit

Permalink
Add: Secret injection from Secrets Manager. (#35)
Browse files Browse the repository at this point in the history
* Add secrets injection and tests

* FIX wrong IAM role ID passed to policy attachment

* Moved the resource to the more appropiate file

* Fix: consistent naming for container resources and variables
  • Loading branch information
lsc authored Aug 5, 2020
1 parent f0d85b7 commit 83d959d
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 0 deletions.
3 changes: 3 additions & 0 deletions examples/secrets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## examples/secrets

An example which shows how to inject secrets with of the module.
128 changes: 128 additions & 0 deletions examples/secrets/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# ----------------------------------------
# Create a ecs service using fargate
# ----------------------------------------
terraform {
required_version = ">= 0.12"
}

provider "aws" {
version = ">= 2.17"
region = var.region
}

data "aws_vpc" "main" {
default = true
}

data "aws_subnet_ids" "main" {
vpc_id = data.aws_vpc.main.id
}


module "fargate_alb" {
source = "telia-oss/loadbalancer/aws"
version = "3.0.0"

name_prefix = var.name_prefix
type = "application"
internal = false
vpc_id = data.aws_vpc.main.id
subnet_ids = data.aws_subnet_ids.main.ids

tags = {
environment = "dev"
terraform = "True"
}
}

resource "aws_lb_listener" "alb" {
load_balancer_arn = module.fargate_alb.arn
port = 80
protocol = "HTTP"

default_action {
target_group_arn = module.fargate.target_group_arn
type = "forward"
}
}

resource "aws_security_group_rule" "task_ingress_8000" {
security_group_id = module.fargate.service_sg_id
type = "ingress"
protocol = "tcp"
from_port = 8000
to_port = 8000
source_security_group_id = module.fargate_alb.security_group_id
}

resource "aws_security_group_rule" "alb_ingress_80" {
security_group_id = module.fargate_alb.security_group_id
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}

resource "aws_ecs_cluster" "cluster" {
name = "${var.name_prefix}-cluster"
}

resource "aws_secretsmanager_secret" "task_container_secrets" {
name = var.name_prefix
kms_key_id = var.task_container_secrets_kms_key
}

resource "aws_secretsmanager_secret_version" "task_container_secrets" {
secret_id = aws_secretsmanager_secret.task_container_secrets.id
secret_string = "Super secret and important string"
}

data "aws_secretsmanager_secret" "task_container_secrets" {
arn = aws_secretsmanager_secret.task_container_secrets.arn
}

data "aws_kms_key" "task_container_secrets" {
key_id = data.aws_secretsmanager_secret.task_container_secrets.kms_key_id
}

module "fargate" {
source = "../../"

name_prefix = var.name_prefix
vpc_id = data.aws_vpc.main.id
private_subnet_ids = data.aws_subnet_ids.main.ids
lb_arn = module.fargate_alb.arn
cluster_id = aws_ecs_cluster.cluster.id
task_container_image = "crccheck/hello-world:latest"

// public ip is needed for default vpc, default is false
task_container_assign_public_ip = true

// port, default protocol is HTTP
task_container_port = 8000

task_container_environment = {
TEST_VARIABLE = "TEST_VALUE"
}

task_container_secrets_kms_key = data.aws_kms_key.task_container_secrets.key_id

task_container_secrets = [
{
name = "TASK_SECRET"
valueFrom = aws_secretsmanager_secret_version.task_container_secrets.arn
}
]

health_check = {
port = "traffic-port"
path = "/"
}

tags = {
environment = "dev"
terraform = "True"
}
}
11 changes: 11 additions & 0 deletions examples/secrets/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "cluster_arn" {
value = aws_ecs_cluster.cluster.arn
}

output "service_arn" {
value = module.fargate.service_arn
}

output "endpoint" {
value = module.fargate_alb.dns_name
}
15 changes: 15 additions & 0 deletions examples/secrets/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
variable "name_prefix" {
type = string
default = "fargate-task-secrets-example"
}

variable "region" {
type = string
default = "eu-west-1"
}

variable "task_container_secrets_kms_key" {
type = string
description = ""
default = "alias/aws/secretsmanager"
}
9 changes: 9 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ resource "aws_iam_role_policy" "read_repository_credentials" {
policy = data.aws_iam_policy_document.read_repository_credentials.json
}

resource "aws_iam_role_policy" "read_task_container_secrets" {
name = "${var.name_prefix}-read-task-container-secrets"
role = aws_iam_role.execution.id
policy = data.aws_iam_policy_document.task_container_secrets.json
}

# ------------------------------------------------------------------------------
# IAM - Task role, basic. Users of the module will append policies to this role
# when they use the module. S3, Dynamo permissions etc etc.
Expand Down Expand Up @@ -141,6 +147,9 @@ resource "aws_ecs_task_definition" "task" {
"credentialsParameter": "${var.repository_credentials}"
},
%{~endif}
%{if length(var.task_container_secrets) > 0~}
"secrets": ${jsonencode(var.task_container_secrets)},
%{~endif}
"essential": true,
"portMappings": [
{
Expand Down
19 changes: 19 additions & 0 deletions policies.tf
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,22 @@ data "aws_iam_policy_document" "read_repository_credentials" {
}
}

data "aws_kms_key" "task_container_secrets_key" {
key_id = var.task_container_secrets_kms_key
}

data "aws_iam_policy_document" "task_container_secrets" {
statement {
effect = "Allow"

resources = concat(
[data.aws_kms_key.task_container_secrets_key.arn],
[for i in var.task_container_secrets : i["valueFrom"]]
)
actions = [
"secretsmanager:GetSecretValue",
"kms:Decrypt",
]
}
}

21 changes: 21 additions & 0 deletions test/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,27 @@ func TestModule(t *testing.T) {
},
},
},
{
description: "task secrets example",
directory: "../examples/secrets",
name: fmt.Sprintf("fargate-secrets-test-%s", random.UniqueId()),
region: "eu-west-1",
expected: ecs.Expectations{
DesiredTaskCount: 1,
TaskCPU: 256,
TaskMemory: 512,
NetworkMode: "awsvpc",
ContainerImage: "crccheck/hello-world:latest",
ContainerEnvironment: map[string]string{
"TEST_VARIABLE": "TEST_VALUE",
},
HTTPGetResponse: []string{
`Hello World`,
`~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~`,
`\______ o _,/`,
},
},
},
}

for _, tc := range tests {
Expand Down
12 changes: 12 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ variable "container_name" {
type = string
}

variable "task_container_secrets" {
type = list(object({ name = string, valueFrom = string }))
default = []
}

variable "task_container_secrets_kms_key" {
type = string
description = ""
default = "alias/aws/secretsmanager"
}

variable "vpc_id" {
description = "The VPC ID."
type = string
Expand Down Expand Up @@ -133,6 +144,7 @@ variable "repository_credentials" {
type = string
}


variable "repository_credentials_kms_key" {
default = "alias/aws/secretsmanager"
description = "key id, key ARN, alias name or alias ARN of the key that encrypted the repository credentials"
Expand Down

0 comments on commit 83d959d

Please sign in to comment.