Skip to content

Commit

Permalink
support AWS SSM parameters and secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
AJ Steers committed Sep 23, 2020
1 parent 84ceec3 commit 79682b9
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 42 deletions.
4 changes: 2 additions & 2 deletions catalog/aws/singer-taps/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ module "ecs_tap_sync_task" {
environment_secrets = merge(
{
for k, v in local.taps_specs[count.index].secrets :
"${local.tap_env_prefix[count.index]}${k}" => length(split(v, ":")) > 1 ? v : "${v}:${k}"
"${local.tap_env_prefix[count.index]}${k}" => length(split(":", v)) > 1 ? v : "${v}:${k}"
},
{
for k, v in local.target.secrets :
"${local.target_env_prefix}${k}" => length(split(v, ":")) > 1 ? v : "${v}:${k}"
"${local.target_env_prefix}${k}" => length(split(":", v)) > 1 ? v : "${v}:${k}"
}
)
schedules = [
Expand Down
2 changes: 1 addition & 1 deletion catalog/aws/singer-taps/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Singer Taps Summary:
- Run sync via State Machine:
${join("\n - ", [
for sf in module.step_function :
"aws stepfunctions start-execution --state-machine-arn ${sf.state_machine_arn}"
"aws stepfunctions start-execution --state-machine-arn ${sf.state_machine_arn} --region ${var.environment.aws_region}"
])}
EOF
Expand Down
73 changes: 44 additions & 29 deletions components/aws/ecs-task/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ data "aws_iam_policy" "CloudWatchLogsFullAccess" {
data "aws_iam_policy" "SecretsManagerReadWrite" {
arn = "arn:aws:iam::aws:policy/SecretsManagerReadWrite"
}
data "aws_iam_policy" "AmazonSSMReadOnlyAccess" {
arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
}

##########################
### ECS Execution Role ###
Expand Down Expand Up @@ -46,35 +49,6 @@ resource "aws_iam_role" "ecs_execution_role" {
}
EOF
}

####
/*
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
*/
####


resource "aws_iam_role_policy_attachment" "ecs_role_policy-ecr" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = data.aws_iam_policy.AmazonEC2ContainerRegistryReadOnly.arn
Expand All @@ -87,10 +61,19 @@ resource "aws_iam_role_policy_attachment" "ecs_role_policy-secrets" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = data.aws_iam_policy.SecretsManagerReadWrite.arn
}
resource "aws_iam_role_policy_attachment" "ecs_role_policy-parameters" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = data.aws_iam_policy.AmazonSSMReadOnlyAccess.arn
}
resource "aws_iam_role_policy_attachment" "ecs_role_policy-kms" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = aws_iam_policy.allow_kms_decrypt.arn
}
resource "aws_iam_role_policy_attachment" "ecs_role_policy-handoff" {
role = aws_iam_role.ecs_execution_role.name
policy_arn = aws_iam_policy.ecs_policy_handoff.id
}

resource "aws_iam_policy" "ecs_policy_handoff" {
name = "${var.name_prefix}ecs_task-policy_handoff-${random_id.suffix.dec}"
policy = <<EOF
Expand Down Expand Up @@ -186,3 +169,35 @@ resource "aws_iam_role_policy_attachment" "permitted_s3_buckets_policy_attachmen
role = aws_iam_role.ecs_task_role.name
policy_arn = aws_iam_policy.permitted_s3_buckets_policy[0].arn
}

resource "aws_iam_policy" "allow_kms_decrypt" {
policy = <<EOF
{
"Id": "AllowsKmsKeyAccess",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowUseOfKey",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:*::alias/*"
},
{
"Sid": "listKeys",
"Effect": "Allow",
"Action": [
"kms:ListKeys",
"kms:ListAliases"
],
"Resource": "*"
}
]
}
EOF
}
23 changes: 13 additions & 10 deletions components/aws/secrets-manager/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ resource "random_id" "suffix" { byte_length = 2 }
locals {
secrets_names = toset(keys(var.secrets_map))
existing_secrets_ids_map = {
# filter existing map for secrets already stored in AWS secrets manager
# filter existing map for secrets already stored in AWS Secrets Manager or AWS SSM
for secret_name, location in var.secrets_map :
secret_name => location
if replace(secret_name, ":secretsmanager:", "") != secret_name
if replace(location, "arn:aws:", "") != secret_name
}
new_yaml_secrets_map = {
# raw secrets from JSON or YAML which have not yet been stored in AWS secrets manager
Expand Down Expand Up @@ -52,22 +52,25 @@ locals {
), ".json", ""), ".yml", ""), ".yaml", "") == lower(location)
}
new_secrets_map = merge(local.new_yaml_secrets_map, local.new_aws_creds_secrets_map)
merged_secrets_map = merge(
local.existing_secrets_ids_map, {
for created_name in keys(local.new_secrets_map) :
created_name => aws_secretsmanager_secret.secrets[created_name].id
}
)
}

resource "aws_secretsmanager_secret" "secrets" {
for_each = toset(keys(local.new_secrets_map))
for_each = var.use_parameter_store ? toset([]) : toset(keys(local.new_secrets_map))
name = "${var.name_prefix}${each.key}-${random_id.suffix.dec}"
kms_key_id = var.kms_key_id
}

resource "aws_secretsmanager_secret_version" "secrets_value" {
for_each = local.new_secrets_map
for_each = var.use_parameter_store ? {} : local.new_secrets_map
secret_id = aws_secretsmanager_secret.secrets[each.key].id
secret_string = each.value
}

resource "aws_ssm_parameter" "secrets" {
for_each = var.use_parameter_store == false ? {} : local.new_secrets_map
name = "${var.name_prefix}${random_id.suffix.dec}/${each.key}"
description = "Stored using Terraform"
type = "SecureString"
value = each.value
tags = var.resource_tags
}
9 changes: 9 additions & 0 deletions components/aws/secrets-manager/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
locals {
merged_secrets_map = merge(
local.existing_secrets_ids_map, {
for created_name in keys(local.new_secrets_map) :
created_name => var.use_parameter_store ? aws_ssm_parameter.secrets[created_name].id : aws_secretsmanager_secret.secrets[created_name].id
}
)
}

output "summary" {
description = "Summary of resources created by this module."
value = <<EOF
Expand Down
7 changes: 7 additions & 0 deletions components/aws/secrets-manager/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,20 @@ A map between secret names and their locations.
The location can be:
- ID of an existing Secrets Manager secret (`arn:aws:secretsmanager:...`)<br>
- ID of an existing Systems Manager Parameter Store secret (`arn:aws:ssm:...`)<br>
- String with the local secrets file name and property names separated by `:` (`path/to/file.yml:my_key_name`)."
EOF
type = map(string)
default = {}
}

variable "use_parameter_store" {
description = "Optional. True to use AWS Systems Manager Parameter Store (free) instead of AWS Secrets Manager ($0.40 per secret per month)."
type = bool
default = true
}

variable "kms_key_id" {
description = "Optional. A valid KMS key ID to use for encrypting the secret values. If omitted, the default KMS key will be applied."
# type = string
Expand Down

0 comments on commit 79682b9

Please sign in to comment.