The TL;DR of security with Amazon ECS
Imagine you sit down with your boss and they ask you “What do you think about Amazon Elastic Container Service (Amazon ECS) and security?” It’s a big topic, but worth exploring. In this blog post, you’ll learn about aspects of Amazon ECS that support better security practices and give you a few talking points when your boss asks you a similar question.
As with any AWS service, the first place to start is understanding the shared responsibility model. This model outlines what you, as a user of a service, are responsible for and what AWS takes care of for you. With this knowledge you can focus on the right things and not worry about others. In context of the shared responsibility model for Amazon ECS, at a high level, AWS manages the security and reliability of the ECS control plane, where as you’re responsible for things like your application data, network, logging/monitoring, and runtime security.
Once you know what you’re responsible for, you can move on to thinking about who you’re dealing with and what they should be legitimately able to do. In other words: identity (authentication) and access (authorization). When architecting a system, you often have to spend tremendous mental energy thinking about how the various moving pieces all accomplish these same tasks, and unfortunately, often using different methods and models which are hard to reconcile. For example, your application framework, database, and orchestrator might all have different ways of reasoning about identity and access and you’re the poor soul that needs to figure it all out.
Amazon ECS is specific to AWS and uses AWS Identity and Access Management (IAM) for these tasks. Your organization has probably invested a ton of time into learning IAM and refining the permissions for your specific use case, which means that Amazon ECS fits into the existing skills of your team and there is one less opportunity for problems as you have no need to shift mental models, tools, or syntax between different methods of identity or access.
A more specific aspect of the integration between Amazon ECS and IAM, is how ECS couples IAM roles in the task definition, at task launch, assigning a container-unique, short-lived IAM role. With this role, you can allow only particular containers to access particular AWS services and resources. As an example, your web-facing application could only access less sensitive resources, and non-web facing services could have access to additional resources. This allows you to quickly reason about your IAM needs at the container-level while keeping the abstraction the same as the rest of your AWS architecture.
Like identity and access, workload connectivity (to/from as well as internal/external) is a non-trivial aspect of overall application security. Typically, you’d have to manage firewalls, as well as carefully consider ports and protocols, with mistaken configurations being a commonly exploited opportunity for bad actors. Thankfully, Amazon ECS tightly integrates with Amazon VPC, which provides familiar abstractions down to the task level.
Amazon ECS tasks are coupled to an Elastic Network Adapters (ENI), the same logical network abstraction used for Amazon Elastic Compute Cloud (Amazon EC2). This allows you to make security group rules based on the needs of your task and you are in control entirely of the connectivity and how the task connects with the rest of your architecture. Additionally, tasks can’t see nor talk to one another unless you explicitly allow it and you can even define how the containers can talk to one another.
Returning to the previous example, your non-web facing services could have connectivity to only what is needed with no access to the outside world where as your web-facing application has very narrow internal connectivity and specific access to the ports needed to serve the application only. Non-web facing services only need to be able to accept connections from other specific containers, creating a minimal surface area with uninteresting attack vectors. Should a bad actor gain access to the web-facing application, their access is effectively limited due to narrowly-defined, explicit inter-task activity.
Combining these properties with IAM limiting access to other resources, the picture becomes clear that Amazon ECS provides a way to use existing AWS abstractions to layer protections on connectivity, access, and resources.
Of course, application security doesn’t stop at protecting the functionality of the application itself, you also have to think about security during administration and debugging.
SSH has been around 28 years and has served the industry well, but the sheer utility and ubiquity of SSH unfortunately makes it a common target. Ideally, you’d want to avoid painting this target entirely: thankfully ECS has a couple of ways to avoid SSH. To debug and interact with containers, you can use ECS Exec. ECS Exec allows you to get a shell to your container without having SSH dependencies nor open ports. This works through AWS Systems Manager (SSM) Session Manager which is enabled by having an outbound connection from the container to the SSM control plane (unlike SSH which creates an open port for inbound traffic). As an AWS user, you can connect to the SSM service and it manages the connection between you and your container which you can use nearly identically to SSH.
Similarly, if you’re running Amazon ECS on Amazon EC2, you can even eliminate your SSH server on the container host by using Bottlerocket, a special purpose Linux distro for containers. Bottlerocket has many security-minded features, but, by-default, it has no SSH server and uses SSM as the primary way to interactively administer and debug the container host.
So, there you have it: Amazon ECS is a container orchestration service built at AWS for AWS. It adopts many of the same security mechanisms and abstractions as the rest of AWS, so your pre-existing understanding of security and tool belt transfers to Amazon ECS without additional translation. This close integration means creating a clean, familiar security landscape a for your containerized applications that fit right in with the tools and services you’re already using.