Deny Linux kernel capabilities for Amazon ECS and AWS Fargate tasks

Nathan Peck profile picture
Nathan Peck
Senior Developer Advocate at AWS

What and why?

Amazon Elastic Container Service (ECS) is a container orchestrator that launches and manages container deployments on your behalf. It configures the settings that are used when running the application container. One of those settings that can be configured is the Linux capabilities of the application container.

Linux capabilities are a way to limit or increase the level of access a process has to use the full capabilities of the Linux kernel. Elevated capabilities could be exploited by a process to "break out" of it's container and interfere with the host. On the other hand, limiting capabilities is a good way to build further limits around a process that may be running potential untrustworthy code.

In this pattern you will learn how to deny containers linux capabilities using CloudFormation Guard, an open-source, general-purpose, policy-as-code evaluation tool.

TIP

If you are deploying Amazon ECS tasks on AWS Fargate then there are already existing restrictions on which Linux capabilities can be added. See the KernelCapabilities documentation for a list of the capabilities that can be added, as well as the current AWS Fargate restrictions on capabilities. This pattern is primarily applicable to deploying Amazon ECS tasks on EC2 capacity.

Dependencies

This pattern uses CloudFormation Guard, which can be installed with the following command:

Language: sh
curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/aws-cloudformation/cloudformation-guard/main/install-guard.sh | sh
export PATH=~/.guard/bin:$PATH
cfn-guard --version

You can also see the install instructions for other systems.

CloudFormation Guard Rule

File: no-capabilities-for-tasks.guardLanguage: guard

let task_defs = Resources.*[Type == 'AWS::ECS::TaskDefinition']

#
# Verify that ECS tasks are not adding Linux kernel capabilities
#
rule tasks_denied_linux_capabilities {
  when %task_defs !empty {
    %task_defs.Properties.ContainerDefinitions[*] {
      LinuxParameters.Capabilities.Add !exists
    }
  }
}

Sample Templates

The following sample CloudFormation templates can be used to verify that this rule works:

  • Good ECS tasks
  • Bad ECS tasks
File: safe-task-def.ymlLanguage: yml
AWSTemplateFormatVersion: '2010-09-09'
Description: Example task definitions that do not add Linux kernel capabilities
Resources:

  DefaultCapabilitiesTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: alpine
      Cpu: 256
      Memory: 128
      ContainerDefinitions:
        - Name: alpine
          Image: public.ecr.aws/docker/library/alpine:latest
          Essential: true

  DroppedCapabilitiesTaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: alpine
      Cpu: 256
      Memory: 128
      ContainerDefinitions:
        - Name: alpine
          Image: public.ecr.aws/docker/library/alpine:latest
          Essential: true
          LinuxParameters:
            Capabilities:
              Drop:
                - SYS_CHROOT

Usage

You can validate the sample CloudFormation templates against the CloudFormation guard rule using the following command:

Language: sh
cfn-guard validate --data *.yml --rules .

You should see output similar to this:

Language: txt
bad-task-def.yml Status = FAIL
FAILED rules
no-capabilities-for-tasks.guard/tasks_denied_linux_capabilities    FAIL
---
Evaluating data bad-task-def.yml against rules no-capabilities-for-tasks.guard
Number of non-compliant resources 1
Resource = AddedCapabilityTaskDefinition {
  Type      = AWS::ECS::TaskDefinition
  Rule = tasks_denied_linux_capabilities {
    ALL {
      Check =  LinuxParameters.Capabilities.Add not EXISTS   {
        ComparisonError {
          Error            = Check was not compliant as property [/Resources/AddedCapabilityTaskDefinition/Properties/ContainerDefinitions/0/LinuxParameters/Capabilities/Add[L:17,C:16]] existed.
          PropertyPath    = /Resources/AddedCapabilityTaskDefinition/Properties/ContainerDefinitions/0/LinuxParameters/Capabilities/Add[L:17,C:16]
          Operator        = NOT EXISTS
          Code:
               15.          LinuxParameters:
               16.            Capabilities:
               17.              Add:
               18.                - SYS_ADMIN

        }
      }
    }
  }
}

See Also

More policy as code patterns: