docs: Update ECS docs for IAM auth method support (#13222)

This commit is contained in:
Paul Glass 2022-06-23 16:42:40 -05:00 committed by GitHub
parent ea0966ff5e
commit 02ee123b7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 758 additions and 280 deletions

View File

@ -23,8 +23,10 @@ The following diagram shows the main components of the Consul architecture when
for Consul and Envoy.
1. **Health Syncing:** Optionally, an additional `health-sync` container can be included in a task to sync health statuses
from ECS into Consul.
1. **ACL Controller:** Automatically provisions Consul ACL tokens for Consul clients and service mesh services
in an ECS Cluster.
1. **ACL Controller:** The ACL controller is responsible for automating configuration and cleanup in the Consul servers.
The ACL controller will automatically configure the [AWS IAM Auth Method](/docs/security/acl/auth-methods/aws-iam), and cleanup
unused ACL tokens from Consul. When using Consul Enterprise namespaces, the ACL controller will automatically create Consul
namespaces for ECS tasks.
For more information about how Consul works in general, see Consul's [Architecture Overview](/docs/architecture).
@ -39,15 +41,27 @@ This diagram shows the timeline of a task starting up and all its containers:
</ImageConfig>
- **T0:** ECS starts the task. The `consul-client` and `mesh-init` containers start:
- `consul-client` uses the `retry-join` option to join the Consul cluster
- `mesh-init` registers the service for the current task and its sidecar proxy with
Consul. It runs `consul connect envoy -bootstrap` to generate Envoys
bootstrap JSON file and write it to a shared volume. `mesh-init` exits after completing these operations.
- `consul-client` does the following:
- If ACLs are enabled, a startup script runs a `consul login` command to obtain a
token from the AWS IAM auth method for the Consul client. This token has `node:write`
permissions.
- It uses the `retry-join` option to join the Consul cluster.
- `mesh-init` does the following:
- If ACLs are enabled, mesh-init runs a `consul login` command to obtain a token from
the AWS IAM auth method for the service registration. This token has `service:write`
permissions for the service and its sidecar proxy. This token is written to a shared
volume for use by the `health-sync` container.
- It registers the service for the current task and its sidecar proxy with Consul.
- It runs `consul connect envoy -bootstrap` to generate Envoys bootstrap JSON file and
writes it to a shared volume.
- **T1:** The following containers start:
- The `sidecar-proxy` container starts and runs Envoy by executing `envoy -c <path-to-bootstrap-json>`.
- If applicable, the `health-sync` container syncs health checks from ECS to Consul (see [ECS Health Check Syncing](#ecs-health-check-syncing)).
- **T2:** The `sidecar-proxy` container is marked as healthy by ECS. It uses a health check that detects if its public listener port is open. At this time, your application containers are started since all Consul machinery is ready to service requests. The only running containers are `consul-client`, `sidecar-proxy`, and your application container(s).
- `sidecar-proxy` starts using a custom entrypoint command, `consul-ecs envoy-entrypoint`.
The entrypoint command starts Envoy by running `envoy -c <path-to-bootstrap-json>`.
- `health-sync` starts if ECS health checks are defined or if ACLs are enabled. It syncs health
checks from ECS to Consul (see [ECS Health Check Syncing](#ecs-health-check-syncing)).
- **T2:** The `sidecar-proxy` container is marked as healthy by ECS. It uses a health check that
detects if its public listener port is open. At this time, your application containers are started
since all Consul machinery is ready to service requests.
## Task Shutdown
@ -62,10 +76,19 @@ This diagram shows an example timeline of a task shutting down:
- **T0**: ECS sends a TERM signal to all containers. Each container reacts to the TERM signal:
- `consul-client` begins to gracefully leave the Consul cluster.
- `health-sync` stops syncing health status from ECS into Consul checks.
- `sidecar-proxy` ignores the TERM signal and continues running until the `user-app` container exits. This allows the application container to continue making outgoing requests through the proxy to the mesh.
- `user-app` exits if it is not configured to ignore the TERM signal. The `user-app` container will continue running if it is configured to ignore the TERM signal.
- `sidecar-proxy` ignores the TERM signal and continues running until the `user-app` container
exits. The custom entrypoint command, `consul-ecs envoy-entrypoint`, monitors the local ECS task
metadata. It waits until the `user-app` container has exited before terminating Envoy. This
enables the application to continue making outgoing requests through the proxy to the mesh for
graceful shutdown.
- `user-app` exits if it is not configured to ignore the TERM signal. The `user-app` container
will continue running if it is configured to ignore the TERM signal.
- **T1**:
- `health-sync` updates its Consul checks to critical status and exits. This ensures this service instance is marked unhealthy.
- `health-sync` does the following:
- It updates its Consul checks to critical status and exits. This ensures this service instance is marked unhealthy.
- If ACLs are enabled, it runs `consul logout` for the two tokens created by the `consul-client` and `mesh-init` containers.
This removes those tokens from Consul. If `consul logout` fails for some reason, the ACL controller will remove the tokens
after the task has stopped.
- `sidecar-proxy` notices the `user-app` container has stopped and exits.
- **T2**: `consul-client` finishes gracefully leaving the Consul datacenter and exits.
- **T3**:
@ -73,45 +96,154 @@ This diagram shows an example timeline of a task shutting down:
- Updates about this task have reached the rest of the Consul cluster, so downstream proxies have been updated to stopped sending traffic to this task.
- **T4**: At this point task shutdown should be complete. Otherwise, ECS will send a KILL signal to any containers still running. The KILL signal cannot be ignored and will forcefully stop containers. This will interrupt in-progress operations and possibly cause errors.
## ACL Tokens
Two types of ACL tokens are required by ECS tasks:
* **Client tokens:** used by the `consul-client` containers to join the Consul cluster
* **Service tokens:** used by sidecar containers for service registration and health syncing
With Consul on ECS, these tokens are obtained dynamically when a task starts up by logging
in via Consul's AWS IAM auth method.
### Consul Client Token
Consul client tokens require `node:write` for any node name, which is necessary because the Consul node
names on ECS are not known until runtime.
### Service Token
Service tokens are associated with a [service identity](/docs/security/acl#service-identities).
The service identity includes `service:write` permissions for the service and sidecar proxy.
## AWS IAM Auth Method
Consul's [AWS IAM Auth Method](/docs/security/acl/auth-methods/aws-iam) is used by ECS tasks to
automatically obtain Consul ACL tokens. When a service mesh task on ECS starts up, it runs two
`consul login` commands to obtain a client token and a service token via the auth method. When the
task stops, it attempts two `consul logout` commands in order to destroy these tokens.
During a `consul login`, the [task's IAM
role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) is presented
to the AWS IAM auth method on the Consul servers. The role is validated with AWS. If the role is
valid, and if the auth method trusts the IAM role, then the role is permitted to login. A new Consul
ACL token is created and [Binding Rules](/docs/security/acl/auth-methods#binding-rules) associate
permissions with the newly created token. These permissions are mapped to the token based on the IAM
role details. For example, tags on the IAM role are used to specify the service name and the
Consul Enterprise namespace to be associated with a service token that is created by a successful
login to the auth method.
### Task IAM Role
The following configuration is required for the task IAM role in order to be compatible with the
auth method. When using Terraform, the `mesh-task` module creates the task role with this
configuration by default.
* A scoped `iam:GetRole` permission must be included on the IAM role, enabling the role to fetch
details about itself.
* A `consul.hashicorp.com.service-name` tag on the IAM role must be set to the Consul service name.
* <EnterpriseAlert inline /> A <code>consul.hashicorp.com.namespace</code> tag must be set on the
IAM role to the Consul Enterprise namespace of the Consul service for the task.
Task IAM roles should not typically be shared across task families. Since a task family represents a
single Consul service, and since the task role must include the Consul service name, one task role
is required for each task family when using the auth method.
### Security
The auth method relies on the configuration of AWS resources, such as IAM roles, IAM policies, and
ECS tasks. If these AWS resources are misconfigured or if the account has loose access controls,
then the security of your service mesh may be at risk.
Any entity in your AWS account with the ability to obtain credentials for an IAM role could potentially
obtain a Consul ACL token and impersonate a Consul service. The `mesh-task` Terraform module
mitigates against this concern by creating the task role with an `AssumeRolePolicyDocument` that
allows only the AWS ECS service to assume the task role. By default, other entities are unable
to obtain credentials for task roles, and are unable to abuse the AWS IAM auth method to obtain
Consul ACL tokens.
However, other entities in your AWS account with the ability to create or modify IAM roles can
potentially circumvent this. For example, if they are able to create an IAM role with the correct
tags, they can obtain a Consul ACL token for any service. Or, if they can pass a role to an ECS task
and start an ECS task, they can use the task to obtain a Consul ACL token via the auth method.
The IAM policy actions `iam:CreateRole`, `iam:TagRole`, `iam:PassRole`, and `sts:AssumeRole` can be
used to restrict these capabilities in your AWS account and improve security when using the AWS IAM
auth method. See the [AWS
documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) to learn how
to restrict these permissions in your AWS account.
## ACL Controller
The ACL controller performs the following operations:
* Provisions Consul ACL tokens for Consul clients and service mesh services.
* Manages Consul admin partitions and namespaces.
The ACL controller performs the following operations on the Consul servers:
### Automatic ACL Token Provisioning
* Configures the Consul AWS IAM auth method.
* Monitors tasks in ECS cluster where the controller is running.
* Cleans up unused Consul ACL tokens created by tasks in this cluster.
* <EnterpriseAlert inline /> Manages Consul admin partitions and namespaces.
Consul ACL tokens secure communication between agents and services.
The following containers in a task require an ACL token:
### Auth Method Configuration
- `consul-client`: The Consul client uses a token to authorize itself with Consul servers.
All `consul-client` containers share the same token.
- `mesh-init`: The `mesh-init` container uses a token to register the service with Consul.
This token is unique for the Consul service, and is shared by instances of the service.
The ACL controller is responsible for configuring the AWS IAM auth method. The following resources
are created by the ACL controller when it starts up:
The ACL controller automatically creates ACL tokens for mesh-enabled tasks in an ECS cluster.
The `acl-controller` Terraform module creates the ACL controller task. The controller creates the
ACL token used by `consul-client` containers at startup and then watches for tasks in the cluster. It checks tags
to determine if the task is mesh-enabled. If so, it creates the service ACL token for the task, if the
token does not yet exist.
* **Client role**: The controller creates the Consul (not IAM) role and policy used for client
tokens if these do not exist. This policy has `node:write` permissions to enable Consul clients to
join the Consul cluster.
* **Auth method for client tokens**: One instance of the AWS IAM auth method is created for client
tokens, if it does not exist. A binding rule is configured that attaches the Consul client role to each
token created during a successful login to this auth method instance.
* **Auth method for service tokens**: One instance of the AWS IAM auth method is created for service
tokens, if it does not exist:
* A binding rule is configured to attach a [service identity](/docs/security/acl#service-identities)
to each token created during a successful login to this auth method instance. The service name for
this service identity is taken from the tag, `consul.hashicorp.com.service-name`, on the IAM role
used to log in.
* <EnterpriseAlert inline /> A namespace binding rule is configured to create service tokens in
the namespace specified by the tag, <code>consul.hashicorp.com.namespace</code>, on the IAM
role used to log in.
The ACL controller stores all ACL tokens in AWS Secrets Manager, and tasks are configured to pull these
tokens from AWS Secrets Manager when they start.
The ACL controller configures both instances of the auth method to permit only certain IAM roles to login,
by setting the [`BoundIAMPrincipalARNs`](/docs/security/acl/auth-methods/aws-iam#boundiamprincipalarns)
field of the AWS IAM auth method as follows:
* By default, the only IAM roles permitted to log in must have an ARN matching the pattern,
`arn:aws:iam::<ACCOUNT>:role/consul-ecs/*`. This allows IAM roles at the role path `/consul-ecs/`
to log in, and only those IAM roles in the same AWS account where the ACL controller is running.
* The role path can be changed by setting the `iam_role_path` input variable for the `mesh-task` and
`acl-controller` modules, or by passing the `-iam-role-path` flag to the `consul-ecs
acl-controller` command.
* Each instance of the auth method is shared by ACL controllers in the same Consul datacenter. Each
controller updates the auth method, if necessary, to include additional entries in the
`BoundIAMPrincipalARNs` list. This enables the use of the auth method with ECS clusters in
different AWS accounts, for example. This does not apply when using Consul Enterprise admin
partitions because auth method instances are not shared by multiple controllers in that case.
### Task Monitoring
After startup, the ACL controller monitors tasks in the same ECS cluster where the ACL controller is
running in order to discover newly running tasks and tasks that have stopped.
The ACL controller cleans up tokens created by `consul login` for tasks that are no longer running.
Normally, each task attempts `consul logout` commands when the task stops to destroy its tokens.
However, in unstable conditions the `consul logout` command may fail to clean up a token.
The ACL controller runs continually to ensure those unused tokens are soon removed.
### Admin Partitions and Namespaces<EnterpriseAlert inline />
When [admin partitions and namespaces](/docs/ecs/enterprise#admin-partitions-and-namespaces) are enabled,
the ACL controller is assigned to its configured admin partition. The ACL controller provisions ACL
tokens for tasks in a single admin partition and supports one ACL controller instance per ECS
the ACL controller is assigned to its configured admin partition. It supports one ACL controller instance per ECS
cluster. This results in an architecture with one admin partition per ECS cluster.
The ACL controller automatically performs the following actions:
* Creates its admin partition at startup if it does not exist.
* Inspects ECS task tags for the task's intended partition and namespace.
The ACL controller ignores tasks that do not match the `partition` tag.
When admin partitions and namespace are enabled, the ACL controller performs the following
additional actions:
* At startup, creates its assigned admin partition if it does not exist.
* Inspects task tags for new ECS tasks to discover the task's intended partition
and namespace. The ACL controller ignores tasks with a partition tag that does not match the
controller's assigned partition.
* Creates namespaces when tasks start up. Namespaces are only created if they do not exist.
* Provisions ACL tokens and ACL policies that are scoped to the applicable admin partition and namespace.
* Provision ACL tokens that allow services to communicate with upstreams across admin partitions and namespaces.
* Creates auth method instances for client and service tokens in controller's assigned admin partition.
## ECS Health Check Syncing
@ -121,6 +253,5 @@ If the following conditions apply, ECS health checks automatically sync with Con
* have ECS `healthChecks`
* are not configured with native Consul health checks
The `mesh-init` container creates a TTL health check for
every container that fits these criteria and the `health-sync` container ensures
that the ECS and Consul health checks remain in sync.
The `mesh-init` container creates a TTL health check for every container that fits these criteria
and the `health-sync` container ensures that the ECS and Consul health checks remain in sync.

View File

@ -44,9 +44,109 @@ These are the top-level fields for the Consul ECS configuration format.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `bootstrapDir` | `string` | required | The directory at which to mount the shared volume where Envoy bootstrap configuration is written by `consul-ecs mesh-init`. |
| `consulCACertFile` | `string` | optional | The file path of the Consul server CA certificate. |
| `consulHTTPAddr` | `string` | optional | The HTTP(S) URL of the Consul server. Required when `authMethod.enabled` is set |
| [`consulLogin`](#consullogin) | `object` | optional | Configuration for logging into the AWS IAM auth method. |
| [`gateway`](#gateway) | `object` | optional | Configuration for the gateway proxy registration. |
| `healthSyncContainers` | `array` | optional | The names of containers that will have health check status synced from ECS into Consul. Cannot be specified with `service.checks`. |
| `logLevel` | `string` | optional | Sets the log level for the `consul-ecs mesh-init` and `consul-ecs health-sync` commands. Defaults to `INFO`. Must be one of `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, or `null`. |
| [`proxy`](#proxy) | `object` | optional | Configuration for the sidecar proxy registration with Consul. |
| [`service`](#service) | `object` | required | Configuration for Consul service registration. |
| [`service`](#service) | `object` | optional | Configuration for Consul service registration. |
# `consulLogin`
Configuration for logging into the AWS IAM auth method.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `enabled` | `boolean` | optional | Enables logging into Consul's AWS IAM auth method to obtain an ACL token. The auth method must be configured on the Consul server and the ECS task role must be trusted by the auth method. After logging in, the token is written to the file `<bootstrapDir>/service-token`. |
| `extraLoginFlags` | `array` | optional | Additional CLI flags to pass to the `consul login` command. These are appended to the command `consul login -type aws -method <name> -token-sink-file <file> -aws-auto-bearer-token -aws-include-identity`. |
| `includeEntity` | `boolean` | optional | Adds the `-aws-include-entity` flag to the `consul login` command. Defaults to `true`. Set to `false` to remove the flag from the command. The `-aws-include-entity` flag should only be passed if the Consul AWS IAM auth method is configured with `EnableIAMEntityDetails=true`. |
| `method` | `string` | optional | The name of Consul auth method. This is passed as the `-method` option to the `consul login` command. Defaults to `iam-ecs-service-token`. |
# `gateway`
Configuration for the gateway proxy registration.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `kind` | `string` | required | Specifies the type of gateway to register. Must be `mesh-gateway`. |
| [`lanAddress`](#gateway-lanaddress) | `object` | optional | LAN address and port for the gateway. If not specified, defaults to the task/node address. |
| `meta` | `object` | optional | Key-value pairs of metadata to include for the gateway. |
| `name` | `string` | optional | The name the gateway will be registered as in Consul. Defaults to the Task family name. |
| `namespace` | `string` | optional | <EnterpriseAlert inline /> Consul namespace in which the gateway will be registered. |
| `partition` | `string` | optional | <EnterpriseAlert inline /> Consul admin partition in which the gateway will be registered. |
| [`proxy`](#gateway-proxy) | `object` | optional | Object that contains the proxy parameters. |
| `tags` | `array` | optional | List of string values that can be used to add labels to the gateway. |
| [`wanAddress`](#gateway-wanaddress) | `object` | optional | WAN address and port for the gateway. If not specified, defaults to the task/node address. |
# `gateway.lanAddress`
LAN address and port for the gateway. If not specified, defaults to the task/node address.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `address` | `string` | optional | |
| `port` | `integer` | optional | |
# `gateway.proxy`
Object that contains the proxy parameters.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `config` | `object` | optional | |
# `gateway.wanAddress`
WAN address and port for the gateway. If not specified, defaults to the task/node address.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `address` | `string` | optional | |
| `port` | `integer` | optional | |
# `proxy`
Configuration for the sidecar proxy registration with Consul.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `config` | `object` | optional | Object value that specifies an opaque JSON configuration. The JSON is stored and returned along with the service instance when called from the API. |
| [`meshGateway`](#proxy-meshgateway) | `object` | optional | Specifies the mesh gateway configuration for the proxy. |
| [`upstreams`](#proxy-upstreams) | `array` | optional | The list of the upstream services that the proxy should create listeners for. |
# `proxy.meshGateway`
Specifies the mesh gateway configuration for the proxy.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `mode` | `string` | required | Specifies how upstreams with a remote destination datacenter are resolved. Must be one of `none`, `local`, or `remote`. |
# `proxy.upstreams`
The list of the upstream services that the proxy should create listeners for. Each `upstream` object may contain the following fields.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `config` | `object` | optional | Specifies opaque configuration options that will be provided to the proxy instance for the upstream. |
| `datacenter` | `string` | optional | Specifies the datacenter to issue the discovery query to. |
| `destinationName` | `string` | required | Specifies the name of the upstream service or prepared query to route the service mesh to. |
| `destinationNamespace` | `string` | optional | <EnterpriseAlert inline /> Specifies the namespace containing the upstream service. |
| `destinationPartition` | `string` | optional | <EnterpriseAlert inline /> Specifies the name of the admin partition containing the upstream service. |
| `destinationType` | `string` | optional | Specifies the type of discovery query the proxy should use for finding service mesh instances. Must be one of `service`, `prepared_query`, or `null`. |
| `localBindAddress` | `string` | optional | Specifies the address to bind a local listener to. |
| `localBindPort` | `integer` | required | Specifies the port to bind a local listener to. The application will make outbound connections to the upstream from the local port. |
| [`meshGateway`](#proxy-upstreams-meshgateway) | `object` | optional | Specifies the mesh gateway configuration for the proxy for this upstream. |
## `proxy.upstreams.meshGateway`
Specifies the mesh gateway configuration for the proxy for this upstream.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `mode` | `string` | required | Specifies how the upstream with a remote destination datacenter gets resolved. Must be one of `none`, `local`, or `remote`. |
# `service`
@ -58,15 +158,15 @@ Configuration for Consul service registration.
| `enableTagOverride` | `boolean` | optional | Determines if the anti-entropy feature for the service is enabled |
| `meta` | `object` | optional | Key-value pairs of metadata to include for the Consul service. |
| `name` | `string` | optional | The name the service will be registered as in Consul. Defaults to the Task family name if empty or null. |
| `namespace` | `string` | optional | The Consul namespace where the service will be registered [Consul Enterprise]. |
| `partition` | `string` | optional | The Consul admin partition where the service will be registered [Consul Enterprise]. |
| `namespace` | `string` | optional | <EnterpriseAlert inline /> The Consul namespace where the service will be registered. |
| `partition` | `string` | optional | <EnterpriseAlert inline /> The Consul admin partition where the service will be registered. |
| `port` | `integer` | required | Port the application listens on, if any. |
| `tags` | `array` | optional | List of string values that can be used to add service-level labels. |
| [`weights`](#service-weights) | `object` | optional | Configures the weight of the service in terms of its DNS service (SRV) response. |
# `service.checks`
Defines the Consul checks for the service. Each check may contain these fields.
Defines the Consul checks for the service. Each `check` object may contain the following fields.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
@ -89,11 +189,11 @@ Defines the Consul checks for the service. Each check may contain these fields.
| `status` | `string` | optional | Specifies the initial status the health check. Must be one of `passing`, `warning`, `critical`, `maintenance`, or `null`. |
| `successBeforePassing` | `integer` | optional | Specifies the number of consecutive successful results required before check status transitions to passing. |
| `tcp` | `string` | optional | Specifies this is a TCP check. Must be an IP/hostname plus port to which a TCP connection is made every `interval`. |
| `udp` | `string` | optional | Specifies this is a UDP check. Must be an IP/hostname plus port to which UDP datagrams are sent every `interval`. |
| `timeout` | `string` | optional | Specifies a timeout for outgoing connections. Applies to script, HTTP, TCP, UDP, and gRPC checks. Must be a duration string, such as `10s` or `5m`. |
| `tlsServerName` | `string` | optional | Specifies an optional string used to set the SNI host when connecting via TLS. |
| `tlsSkipVerify` | `boolean` | optional | Specifies if the certificate for an HTTPS check should not be verified. |
| `ttl` | `string` | optional | Specifies this is a TTL check. Must be a duration string, such as `10s` or `5m`. |
| `udp` | `string` | optional | Specifies this is a UDP check. Must be an IP/hostname plus port to which UDP datagrams are sent every `interval`. |
# `service.weights`
@ -104,45 +204,3 @@ Configures the weight of the service in terms of its DNS service (SRV) response.
| `passing` | `integer` | required | Weight for the service when its health checks are passing. |
| `warning` | `integer` | required | Weight for the service when it has health checks in `warning` status. |
# `proxy`
Configuration for the sidecar proxy registration with Consul.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `config` | `object` | optional | Object value that specifies an opaque JSON configuration. The JSON is stored and returned along with the service instance when called from the API. |
| [`meshGateway`](#proxy-meshgateway) | `object` | optional | Specifies the mesh gateway configuration for the proxy. |
| [`upstreams`](#proxy-upstreams) | `array` | optional | The list of the upstream services that the proxy should create listeners for. |
# `proxy.upstreams`
The list of the upstream services that the proxy should create listeners for. Each upstream may contain these fields.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `config` | `object` | optional | Specifies opaque configuration options that will be provided to the proxy instance for the upstream. |
| `datacenter` | `string` | optional | Specifies the datacenter to issue the discovery query to. |
| `destinationName` | `string` | required | Specifies the name of the upstream service or prepared query to route the service mesh to. |
| `destinationNamespace` | `string` | optional | Specifies the namespace containing the upstream service [Consul Enterprise]. |
| `destinationPartition` | `string` | optional | Specifies the name of the admin partition containing the upstream service [Consul Enterprise]. |
| `destinationType` | `string` | optional | Specifies the type of discovery query the proxy should use for finding service mesh instances. Must be one of `service`, `prepared_query`, or`null`. |
| `localBindAddress` | `string` | optional | Specifies the address to bind a local listener to. |
| `localBindPort` | `integer` | required | Specifies the port to bind a local listener to. The application will make outbound connections to the upstream from the local port. |
| [`meshGateway`](#proxy-upstreams-meshgateway) | `object` | optional | Specifies the mesh gateway configuration for the proxy for this upstream. |
## `proxy.upstreams.meshGateway`
Specifies the mesh gateway configuration for the proxy for this upstream.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `mode` | `string` | required | Specifies how the upstream with a remote destination datacenter gets resolved. Must be one of `none`, `local`, or`remote`. |
# `proxy.meshGateway`
Specifies the mesh gateway configuration for the proxy.
| Field | Type | Required | Description |
| ----- | ---- | -------- | ----------- |
| `mode` | `string` | required | Specifies how upstreams with a remote destination datacenter get resolved. Must be one of `none`, `local`, or`remote`. |

View File

@ -26,11 +26,10 @@ module "my_task" {
## Licensing
~> **Warning:** Consul Enterprise is currently only fully supported when [ACLs are enabled](/docs/ecs/production-installation#deploy-acl-controller).
~> **Warning:** Consul Enterprise is currently only fully supported when [ACLs are enabled](/docs/ecs/terraform/secure-configuration).
Consul Enterprise [requires a license](/docs/enterprise/license/overview). If running
Consul on ECS with [ACLs enabled](/docs/ecs/production-installation#deploy-acl-controller), the license
will be automatically pulled down from Consul servers.
Consul on ECS with ACLs enabled, the license will be automatically pulled down from Consul servers.
Currently there is no capability for specifying the license when ACLs are disabled so if you wish to
run Consul Enterprise clients then you must enable ACLs.
@ -68,8 +67,9 @@ Consul on ECS supports [admin partitions](/docs/enterprise/admin-partitions) and
- `mesh-task` must use a Consul Enterprise client image.
- `gateway-task` must use a Consul Enterprise client image.
The ACL controller automatically manages ACL policies and token provisioning for clients and services on the service mesh.
It also creates admin partitions and namespaces if they do not already exist.
The ACL controller manages configuration of the AWS IAM auth method on the Consul servers. It
ensures unused tokens created by tasks are cleaned up. It also creates admin partitions and
namespaces if they do not already exist.
-> **NOTE:** The ACL controller does not delete admin partitions or namespaces once they are created.

View File

@ -7,48 +7,28 @@ description: >-
# Install the ACL Controller
This topic describes how to manually deploy the ACL controller to [automatically provision ACL tokens](/docs/ecs/architecture#automatic-acl-token-provisioning) for Consul on ECS.
If you are using Terraform, refer to the [Terraform Secure Configuration](/docs/ecs/terraform/secure-configuration) page to deploy the ACL controller.
This topic describes how to manually deploy the ACL controller, which will automatically configure the [AWS IAM Auth Method](/docs/security/acl/auth-methods/aws-iam). If you are using Terraform, refer to the [Terraform Secure Configuration](/docs/ecs/terraform/secure-configuration) page to deploy the ACL controller.
## Prerequisites
* Your application tasks must include certain tags to be compatible with the ACL controller.
Refer to the [Task Tags](/docs/ecs/manual/install#task-tags) section of the installation page.
* You should be familiar with configuring Consul's secure features, including how to create ACL tokens and policies. Refer to the following [Learn Guides](https://learn.hashicorp.com/collections/consul/security) for an introduction and the [ACL system](/docs/security/acl) documentation for more information.
* You should be familiar with configuring Consul's secure features, including how to create ACL tokens and policies. Refer to the [Learn Guides about Consul Security](https://learn.hashicorp.com/collections/consul/security) for an introduction and the [ACL system](/docs/security/acl) documentation for more information.
* If you are using Consul with multiple ECS clusters, each cluster requires its own instance of the ACL controller.
## Set Up Secrets
The ACL controller supports managing secrets in AWS Secrets Manager.
Before deploying the ACL controller for the first time, you must [store the following secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html) from Consul in AWS Secrets Manager.
Before deploying the ACL controller for the first time, you must [create the following secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html) from Consul in AWS Secrets Manager.
| Secret | Initial Value | Sample Secret Name |
| --------------------- | -------------- | ------------------------------ |
| Consul server CA cert | Set | `my-consul-ca-cert` |
| Bootstrap ACL Token | Set | `my-consul-bootstrap-token` |
| Consul Client ACL Token | Empty | `<PREFIX>-consul-client-token` |
The secret for the client token must be initially empty. The ACL controller creates the client token in Consul
and stores the token in Secrets Manager. In the secret name, `<PREFIX>` should be replaced with the
[secret name prefix](/docs/ecs/manual/acl-controller#secret-name-prefix) of your choice.
### Secret Name Prefix
The ACL controller requires that the secrets it reads and writes are named with a unique prefix. The name prefix is used
in the [Task Role Policy](/docs/ecs/manual/acl-controller#task-role-policy) to limit the ACL controller's access within
AWS Secrets Manager to only those secrets strictly needed by the ACL controller.
The name prefix should be unique among secrets in your AWS account. We recommend using a short (8 character) random
string for the prefix.
-> **NOTE:** If you are using the ACL controller with multiple ECS clusters, each cluster requires
its own instance of the ACL controller, and each instance of the ACL controller should have a unique
name prefix.
| Secret | Sample Secret Name | Description |
| --------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Consul server CA cert | `my-consul-ca-cert` | The Consul server CA Cert for the HTTPS interface. This is required if the Consul server uses a self-signed or internal CA. It is not required for Consul servers in HCP. |
| Bootstrap ACL Token | `my-consul-bootstrap-token` | A Consul ACL token with `acl:write` and `operator:write` permissions. |
## Task Definition
You must create a task definition to deploy the ACL controller in your ECS cluster.
The ACL controller must run in the same ECS cluster hosting your service mesh application
The ACL controller must run in the same ECS cluster that hosts your service mesh application
tasks.
The following example shows how the task definition should be configured for the ACL controller.
@ -62,11 +42,7 @@ The following example shows how the task definition should be configured for the
"name": "acl-controller",
"image": "public.ecr.aws/hashicorp/consul-ecs:<CONSUL_ECS_VERSION>",
"essential": true,
"command": [
"acl-controller",
"-consul-client-secret-arn", "arn:aws:secretsmanager:us-west-2:000000000000:secret:<PREFIX>-consul-client-token",
"-secret-name-prefix", "<PREFIX>",
],
"command": ["acl-controller", "-iam-role-path", "/consul-ecs/"],
"secrets": [
{
"name": "CONSUL_HTTP_TOKEN",
@ -98,20 +74,27 @@ You must include the following top-level fields.
In the `containerDefinitions` list, include one container with the following fields.
| Field name | Type | Description |
| ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | string | The container name, which should be `acl-controller` |
| `image` | string | The `consul-ecs` image. Use our public AWS registry, `public.ecr.aws/hashicorp/consul-ecs`, to avoid rate limits. |
| `command` | list | Must be set as shown. The startup command for the ACL controller. |
| `command` | list | Should be set as shown. The startup command for the ACL controller. |
| `essential` | boolean | Must be `true` to ensure the health of your application container affects the health status of the task. |
| `secrets` | list | Must have `CONSUL_HTTP_TOKEN` set to the ACL bootstrap token and `CONSUL_CACERT_PEM` set to the Consul server CA certificate. |
| `environment` | string | Must set the `CONSUL_HTTP_ADDR` environment variable to the address of the HTTP API of your Consul servers. |
| `secrets` | list | Should be set as shown. Configures the secrets the ECS service will retrieve and set as environment variables in the `acl-controller` container. |
| `environment` | string | Must be set as shown. Configures environment variables that the ECS service will set in the `acl-controller` container. Must set the `CONSUL_HTTP_ADDR` environment variable to the HTTP(S) address of the Consul servers. |
The following CLI options are required in the `command` field of the container definition.
The following CLI options are available in the `command` field of the container definition.
| Flag | Type | Description |
| --------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| `-consul-client-secret-arn` | string | The secret where the ACL controller will store the Consul client token. |
| `-secret-name-prefix` | string | The [secret name prefix](/docs/ecs/manual/acl-controller#secret-name-prefix) that you chose for this ACL controller. |
| ------------------ | ------- | --------------------------------------------------------------------------------------------- |
| `-iam-role-path` | string | Specifies the path to IAM roles trusted by the AWS IAM auth method created by the controller. |
| `-log-level` | string | The log level for the ACL controller. Can be set to `DEBUG` for additional detail. |
The following describes the entries to include in the `secrets` list.
| Name | Description |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `CONSUL_HTTP_TOKEN` | Must be set to the secret containing the bootstrap ACL token. |
| `CONSUL_CACERT_PEM` | If applicable, should be set to the secret containing the Consul server CA certificate. This must not be set when using Consul servers in HCP. |
## ECS Service
@ -162,29 +145,17 @@ secrets.
"ecs:DescribeTasks"
],
"Resource": ["*"]
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:UpdateSecret"
],
"Resource": [
"arn:aws:secretsmanager:us-west-2:000000000000:secret:<PREFIX>-*"
]
}
]
}
```
The following are the required permissions. You will need to substitute `<PREFIX>` with your chosen [name prefix](/docs/ecs/manual/acl-controller#secret-name-prefix).
The following are the required permissions.
| Action | Resource | Description |
| ------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| --------------------- | --------- | ------------------------------------------------------------ |
| `ecs:ListTasks` | `*` | Allow the ACL controller to watch for new tasks. |
| `ecs:DescribeTasks` | `*` | Allow the ACL controller to retrieve details for new tasks. |
| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:us-west-2:000000000000:secret:<PREFIX>-*` | Allow the ACL controller to read secrets with a name prefix. |
| `secretsmanager:UpdateSecret` | `arn:aws:secretsmanager:us-west-2:000000000000:secret:<PREFIX>-*` | Allow the ACL controller to store Consul ACL tokens in secrets with a name prefix. |
### Execution Role Policy
@ -205,9 +176,15 @@ The following example shows the policy needed for the execution role.
],
"Resource": [
"arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-bootstrap-token",
"arn:aws:secretsmanager:us-west-2:000000000000:secret:<PREFIX>-consul-client-token"
"arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-ca-cert"
]
}
]
}
```
The following are the required permissions.
| Action | Resource | Description |
| ------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:us-west-2:000000000000:secret:<NAME>` | Allow ECS to retrieve this secret and inject the secret into the task. |

View File

@ -25,7 +25,7 @@ Configure a task definition that creates the containers:
- An Envoy sidecar-proxy container
- A Consul client container
- A `consul-ecs-mesh-init` container for service mesh setup
* (Optional) A `consul-ecs-health-sync` container to sync ECS health checks into Consul
- (Optional) A `consul-ecs-health-sync` container to sync ECS health checks into Consul
## Top-level fields
@ -42,10 +42,10 @@ during task startup.
"networkMode": "awsvpc",
"volumes": [
{
"name": "consul_data",
"name": "consul_data"
},
{
"name": "consul_binary",
"name": "consul_binary"
}
],
"containerDefinitions": [...]
@ -71,7 +71,7 @@ during task startup.
### Task Tags
The `tags` list must include the following if you are using the ACL controller in a [secure configuration](/docs/manual/secure-configuration).
The `tags` list must include the following if you are using the ACL controller in a [secure configuration](/docs/ecs/manual/secure-configuration).
Without these tags, the ACL controller will be unable to provision a service token for the task.
| Tag Key | Tag Value | Description |
@ -369,7 +369,7 @@ configuration to a shared volume.
| `image` | string | The `consul-ecs` image. Use our public AWS registry, `public.ecr.aws/hashicorp/consul-ecs`, to avoid rate limits. |
| `mountPoints` | list | Must be set as show above, so the `consul` and `consul-ecs` binaries can be shared among containers for task setup. |
| `command` | list | Set to `["mesh-init"]` so that the container runs the `consul-ecs mesh-init` command. |
| `environment` | list | This must include the [`CONSUL_ECS_CONFIG_JSON`](/docs/ecs/manual-installation#consul_ecs_config_json) variable. See below for details. |
| `environment` | list | This must include the [`CONSUL_ECS_CONFIG_JSON`](/docs/ecs/manual/install#consul_ecs_config_json) variable. See below for details. |
### `CONSUL_ECS_CONFIG_JSON`
@ -405,7 +405,7 @@ the `consul-ecs-health-sync` container.
| Field name | Type | Description |
| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `bootstrapDir` | string | This is the path of a shared volume that is mounted to other containers, where `consul-ecs-mesh-init` will write out Envoy configuration. |
| `healthSyncContainers` | list | Used for [health status syncing](/docs/ecs/manual-installation#consul-ecs-health-sync-container) from ECS to Consul. See below for details. |
| `healthSyncContainers` | list | Used for [health status syncing](/docs/ecs/architecture#ecs-health-check-syncing) from ECS to Consul. See below for details. |
| `proxy.upstreams` | list | The upstream services that your application calls over the service mesh, if any. The `destinationName` and `localBindPort` fields are required. |
| `service.name` | string | The name used to register this service into the Consul service catalog. |
| `service.port` | integer | The port your application listens on. Set to `0` if your application does not listen on any port. |
@ -551,6 +551,6 @@ and `consul-ecs-mesh-init` containers.
# Next Steps
* Create the task definition using the [AWS Console](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html) or the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html), or another method of your choice.
* Create the task definition using the [AWS Console](https://docs.aws.amazon.com/AmazonECS/latest/userguide/create-task-definition-classic.html) or the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/ecs/register-task-definition.html), or another method of your choice.
* Create an [ECS Service](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) to start tasks using the task definition.
* Follow the [Secure Configuration](/docs/ecs/manual/secure-configuration) to get production-ready.

View File

@ -23,20 +23,84 @@ You should be familiar with [specifying sensitive data](https://docs.aws.amazon.
You should be familiar with configuring Consul's secure features, including how to create ACL tokens and policies. Refer to the [ACL system documentation](/docs/security/acl) and [Day 1: Security tutorials](https://learn.hashicorp.com/collections/consul/security) for an introduction and additional information.
## ACL Tokens
## Auth Method
Tokens are artifacts within the ACL system that authenticate users, services, and Consul agents. Tokens are linked to policies that specify the resources the token bearer has access to when making requests in the network.
You must create two types of ACL tokens for Consul on ECS:
Auth Methods are a Consul server component that performs authentication against a trusted external party to authorize the creation of ACL tokens. The [AWS IAM auth method](/docs/security/acl/auth-methods/aws-iam) is used to enable an ECS task to automatically obtain ACL tokens when the task starts up.
There are two types of ACL tokens for Consul on ECS:
* **Client tokens:** used by the `consul-client` containers to join the Consul cluster
* **Service tokens:** used by sidecar containers for service registration and health syncing
This section describes how to manually create ACL tokens. Alternatively, you can install the ACL controller to ease the burden of creating tokens. The ACL controller can automatically create ACL tokens for Consul on ECS. For additional details, refer to [ACL Controller](/docs/manual/acl-controller).
This section describes how to manually configure the AWS IAM auth method for Consul on ECS. Alternatively, you can install the ACL controller to ease the burden of creating these resources. The ACL controller can automatically configure ACL resources for Consul on ECS. For additional details, refer to [ACL Controller](/docs/manual/acl-controller) and [Architecture](/docs/ecs/architecture).
### Define policies
### ECS Task Role Configuration
Configure the following ACL policy for the Consul client token:
The ECS [task role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html)
is an IAM role associated with an ECS task.
When an ECS task starts up, it runs a `consul login` command. The `consul login` command obtains
credentials for the task role role from AWS. It uses those credentials to sign the login request to
the AWS IAM auth method. This proves the ECS task's identity to the Consul servers.
The task role must be configured with the following details to compatible with the AWS IAM auth
method.
* An `iam:GetRole` permission to fetch itself. See
[IAM Policies](/docs/security/acl/auth-methods/aws-iam#iam-policies) for details.
* A `consul.hashicorp.com.service-name` tag on the task role which contains the Consul service name
for the application in this task.
* <EnterpriseAlert inline /> A <code>consul.hashicorp.com.namespace</code> tag on the task role
indicating the Consul Enterprise namespace where this service is registering.
The following sections describe how to configure the auth method to enable task roles to
successfully authenticate to the AWS IAM auth method and obtain tokens with the necessary
permissions.
### Auth Method for Client Tokens
The following steps configure an instance of the auth method that creates client tokens for tasks.
1. Create the auth method instance
2. Create the client policy and role
3. Create the binding rule
#### Create Auth Method for Client Tokens
The following Consul CLI command creates an instance of the auth method for client tokens.
```shell
consul acl auth-method create \
-type aws-iam \
-name iam-ecs-client-token \
-description="AWS IAM auth method for ECS client tokens" \
-config '{
"BoundIAMPrincipalArns": ["arn:aws:iam::<ACCOUNT>:role/consul-ecs/*"],
"EnableIAMEntityDetails": true
}'
```
The following flags are required:
| Flag | Type | Description |
| --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `-type` | string | Must be `aws-iam`. |
| `-name` | string | A name of your choice. Must be unique among all auth methods. |
| `-description` | string | A description of your choice. |
| `-config` | string | A JSON string containing the [configuration](/docs/security/acl/auth-methods/aws-iam#config-parameters) for the the auth method. |
In the `-config` option, the following fields are required:
| Field | Type | Description |
| ------------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `BoundIAMPrincipalArns` | list | The list of trusted IAM roles. We recommend using a wildcard to trust IAM roles at a particular path. |
| `EnableIAMEntityDetails` | boolean | Must be true so that the auth method can retrieve IAM role details, such as the role path and role tags. |
#### Create Client Policy and Role
Configure the following ACL policy for Consul client tokens:
<CodeBlockConfig filename="client-token-policy.hcl">
@ -55,52 +119,167 @@ The policy allows `node:write` for any node name, which is necessary because the
You can add the policy in Consul using the [`consul acl policy create`](/commands/acl/policy/create) command or the [`[PUT] /v1/acl/policy`](/api-docs/acl/policies#create-a-policy) API endpoint.
If you intend to create a gateway for connecting multiple Consul datacenters, you will need to configure a mesh gateway policy. If namespaces are enabled, the mesh gateway must run in the default namespace.
After the policy is created, create a Consul role associated with the policy by using the [`consul acl role create`](/commands/acl/role/create) command or the [`[PUT] /v1/acl/role`](/api-docs/acl/roles#create-a-role) API endpoint.
<CodeBlockConfig filename="mesh-gateway-policy.hcl">
The following example shows how to use the Consul CLI to create the client policy and role.
```shell
consul acl policy create -name consul-ecs-client-policy -rules @client-token-policy.hcl
consul acl role create -name consul-ecs-client-role -policy-name consul-ecs-client-policy
```
#### Create Binding Rule for Client Tokens
The following creates a binding rule for the auth method for client tokens. The binding rule
associates the client role with each token created by a successful login to this auth
method instance.
```shell
consul acl binding-rule create -method iam-ecs-client-token \
-description 'Bind a role for Consul clients on ECS' \
-bind-type role \
-bind-name consul-ecs-client-role
```
### Auth Method for Service Tokens
The following steps configure an instance of the auth method that creates service tokens for tasks.
* Create the auth method instance
* Create the binding rule
#### Create Auth Method for Service Tokens
The following uses the Consul CLI to create an instance of the auth method
for service tokens. This configures the auth method to associate a service identity
to each token created during login to this auth method instance.
```shell
consul acl auth-method create \
-type aws-iam \
-name iam-ecs-service-token \
-description="AWS IAM auth method for ECS service tokens" \
-config '{
"BoundIAMPrincipalArns": ["arn:aws:iam::<ACCOUNT>:role/consul-ecs/*"],
"EnableIAMEntityDetails": true,
"IAMEntityTags": [
"consul.hashicorp.com.service-name"
]
}'
```
The following flags are required:
| Flag | Type | Description |
| --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `-type` | string | Must be `aws-iam`. |
| `-name` | string | A name of your choice. Must be unique among all auth methods. |
| `-description` | string | A description of your choice. |
| `-config` | string | A JSON string containing the [configuration](/docs/security/acl/auth-methods/aws-iam#config-parameters) for the the auth method. |
In the `-config` option, the following fields are required:
| Field | Type | Description |
| --- | --- | --- |
| `BoundIAMPrincipalArns` | list | The list of trusted IAM roles. We recommend using a wildcard to trust IAM roles at a particular path. |
| `EnableIAMEntityDetails` | boolean | Must be true so that the auth method can retrieve IAM role details, such as the role path and role tags. |
| `IAMEntityTags` | list | The list of IAM role tags to make available to binding rules. Must include the service name tag as shown. |
The following binding rule is used to associate a service identity with each token created by
successful login to this instance of the auth method. The service identity name is taken from the
`consul.hashicorp.com.service-name` tag from the authenticaing IAM role identity.
#### Create Binding Rule
```shell
consul acl binding-rule create \
-method iam-ecs-service-token \
-description 'Bind a service identity from IAM role tags for ECS service tokens' \
-bind-type service \
-bind-name '${entity_tags.consul.hashicorp.com.service-name}'
```
### Configuration for Consul Enterprise<EnterpriseAlert inline />
When using Consul Enterprise namespaces and admin partitions, pass the `-partition <partition-name>`
option to the Consul CLI when creating Consul ACL roles, policies, auth methods, and binding rules,
in order to create these resources in a particular partition.
The following shows how to create the ACL policy for client tokens. This ensures permissions for the
client token are scoped to a particular partition.
<CodeBlockConfig filename="client-token-policy-ent.hcl">
```hcl
namespace "default" { ## If namespaces enabled
service "<service name>" {
partition "<partition-name>" {
node_prefix "" {
policy = "write"
}
}
namespace_prefix "" { ## If namespaces enabled
namespace_prefix "" {
service_prefix "" {
policy = "read"
}
node_prefix "" {
policy = "read"
}
}
agent_prefix "" {
policy = "read"
}
```
</CodeBlockConfig>
### Create service tokens
The following commands show how to use the Consul CLI to create the policy and role.
Create the Consul client token and the service tokens after adding the necessary policies. Service tokens should be associated with a service identity. The service identity includes `service:write` permissions for the service and sidecar proxy.
```shell
consul acl policy create -partition <partition-name> \
-name consul-ecs-client-policy \
-rules @client-token-policy-ent.hcl
You can create tokens using the [`consul acl token create`](/commands/acl/token/create) command or the [`[PUT] /v1/acl/token`](/api-docs/acl/tokens#create-a-token) API endpoint.
The following example shows how to use the Consul CLI to create a service token for a service named `example-client-app`:
```shell-session
$ consul acl token create -service-identity=example-client-app ...
consul acl role create \
-partition <partition-name> \
-name consul-ecs-client-role \
-policy-name consul-ecs-client-policy
```
You need to create one service token for each registered Consul service in ECS. When you add new services to the service mesh, you must create new tokens for each service.
The auth method for *service tokens* requires the following additional configuration to include a
namespace binding rule. This ensures the service tokens are created in the right namespace during
login. (The namespace binding rule must not be configured on the instance of the auth method
instance for *client tokens*.)
<CodeBlockConfig highlight="2-2,6-7,13-13">
```shell
consul acl auth-method create \
-partition <partition-name> \
-type aws-iam \
-name iam-ecs-service-token \
-description="AWS IAM auth method for ECS service tokens" \
-namespace-rule-selector 'entity_tags["consul.hashicorp.com.namespace"] != ""' \
-namespace-rule-bind-namespace '${entity_tags.consul.hashicorp.com.namespace}' \
-config '{
"BoundIAMPrincipalArns": ["arn:aws:iam::<ACCOUNT>:role/consul-ecs/*"],
"EnableIAMEntityDetails": true,
"IAMEntityTags": [
"consul.hashicorp.com.service-name",
"consul.hashicorp.com.namespace"
]
}'
```
</CodeBlockConfig>
| Field | Type | Description |
| -------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-partition` | string | The Consul Enterprise admin partition in which the auth method is created. |
| `-namespace-rule-selector` | string | When this expression evaluates to true during login, the `-namespace-rule-bind-namespace` is applied. As shown, it evaluates to true when the `consul.hashicorp.com.namespace` tag is non-empty on the task IAM role. |
| `-namespace-rule-bind-namespace` | string | This expression is evaluted to determine the namespace where the token is created during login. As shown, it uses the namespace from the `consul.hashicorp.com.namespace` tag on the task IAM role. |
| `IAMEntityTags` | list | Must include `consul.hashicorp.com.namespace` to enable use of this tag in binding rules. |
## Secret storage
You should securely store the following secrets in order to make them available to ECS tasks.
1. Consul Server CA certificate
1. Consul Server CA certificates. More than one may be required for different Consul protocols.
2. Consul gossip encryption key
3. Consul client ACL token
4. Consul service ACL tokens (one per service)
These secrets can be securely stored and passed to ECS tasks using either of the following AWS secret services:
@ -112,18 +291,16 @@ example secret ARNs when using AWS Secrets Manager:
| Secret | Sample Secret ARN |
| ---------------------- | ---------------------------------------------------------------------------------- |
| Consul Server CA Cert | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-ca-cert` |
| Consul Server CA Cert for RPC | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-ca-cert` |
| Consul Server CA Cert for HTTPS | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-https-ca-cert` |
| Gossip encryption key | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-gossip-key` |
| Client token | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-client-token` |
| Service token | `arn:aws:secretsmanager:us-west-2:000000000000:secret:my-example-client-app-token` |
## Configure `consul-client`
The following secrets must be passed to the `consul-client` container:
* Consul server CA certificate
* Consul server CA certificates
* Gossip encryption key
* Consul client ACL token
The following example shows how to include these secrets in the task definition. The `secrets`
list specifies environment variable `name`s that will be set to the secret values for this container.
@ -137,16 +314,16 @@ ECS automatically fetches the secret values specified in the `valueFrom` fields
"image": "public.ecr.aws/hashicorp/consul:<CONSUL_VERSION>",
"secrets": [
{
"name": "CONSUL_CACERT",
"name": "CONSUL_CACERT_PEM",
"valueFrom": "arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-ca-cert"
},
{
"name": "CONSUL_HTTPS_CACERT_PEM",
"valueFrom": "arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-https-ca-cert"
},
{
"name": "CONSUL_GOSSIP_ENCRYPTION_KEY",
"valueFrom": "arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-gossip-key"
},
{
"name": "AGENT_TOKEN",
"valueFrom": "arn:aws:secretsmanager:us-west-2:000000000000:secret:my-consul-client-token"
}
]
},
@ -155,19 +332,76 @@ ECS automatically fetches the secret values specified in the `valueFrom` fields
}
```
Next, update Consul configuration options to pass the secrets to the Consul client.
Next, update the Consul client startup script with the `consul login` command and additional Consul configuration
options for a secure configuration.
The following is an example of the *additional* content to include in the `consul-client` startup script. Refer to the [install
page](/docs/ecs/manual/install#consul-client-container) for the remainder of the startup script and how to pass this
script to the container.
<CodeBlockConfig highlight="3-4,10-29">
<CodeBlockConfig highlight="3-60,66-91">
```shell
...
# Write the CA Cert to a file
echo "$CONSUL_CACERT" > /tmp/consul-ca-cert.pem
# Obtain details from the task metadata
ECS_TASK_META=$(curl -s $ECS_CONTAINER_METADATA_URI_V4/task)
TASK_REGION=$(echo "$ECS_TASK_META" | jq -r .TaskARN | cut -d ':' -f 4)
TASK_ID=$(echo "$ECS_TASK_META" | jq -r .TaskARN | cut -d '/' -f 3)
CLUSTER_ARN=$(echo "$ECS_TASK_META" | jq -r .TaskARN | sed -E 's|:task/([^/]+).*|:cluster/\1|')
# Write the CA certs to a files in the shared volume
echo "$CONSUL_CACERT_PEM" > /consul/consul-ca-cert.pem
echo "$CONSUL_HTTPS_CACERT_PEM" > /consul/consul-https-ca-cert.pem
consul_login() {
echo "Logging into auth method"
consul login \
-http-addr "<consul server address>" \
-ca-file /consul/consul-https-ca-cert.pem \
-partition "<partition>" \
-type aws-iam \
-method iam-ecs-client-token \
-meta "consul.hashicorp.com/task-id=$TASK_ID" \
-meta "consul.hashicorp.com/cluster=$CLUSTER_ARN" \
-aws-region "$TASK_REGION" \
-aws-auto-bearer-token -aws-include-entity \
-token-sink-file /consul/client-token
}
read_token_stale() {
consul acl token read -http-addr ${ consul_http_addr } \
-ca-file /consul/consul-https-ca-cert.pem \
-stale -self -token-file /consul/client-token \
> /dev/null
}
# Retry in order to login successfully.
while ! consul_login; do
sleep 2
done
# Allow the health-sync container to read this token for consul logout.
chmod 0644 /consul/client-token
# Wait for raft replication to hopefully occur. Without this, an "ACL not found" may be cached for a while.
COUNT=20
while [ "$COUNT" -gt 0 ]; do
echo "Checking that the ACL token exists when reading it in the stale consistency mode ($COUNT attempts remaining)"
if read_token_stale; then
echo "Successfully read ACL token from the server"
break
fi
sleep 0.1
COUNT=$((COUNT - 1))
done
if [ "$COUNT" -eq 0 ]; then
echo "Unable to read ACL token from a Consul server; please check that your server cluster is healthy"
exit 1
fi
# This is interpolated into the agent-defaults.hcl
export AGENT_TOKEN=$(cat /consul/client-token)
# Write the Consul agent configuration file.
cat << EOF > /consul/agent-defaults.hcl
@ -183,7 +417,7 @@ auto_encrypt = {
}
tls {
defaults {
ca_file = "/tmp/consul-ca-cert.pem"
ca_file = "/consul/consul-ca-cert.pem"
verify_outgoing = true
}
}
@ -198,46 +432,75 @@ acl {
}
}
partition = "<partition>"
EOF
```
</CodeBlockConfig>
The following describes the additional steps added to the startup script:
* Fetch additional details from the task metadata: the AWS region, task id, and cluster arn.
These details are necessary for the `consul login` command used to obtain a Consul client token.
* Write CA certificates to files for Consul CLI and Consul client
* Run the `consul login` command in a retry loop.
* Wait for Raft replication to hopefully occur for this token.
* Configure the Consul client config file with additional fields necessary for secure configuration.
The following flags are passed to the `consul login` command:
| Field name | Type | Description |
| ------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| [`-http-addr`](/commands/login#http-addr) | string | HTTP(S) address of the Consul server. |
| [`-ca-file`](/commands/login#ca-file) | string | Path of the CA cert for Consul's HTTPS interface. Not required when using Consul servers on HCP. |
| `-partition` | string | <EnterpriseAlert inline /> The Consul Enterprise admin partition the auth method belongs to. |
| [`-type`](/commands/login#type) | string | The auth method type. Must be `aws-iam`. |
| [`-method`](/commands/login#type) | string | The auth method name. Must be the name of the auth method for ECS client tokens. |
| [`-meta`](/commands/login#meta) | string | Metadata to set in description of the created token. Should include the task id and cluster as shown. |
| `-aws-region` | string | The AWS region where the task is running. |
| `-aws-auto-bearer-token` | | Must be set to login to the AWS IAM auth method. |
| `-aws-include-entity` | | Must be set to enable IAM role details. |
The following table describes the additional fields that must be included in the Consul client configuration file.
| Field name | Type | Description |
| ------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------ |
| [`encrypt`](/docs/agent/config/cli-flags#_encrypt) | string | Specifies the gossip encryption key |
| [`tls.defaults.ca_file`](/docs/agent/config/config-files#tls_defaults_ca_file) | string | Specifies the Consul server CA cert for TLS verification. |
| [`encrypt`](/docs/agent/config/cli-flags#_encrypt) | string | Gossip encryption key |
| [`tls.defaults.ca_file`](/docs/agent/config/config-files#tls_defaults_ca_file) | string | Consul server CA cert for TLS verification. |
| [`acl.enabled`](/docs/agent/config/config-files#acl_enabled) | boolean | Enable ACLs for this agent. |
| [`acl.tokens.agent`](/docs/agent/config/config-files#acl_tokens_agent) | string | Specifies the Consul client token which authorizes this agent with Consul servers. |
| [`acl.tokens.agent`](/docs/agent/config/config-files#acl_tokens_agent) | string | Consul client token which authorizes this agent with Consul servers. |
| [`partition`](/docs/agent/config/config-files#partition-1) | string | <EnterpriseAlert inline /> The Consul Enterprise admin partition this agent belongs to. |
## Configure `consul-ecs-mesh-init` and `consul-ecs-health-sync`
Both `consul-ecs-mesh-init` and `consul-ecs-health-sync` containers need to be configured with
the service ACL token. This allows these containers to make HTTP API requests to the local
Consul client for service registration and health syncing.
The following *additional* options should be set in the [`CONSUL_ECS_CONFIG_JSON`](/docs/ecs/manual/install#consul_ecs_config_json) environment variable. When these options are specified, the `consul-ecs mesh-init` command will run the `consul login` command to obtain a service token from the Consul AWS IAM Auth method. The `consul-ecs health-sync` command is responsible for running a `consul logout` command for both the service and client tokens when the task shuts down.
The following shows how to set the `CONSUL_HTTP_TOKEN` variable to the service token for the `example-client-app` service,
if the token is stored in AWS Secrets Manager.
<CodeBlockConfig highlight="5-8">
<CodeBlockConfig highlight="2-8">
```json
{
"containerDefinitions": [
{
"secrets": [
{
"name": "CONSUL_HTTP_TOKEN",
"valueFrom": "arn:aws:secretsmanager:us-west-2:000000000000:secret:my-example-client-app-token"
}
]
"consulHTTPAddr": "<Consul server address>",
"consulCACertFile": "/consul/consul-https-ca-cert.pem",
"consulLogin": {
"enabled": true,
"method": "iam-ecs-service-token",
"extraLoginFlags": ["-partition", "<partition>"]
},
...
],
"bootstrapDir": "/consul",
"healthSyncContainers": [],
...
}
```
</CodeBlockConfig>
The following table explains the additional fields for the `CONSUL_ECS_CONFIG_JSON`:
| Field name | Type | Description |
| ----------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `consulHTTPAddr` | string | HTTP(S) address for the Consul server. |
| `consulCACertFile` | string | Path of the CA cert file for Consul's HTTPS interface. Not required for Consul servers in HCP. |
| `consulLogin.enabled` | boolean | Must be set to true to log in to the auth method. |
| `consulLogin.method` | string | Must be set to the name of the auth method instance for service tokens. |
| `consulLogin.extraLoginFlags` | list | Additional flags passed to the `consul login` command. <EnterpriseAlert inline /> This shows how to pass the Consul Enterprise admin partition to the `consul login` command. |

View File

@ -7,7 +7,7 @@ description: >-
# Installation with Terraform
This topic describes how to use HashiCorps Terraform modules to launch your application in AWS ECS as part of Consul service mesh. If you do not use Terraform, refer to the [Manual Installation](/docs/ecs/manual-installation) page to install Consul on ECS without Terraform.
This topic describes how to use HashiCorps Terraform modules to launch your application in AWS ECS as part of Consul service mesh. If you do not use Terraform, refer to the [Manual Installation](/docs/ecs/manual/install) page to install Consul on ECS without Terraform.
This topic does not include instructions for creating all AWS resources necessary to install Consul, such as a VPC or the ECS cluster. Refer to the guides in the [Getting Started](/docs/ecs#getting-started) section for complete and runnable examples.
@ -88,7 +88,7 @@ The following fields are required. Refer to the [module reference documentation]
| `container_definitions` | list | This is the list of [container definitions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definitions) for the task definition. This is where you include your application containers. |
| `essential` | boolean | Must be `true` to ensure the health of your application container affects the health status of the task. |
| `port` | integer | The port that your application listens on, if any. If your application does not listen on a port, set `outbound_only = true`. |
| `retry_join` | list | This is the [`retry_join`](/docs/agent/options#_retry_join) option for the Consul agent, which specifies the locations of your Consul servers. |
| `retry_join` | list | This is the [`retry_join`](/docs/agent/options#retry_join) option for the Consul agent, which specifies the locations of your Consul servers. |
### Configure an ECS service for the mesh task module
[ECS services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html) are one of the most common

View File

@ -97,7 +97,7 @@ module "my_task" {
The main differences are:
- You must remove the `execution_role_arn` and `task_role_arn` fields. The `mesh-task` module will create the task and execution roles.
- You should remove the `execution_role_arn` and `task_role_arn` fields. The `mesh-task` module creates the task and execution roles by default. If you need to use existing IAM role(s), set the `task_role` and `execution_role` fields to pass in existing roles.
- You must set the `port` field to the port that your application listens on.
If your application has no listening port, set `outbound_only = true` and remove the `port` field.
- You must add the `retry_join` field. This specifies the location of your Consul servers so that your task can join the mesh.
@ -111,5 +111,5 @@ resource.
Now that your task(s) are migrated to the `mesh-task` module,
- Start at the [ECS Service section](/docs/ecs/terraform/install#ecs-service) of the Installation Guide to continue installing Consul on ECS.
- Start at the [ECS Service section](/docs/ecs/terraform/install#configure-an-ecs-service-for-the-mesh-task-module) of the Installation Guide to continue installing Consul on ECS.
- Refer to the [`mesh-task` reference documentation](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/mesh-task?tab=inputs) for all available inputs to your mesh tasks.

View File

@ -11,7 +11,7 @@ This topic describes how to enable Consul security features for your production
## Overview
To enable security in your production workloads, you must deploy the [ACL controller](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/acl-controller), which provisions tokens for other service mesh tasks. Refer to [Automatic ACL Token Provisioning](/docs/ecs/architecture#automatic-acl-token-provisioning) to learn more about the ACL controller.
To enable security in your production workloads, you must deploy the [ACL controller](https://registry.terraform.io/modules/hashicorp/consul-ecs/aws/latest/submodules/acl-controller), which provisions tokens for other service mesh tasks. Refer to [Architecture](/docs/ecs/architecture#acl-controller) to learn more about the ACL controller.
The controller cannot provision tokens for itself, so you must create the token for the ACL controller. The following steps describe the overall process of enabling security features for your production workloads:
@ -30,10 +30,30 @@ Implement the following security features for your Consul server clusters before
1. [Gossip encryption](/docs/security/encryption#gossip-encryption) for encrypting gossip traffic.
1. [Access control lists (ACLs)](/docs/security/acl) for authentication and authorization for Consul clients and services on the mesh.
## Auth Method
Consul on ECS uses the [AWS IAM Auth Method](/docs/ecs/architecture#aws-iam-auth-method) to enable
tasks to automatically obtain Consul ACL tokens during startup.
With the Terraform modules for Consul on ECS, the auth method is supported by default when ACLs are
enabled. The ACL controller sets up the auth method on the Consul servers. The `mesh-task` module
configures the ECS task definition to be compatible with the auth method.
A unique task IAM role is required for each ECS task family. Task IAM roles must not be shared by
different task families. This is because the task family represents only one Consul service and the
task IAM role must encode the Consul service name.
By default, the `mesh-task` module will create and configure the task IAM role for you.
-> **NOTE**: When passing an existing IAM role to the `mesh-task` module using the `task_role` input
variable, you must configure the IAM role as described in [ECS Task Role
Configuration](/docs/ecs/manual/secure-configuration#ecs-task-role-configuration) to be compatible with
the AWS IAM auth method.
## ACL controller
1. Create a policy that grants `acl:write` and `operator:write` access for the controller. Refer to the [ACL policies documentation](/docs/security/acl/policies) for instructions.
1. Create a token and link it to the ACL controller policy. Refer to the [ACL tokens documentation](/docs/security/acl/tokens) for instructions.
1. Create a policy that grants `acl:write` and `operator:write` access for the controller. Refer to the [ACL policies documentation](/docs/security/acl/acl-policies) for instructions.
1. Create a token and link it to the ACL controller policy. Refer to the [ACL tokens documentation](/docs/security/acl/acl-tokens) for instructions.
1. Create a Secrets Manager secret containing the ACL controller's token and a Secrets Manager secret containing the Consul CA cert.
```hcl
@ -61,18 +81,36 @@ Implement the following security features for your Consul server clusters before
```hcl
module "acl_controller" {
source = "hashicorp/consul/aws-ecs//modules/acl-controller"
version = "<version>"
consul_bootstrap_token_secret_arn = aws_secretsmanager_secret.bootstrap_token.arn
consul_server_http_addr = "https://consul-server.example.com:8501"
consul_server_ca_cert_arn = aws_secretsmanager_secret.ca_cert.arn
ecs_cluster_arn = "arn:aws:ecs:my-region:111111111111:cluster/consul-ecs"
region = "my-region"
ecs_cluster_arn = "arn:aws:ecs:us-east-1:111111111111:cluster/consul-ecs"
region = "us-east-1"
subnets = ["subnet-abcdef123456789"]
name_prefix = "consul-ecs"
}
```
The `name_prefix` parameter is used to prefix any secrets that the ACL controller will
update in AWS Secrets Manager. The `name_prefix` parameter value must be unique for each ECS cluster where you deploy this controller.
The following table describes the required input variables for the `acl-controller` module.
| Input Variable | Type | Description |
| ----------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `source` | string | The location of the `acl-controller` module source. |
| `version` | string | The version of the `acl-controller` module. |
| `consul_bootstrap_token_secret_arn` | string | The Secrets Manager secret containing an ACL token for the ACL controller. The ACL token must have `acl:write` and `operator:write` permissions. |
| `consul_server_http_addr` | string | The HTTP(S) address of the Consul servers. |
| `consul_server_ca_cert_arn` | string | (Optional) The Secrets Manager secret containing the CA cert for HTTPS communication with Consul servers. Required if the server's certificate is self-signed or signed by an internal CA. This is not required for Consul servers in HCP. |
| `ecs_cluster_arn` | string | The ECS cluster where the ACL controller will be deployed. |
| `region` | string | The AWS region where the AWS resources will be created. |
| `subnets` | list | The AWS VPC subnet ids where the ACL controller will be deployed. |
| `name_prefix` | string | AWS resources created by the `acl-controller` module will include this prefix in the resource name. |
<EnterpriseAlert>
If you are using Consul Enterprise, see <a href="/docs/ecs/enterprise#admin-partitions-and-namespaces">Admin Partitions and Namespaces</a> for
additional configuration required to support Consul Enterprise on ECS.
</EnterpriseAlert>
## Deploy your services
@ -104,7 +142,7 @@ should be the same as the `name_prefix` you provide to the ACL controller module
```hcl
module "my_task" {
source = "hashicorp/consul/aws-ecs//modules/mesh-task"
family = "my_task"
version = "<version>"
...
@ -113,11 +151,22 @@ module "my_task" {
gossip_key_secret_arn = aws_secretsmanager_secret.gossip_key.arn
acls = true
consul_client_token_secret_arn = module.acl_controller.client_token_secret_arn
acl_secret_name_prefix = "consul-ecs"
consul_http_addr = "https://consul-server.example.com:8501"
consul_https_ca_cert_arn = aws_secretsmanager_secret.ca_cert.arn
}
```
The following table explains the `mesh-task` input variables relevant to a secure configuration:
| Input Variable | Type | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `tls` | boolean | If true, TLS is enabled for RPC communication with the Consul servers. |
| `consul_server_ca_cert_arn` | string | The Secrets Manager secret containing the CA certificate for RPC communication with the Consul servers when TLS is enabled. |
| `gossip_key_secret_arn` | string | The Secrets Manager secret containing Consul's gossip encryption key. |
| `acls` | boolean | If true, ACLs are enabled. |
| `consul_http_addr` | string | The Consul server address. Required when `acls = true` in order to log in to Consul's AWS IAM auth method to obtain ACL tokens. |
| `consul_https_ca_cert_arn` | string | (optional) The Secrets Manager secret containing the CA cert for HTTPS communication with Consul servers. Required if the server's certificate is self-signed or signed by an internal CA. This is not required for Consul servers in HCP. |
Complete the following steps described in the Installation with Terraform chapter to deploy and connect your services:
1. [Run Terraform](/docs/ecs/terraform/install#run-terraform)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 153 KiB