Skip to content

Commit

Permalink
Support the auth method (#100)
Browse files Browse the repository at this point in the history
* mesh-task: Update to support the auth method
* Bump default image to Consul 1.12.0
* Bump to consul-ecs-test:0.3.1 in circleci
  • Loading branch information
Paul Glass authored May 2, 2022
1 parent 33c985a commit a2d97cb
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 26 deletions.
12 changes: 6 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ orbs:
executors:
consul-ecs-test:
docker:
- image: docker.mirror.hashicorp.services/hashicorpdev/consul-ecs-test:0.3.0
- image: docker.mirror.hashicorp.services/hashicorpdev/consul-ecs-test:0.3.1
environment:
TEST_RESULTS: &TEST_RESULTS /tmp/test-results # path to where test results are saved

Expand All @@ -17,7 +17,7 @@ jobs:
# Restore go module cache if there is one
- restore_cache:
keys:
- consul-ecs-acceptance-modcache-v1-{{ checksum "test/acceptance/go.mod" }}
- consul-ecs-acceptance-modcache-v2-{{ checksum "test/acceptance/go.mod" }}

- run:
name: go mod download
Expand All @@ -26,9 +26,9 @@ jobs:

# Save go module cache if the go.mod file has changed
- save_cache:
key: consul-ecs-acceptance-modcache-v1-{{ checksum "test/acceptance/go.mod" }}
key: consul-ecs-acceptance-modcache-v2-{{ checksum "test/acceptance/go.mod" }}
paths:
- "/go/pkg/mod"
- "/home/circleci/go/pkg/mod"

# check go fmt output because it does not report non-zero when there are fmt changes
- run:
Expand Down Expand Up @@ -99,7 +99,7 @@ jobs:
# Restore go module cache if there is one
- restore_cache:
keys:
- consul-ecs-acceptance-modcache-v1-{{ checksum "test/acceptance/go.mod" }}
- consul-ecs-acceptance-modcache-v2-{{ checksum "test/acceptance/go.mod" }}

- run: mkdir -p $TEST_RESULTS

Expand All @@ -108,7 +108,7 @@ jobs:
working_directory: test/acceptance/tests
no_output_timeout: 1h
command: |
gotestsum --junitfile "$TEST_RESULTS/gotestsum-report.xml" -- ./... -p 1 -timeout 1h -v -failfast
gotestsum --junitfile "$TEST_RESULTS/gotestsum-report.xml" --format standard-verbose -- ./... -p 1 -timeout 1h -v -failfast
- store_test_results:
path: *TEST_RESULTS
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ FEATURES
* modules/dev-server: Add `consul_license` input variable to support
passing a Consul enterprise license.
[[GH-96](https://github.com/hashicorp/terraform-aws-consul-ecs/pull/96)]
* modules/mesh-task, modules/acl-controller: Support the Consul AWS IAM auth method. This requires
Consul 1.12.0+. Add `consul_http_addr`, `client_token_auth_method_name`, and
`service_token_auth_method_name` variables to `mesh-task`. Add `iam_role_path` variable to
`acl-controller`. Add an `iam:GetRole` permission to the task role. Set the tags
`consul.hashicorp.com.service-name` and `consul.hashicorp.com.namespace` on the task role.
[[GH-100](https://github.com/hashicorp/terraform-aws-consul-ecs/pull/100)]


## 0.4.1 (April 8, 2022)
Expand Down
15 changes: 10 additions & 5 deletions modules/acl-controller/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,20 @@ resource "aws_ecs_task_definition" "this" {
image = var.consul_ecs_image
essential = true
logConfiguration = var.log_configuration,
command = concat([
"acl-controller",
"-consul-client-secret-arn", aws_secretsmanager_secret.client_token.arn,
"-secret-name-prefix", var.name_prefix
command = concat(
[
"acl-controller",
"-consul-client-secret-arn", aws_secretsmanager_secret.client_token.arn,
"-secret-name-prefix", var.name_prefix
],
var.consul_partitions_enabled ? [
"-partitions-enabled",
"-partition", var.consul_partition
] : [])
] : [],
var.iam_role_path != "" ? [
"-iam-role-path", var.iam_role_path,
] : [],
)
linuxParameters = {
initProcessEnabled = true
}
Expand Down
6 changes: 6 additions & 0 deletions modules/acl-controller/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ variable "log_configuration" {
default = null
}

variable "iam_role_path" {
description = "IAM roles at this path will be permitted to login to the Consul AWS IAM auth method configured by this controller."
type = string
default = ""
}

variable "subnets" {
description = "Subnets where the controller task should be deployed. If these are private subnets then there must be a NAT gateway for image pulls to work. If these are public subnets then you must also set assign_public_ip for image pulls to work."
type = list(string)
Expand Down
2 changes: 1 addition & 1 deletion modules/dev-server/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ variable "lb_ingress_rule_security_groups" {
variable "consul_image" {
description = "Consul Docker image."
type = string
default = "public.ecr.aws/hashicorp/consul:1.11.4"
default = "public.ecr.aws/hashicorp/consul:1.12.0"
}

variable "consul_license" {
Expand Down
11 changes: 11 additions & 0 deletions modules/mesh-task/config.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@ locals {
serviceExtra = lookup(var.consul_ecs_config, "service", {})
proxyExtra = lookup(var.consul_ecs_config, "proxy", {})

consulLogin = var.acls ? {
// TODO: Switch this to `enabled = var.acls` once the auth method is fully supported.
enabled = var.service_token_auth_method_name != ""
method = var.service_token_auth_method_name
// TODO: Move this to a top-level partition field in the CONSUL_ECS_CONFIG_JSON
extraLoginFlags = var.consul_partition != "" ? ["-partition", var.consul_partition] : []
} : null

config = {
consulHTTPAddr = var.consul_http_addr
consulCACertFile = "/consul/consul-ca-cert.pem"
consulLogin = local.consulLogin
service = merge(
{
name = local.service_name
Expand Down
40 changes: 40 additions & 0 deletions modules/mesh-task/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ locals {
// Create the task role
resource "aws_iam_role" "task" {
count = local.create_task_role ? 1 : 0
path = "/ecs/"

name = "${var.family}-task"
assume_role_policy = jsonencode({
Expand All @@ -39,6 +40,44 @@ resource "aws_iam_role" "task" {
}
]
})

tags = {
"consul.hashicorp.com.service-name" = local.service_name
"consul.hashicorp.com.namespace" = var.consul_namespace
}
}

// If acls are enabled, the task role must be configured with an `iam:GetRole` permission
// to fetch itself, in order to be compatbile with the auth method.
resource "aws_iam_policy" "task" {
count = var.acls ? 1 : 0
name = "${var.family}-task"
path = "/ecs/"
description = "${var.family} mesh-task task policy"

policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:GetRole"
],
"Resource": [
"${local.task_role_arn}"
]
}
]
}
EOF
}


resource "aws_iam_role_policy_attachment" "task" {
count = var.acls ? 1 : 0
role = local.task_role_id
policy_arn = aws_iam_policy.task[count.index].arn
}

resource "aws_iam_role_policy_attachment" "additional_task_policies" {
Expand Down Expand Up @@ -73,6 +112,7 @@ resource "aws_iam_policy" "execution" {
path = "/ecs/"
description = "${var.family} mesh-task execution policy"

// TODO: Remove client and service token secrets once switched to the auth method.
policy = <<EOF
{
"Version": "2012-10-17",
Expand Down
20 changes: 17 additions & 3 deletions modules/mesh-task/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ locals {
)

secret_name = var.consul_partition != "" ? "${var.acl_secret_name_prefix}-${local.service_name}-${var.consul_namespace}-${var.consul_partition}" : "${var.acl_secret_name_prefix}-${local.service_name}"

// TODO: Remove this "feature flag" once switched over to the auth method
auth_method_enabled = var.client_token_auth_method_name != "" && var.service_token_auth_method_name != ""
}

resource "aws_secretsmanager_secret" "service_token" {
Expand Down Expand Up @@ -218,8 +221,9 @@ resource "aws_ecs_task_definition" "this" {
initProcessEnabled = true
}
portMappings = []
secrets = var.acls ? [
secrets = var.acls && !local.auth_method_enabled ? [
{
// TODO: Remove once switched to auth method
name = "CONSUL_HTTP_TOKEN",
valueFrom = "${aws_secretsmanager_secret.service_token[0].arn}:token::"
}
Expand All @@ -239,6 +243,11 @@ resource "aws_ecs_task_definition" "this" {
consul_agent_defaults_hcl = local.consul_agent_defaults_hcl
consul_agent_configuration_hcl = var.consul_agent_configuration
tls = var.tls
acls = var.acls
consul_http_addr = var.consul_http_addr
client_token_auth_method_name = var.client_token_auth_method_name
consul_partition = var.consul_partition
region = data.aws_region.current.name
}
), "\r", "")
]
Expand Down Expand Up @@ -273,8 +282,9 @@ resource "aws_ecs_task_definition" "this" {
valueFrom = var.gossip_key_secret_arn
}
] : [],
var.acls ? [
var.acls && !local.auth_method_enabled ? [
{
// TODO: Remove once switched to auth method
name = "AGENT_TOKEN",
valueFrom = "${var.consul_client_token_secret_arn}:token::"
}
Expand Down Expand Up @@ -332,6 +342,9 @@ resource "aws_ecs_task_definition" "this" {
}
]
portMappings = []
mountPoints = [
local.consul_data_mount
]
dependsOn = [
{
containerName = "consul-ecs-mesh-init"
Expand All @@ -341,8 +354,9 @@ resource "aws_ecs_task_definition" "this" {
linuxParameters = {
initProcessEnabled = true
}
secrets = var.acls ? [
secrets = var.acls && !local.auth_method_enabled ? [
{
// TODO: Remove once switched to auth method
name = "CONSUL_HTTP_TOKEN",
valueFrom = "${aws_secretsmanager_secret.service_token[0].arn}:token::"
}
Expand Down
8 changes: 8 additions & 0 deletions modules/mesh-task/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ output "execution_role_id" {
value = local.execution_role_id
}

output "task_role_arn" {
value = local.task_role_arn
}

output "execution_role_arn" {
value = local.execution_role_arn
}

output "task_tags" {
value = aws_ecs_task_definition.this.tags_all
}
Expand Down
2 changes: 1 addition & 1 deletion modules/mesh-task/templates/consul_agent_defaults.hcl.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ auto_encrypt = {
tls = true
ip_san = ["$ECS_IPV4"]
}
ca_file = "/tmp/consul-ca-cert.pem"
ca_file = "/consul/consul-ca-cert.pem"
verify_outgoing = true
%{ endif ~}

Expand Down
32 changes: 30 additions & 2 deletions modules/mesh-task/templates/consul_client_command.tpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
cp /bin/consul /bin/consul-inject/consul

ECS_IPV4=$(curl -s $ECS_CONTAINER_METADATA_URI_V4 | jq -r '.Networks[0].IPv4Addresses[0]')
ECS_TASK_META=$(curl -s $ECS_CONTAINER_METADATA_URI_V4)
ECS_IPV4=$(echo "$ECS_TASK_META" | jq -r '.Networks[0].IPv4Addresses[0]')
TASK_REGION=$(echo "$ECS_TASK_META" | jq -r .ContainerARN | cut -d':' -f4)

%{ if tls ~}
echo "$CONSUL_CACERT" > /tmp/consul-ca-cert.pem
echo "$CONSUL_CACERT" > /consul/consul-ca-cert.pem
%{ endif ~}

%{ if acls && client_token_auth_method_name != "" ~}

login() {
echo "Logging into auth method: name=${ client_token_auth_method_name }"
consul login \
-http-addr ${ consul_http_addr } \
%{ if tls ~}
-ca-file /consul/consul-ca-cert.pem \
%{ endif ~}
%{ if consul_partition != "" ~}
-partition ${ consul_partition } \
%{ endif ~}
-type aws -method ${ client_token_auth_method_name } \
-aws-region "$TASK_REGION" \
-aws-auto-bearer-token -aws-include-entity \
-token-sink-file /consul/client-token
}

while ! login; do
sleep 2
done

# This is an env var which is interpolated into the agent-defaults.hcl
export AGENT_TOKEN=$(cat /consul/client-token)
%{ endif ~}

cat << EOF > /consul/agent-defaults.hcl
Expand Down
20 changes: 19 additions & 1 deletion modules/mesh-task/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ variable "outbound_only" {
variable "consul_image" {
description = "Consul Docker image."
type = string
default = "public.ecr.aws/hashicorp/consul:1.11.4"
default = "public.ecr.aws/hashicorp/consul:1.12.0"
}

variable "consul_ecs_image" {
Expand Down Expand Up @@ -230,6 +230,24 @@ variable "retry_join" {
type = list(string)
}

variable "consul_http_addr" {
description = "Consul HTTP Address. Required when using the IAM Auth Method to obtain ACL tokens."
type = string
default = ""
}

variable "client_token_auth_method_name" {
description = "The name of the Consul Auth Method to login to for client tokens."
type = string
default = ""
}

variable "service_token_auth_method_name" {
description = "The name of the Consul Auth Method to login to for service tokens."
type = string
default = ""
}

variable "tags" {
description = "A map of tags to add to all resources."
type = map(string)
Expand Down
Loading

0 comments on commit a2d97cb

Please sign in to comment.