Anchore uses a go binary called anchore-ecs-inventory that leverages the AWS Go SDK to gather an inventory of containers and their images running on Amazon ECS and report back to Anchore.
The Amazon ECS Inventory Agent can be installed via Helm Chart or as an ECS task definition.
Note
The Anchore Amazon ECS Inventory Agent is a licensed add-on, please make sure you have a valid runtime license entitlement.Deploying via Helm on Kubernetes
You can install the chart via the Anchore repository:
helm repo add anchore https://charts.anchore.io
helm install <release-name> -f <values.yaml> anchore/ecs-inventory
A basic values file can be found here.
IAM Role Configuration
Note
Anchore recommends using an IAM role to provide the ECS Inventory Agent secure access to the ECS service API.The following IAM role permissions should be used in order to allow the Anchore ECS Inventory Agent to poll the ECS service API for running inventory:
cat <<EOF > ecs-read-only-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ecs:Describe*",
"ecs:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
aws iam create-policy \
--policy-name ECSReadOnly \
--policy-document file://ecs-read-only-policy.json
Follow the AWS instructions found here to assign your IAM role to a Kubernetes service account in your cluster where the Anchore ECS Inventory Agent will be running. Then configure the following in your values.yaml to ensure the agent has access to the ECS service API:
serviceAccountName: "service_account_name"
Using existing secrets
For those users unable to use IAM roles (e.g. the ECS Inventory Agent is not running on Kubernetes or ECS), the (ecsInventory.useExistingSecret and ecsInventory.existingSecretName) or ecsInventory.injectSecretsViaEnv keys allows you to create your own secret and provide it in the values file or place the required secret into the pod via different means such as injecting the secrets into the pod using hashicorp vault. For example:
Create a secret in kubernetes:
apiVersion: v1 kind: Secret metadata: name: ecs-inventory-secrets type: Opaque stringData: ANCHORE_ECS_INVENTORY_ANCHORE_PASSWORD: foobar AWS_ACCESS_KEY_ID: someKeyId AWS_SECRET_ACCESS_KEY: someSecretAccessKeyProvide it to the helm chart via the values file:
ecsInventory: useExistingSecret: true existingSecretName: "ecs-inventory-secrets"
Deploying on Amazon ECS
It is also possible to deploy the ecs-inventory container on Amazon ECS, using the same IAM role for access permissions to the ECS service API, as seen above. Here is an sample task definition that could be used to deploy ecs-inventory with a default configuration:
export aws_account_id=$(aws sts get-caller-identity --query Account --output text);
export AWS_DEFAULT_REGION=us-east-1
# VPC ID here
export vpc_id="vpc-0f14583bb6ffca152";
# Subnet ID(s) here (comma separated)
export subnet_ids="subnet-08636facfc2fbbaff,subnet-00a124b8117b3aead";
# Security group IDS here (allowing outbound access to your Anchore environment)
export security_group_id="sg-0f775aa6bc7b5f947";
export ANCHORE_URL="https://my.anchore.com";
# NOTE: We don't suggest embedding the admin account & user but it is being used as an example
# Anchore Account name (tenant name) goes here
export ANCHORE_ACCOUNT="admin";
# Anchore Username goes here
export ANCHORE_USERNAME="admin";
# Populate your password here (stored in an SSM parameter)
export ANCHORE_PASSWORD="";
aws iam create-policy \
--policy-name ECSReadOnly \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ecs:Describe*",
"ecs:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}'
aws iam create-role \
--role-name AnchoreECSInventoryTaskRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
aws iam create-role \
--role-name AnchoreECSInventoryExecutionRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
aws iam attach-role-policy \
--role-name AnchoreECSInventoryExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws iam attach-role-policy \
--role-name AnchoreECSInventoryTaskRole \
--policy-arn arn:aws:iam::${aws_account_id}:policy/ECSReadOnly
aws iam attach-role-policy \
--role-name AnchoreECSInventoryExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws logs create-log-group --log-group-name /anchore/ecs-inventory --region ${AWS_DEFAULT_REGION}
aws ssm put-parameter \
--name "/ANCHORE_ECS_INVENTORY_ANCHORE_PASSWORD" \
--type "SecureString" \
--value "${ANCHORE_PASSWORD}" \
--overwrite
aws iam put-role-policy \
--role-name AnchoreECSInventoryExecutionRole \
--policy-name ECSInventorySSMAccess \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters",
"ssm:GetParameter"
],
"Resource": "arn:aws:ssm:'${AWS_DEFAULT_REGION}':'${aws_account_id}':parameter/ANCHORE_ECS_INVENTORY_ANCHORE_PASSWORD"
}
]
}'
cat << EOF > task-definition.json
{
"family": "anchore-ecs-inventory-example-task-definition",
"cpu": "512",
"memory": "1024",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"executionRoleArn": "arn:aws:iam::${aws_account_id}:role/AnchoreECSInventoryExecutionRole",
"taskRoleArn": "arn:aws:iam::${aws_account_id}:role/AnchoreECSInventoryTaskRole",
"containerDefinitions": [
{
"name": "ecs-inventory",
"image": "docker.io/anchore/ecs-inventory:latest",
"cpu": 0,
"essential": true,
"environment": [
{
"name": "ANCHORE_ECS_INVENTORY_ANCHORE_URL",
"value": "${ANCHORE_URL}"
},
{
"name": "ANCHORE_ECS_INVENTORY_ANCHORE_USER",
"value": "${ANCHORE_USERNAME}"
},
{
"name": "ANCHORE_ECS_INVENTORY_ANCHORE_ACCOUNT",
"value": "${ANCHORE_ACCOUNT}"
},
{
"name": "ANCHORE_ECS_INVENTORY_REGION",
"value": "${AWS_DEFAULT_REGION}"
}
],
"secrets": [
{
"name": "ANCHORE_ECS_INVENTORY_ANCHORE_PASSWORD",
"valueFrom": "arn:aws:ssm:${AWS_DEFAULT_REGION}:${aws_account_id}:parameter/ANCHORE_ECS_INVENTORY_ANCHORE_PASSWORD"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-create-group": "true",
"awslogs-group": "/anchore/ecs-inventory",
"awslogs-region": "${AWS_DEFAULT_REGION}",
"awslogs-stream-prefix": "ecs"
}
}
}
]
}
EOF
aws ecs register-task-definition \
--cli-input-json file://task-definition.json
aws ecs create-cluster \
--cluster-name anchore-ecs-inventory-cluster
#vpc_id=$(aws ec2 describe-vpcs \
# --filters "Name=isDefault,Values=true" \
# --query "Vpcs[0].VpcId" --output text)
#subnet_ids=$(aws ec2 describe-subnets \
# --filters "Name=vpc-id,Values=$vpc_id" \
# --query "Subnets[*].SubnetId" --output text)
#security_group_id=$(aws ec2 describe-security-groups \
# --filters "Name=vpc-id,Values=$vpc_id" \
# --query "SecurityGroups[?GroupName=='default'].GroupId" --output text)
#echo $vpc_id
#echo $subnet_id
#echo $security_group_id
export vpc_id="vpc-0f14583bb6ffca152";
export subnet_ids="subnet-08636facfc2fbbaff,subnet-00a124b8117b3aead";
export security_group_id="sg-0f775aa6bc7b5f947";
aws ecs run-task \
--cluster anchore-ecs-inventory-cluster \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={
subnets=[${subnet_ids}],
securityGroups=[${security_group_id}],
assignPublicIp=ENABLED
}" \
--task-definition anchore-ecs-inventory-example-task-definition
Usage
To verify that you are tracking Amazon ECS inventory in your Anchore Enterprise deployment you can access inventory results with the command anchorectl inventory list and look for results where the TYPE is ecs.
Auto analyze new inventory
It is possible to create a subscription to watch for new Amazon ECS inventory that is reported to Anchore and automatically schedule those images for analysis.
1. Create the subscription
A subscription can be created by sending a POST to /v2/subscriptions with the following payload:
{
"subscription_key": "<SUBSCRIPTION_KEY>",
"subscription_type": "runtime_inventory"
}
Curl example:
curl -X POST -u USERNAME:PASSWORD --url ANCHORE_URL/v2/subscriptions --header 'Content-Type: application/json' --data '{
"subscription_key": "arn:aws:ecs:eu-west-2:123456789012:cluster/myclustername",
"subscription_type": "runtime_inventory"
}'
The subscription_key can be set to any part of an Amazon ECS ClusterARN. For example setting the subscription_key to the:
- full ClusterARN
arn:aws:ecs:us-east-1:012345678910:cluster/telemetrywill create a subscription that only watches this cluster - partial ClusterARN
arn:aws:ecs:eu-west-2:988505687240will result in a subscription that watches every cluster within the account988505687240
2. Activate the subscription
After a subscription has been created it needs to be activated. This can be achieved with anchorectl.
anchorectl subscription activate <SUBSCRIPTION_KEY> runtime_inventory
General Runtime Management
See Data Management