Skip to content

Commit

Permalink
Merge pull request #24 from toricls/check-readonlyrootfs
Browse files Browse the repository at this point in the history
Add check for "readonlyRootFilesystem"
  • Loading branch information
toricls authored May 20, 2021
2 parents be0747c + bc24285 commit d4d7bfb
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,14 @@ The managed agent for a container in your Task has stopped for some reasons. If
14. **_🟡 Init Process Enabled | Disabled_**
This check item won't block you to use ECS Exec, but we recommend you to add the `initProcessEnabled` flag to your ECS task definition for each container to avoid having orphaned and zombie processes. See the "Considerations for using ECS Exec" in [the ECS official documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-considerations) for more details.

15. **_🔴 EC2 or Task Role | Not Configured"_ or _{serviceName}:{ActionName}: implicitDeny_**
15. **_🔴 Read-Only Root Filesystem | ReadOnly_**
ECS Exec uses the SSM agent as its managed agent, and the agents requires that the container file system is able to be written in order to create the required directories and files. Therefore, you need to set the `readonlyRootFilesystem` flag as `false` in your task definition to exec into the container using ECS Exec. See the "Considerations for using ECS Exec" in [the ECS official documentation](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-considerations) for more details.

16. **_🔴 EC2 or Task Role | Not Configured"_ or _{serviceName}:{ActionName}: implicitDeny_**
Your ECS task needs a task role or an instance role of the underlying EC2 instance with some permissions for using SSM Session Manager at least. See the [IAM permissions required for ECS Exec](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-enabling-and-using) section and the [Enabling logging and auditing in your tasks and services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-logging) section in the official documentation for the details.
Note that the `Condition` element of the IAM policy is not currently supported to evaluate by `check-ecs-exec.sh`.

16. **_🟡 SSM PrivateLink "com.amazonaws.(region).ssmmessages" not found_**
17. **_🟡 SSM PrivateLink "com.amazonaws.(region).ssmmessages" not found_**
The `check-ecs-exec.sh` found one or more VPC endpoints configured in the VPC for your task, so you **may** want to add an additional SSM PrivateLink for your VPC. Make sure your ECS task has proper outbound internet connectivity, and if it doesn't, then you **need** to configure an additional SSM PrivateLink for your VPC.

## Security
Expand Down
48 changes: 39 additions & 9 deletions check-ecs-exec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -356,25 +356,33 @@ fi
printf "${COLOR_DEFAULT}\n"

# 6. Check the managed agents' status
printf "${COLOR_DEFAULT} Managed Agent Status | "
printf "${COLOR_DEFAULT} Container-Level Checks | \n"
printf "${COLOR_DEFAULT} ----------\n"
printf "${COLOR_DEFAULT} Managed Agent Status"
if [[ "x${executeCommandEnabled}" = "xfalse" ]]; then
printf "${COLOR_YELLOW}SKIPPED\n"
printf " - ${COLOR_YELLOW}SKIPPED\n"
printf "${COLOR_DEFAULT} ----------\n"
else
printf "\n"
printf "${COLOR_DEFAULT} ----------\n"
agentsStatus=$(echo "${describedTaskJson}" | jq -r ".tasks[0].containers[].managedAgents[].lastStatus")
idx=0
for _ in $agentsStatus; do
containerName=$(echo "${describedTaskJson}" | jq -r ".tasks[0].containers[${idx}].name")
status=$(echo "${describedTaskJson}" | jq -r ".tasks[0].containers[${idx}].managedAgents[0].lastStatus")
reason=$(echo "${describedTaskJson}" | jq -r ".tasks[0].containers[${idx}].managedAgents[0].reason")
lastStartedAt=$(echo "${describedTaskJson}" | jq -r ".tasks[0].containers[${idx}].managedAgents[0].lastStartedAt")
printf " $((idx+1)). "
printf " $((idx+1)). "
case "${status}" in
*STOPPED* ) printf "${COLOR_RED}STOPPED (Reason: ${reason})";;
*PENDING* ) printf "${COLOR_YELLOW}PENDING";;
* ) printf "${COLOR_GREEN}RUNNING";;
esac
printf "${COLOR_DEFAULT} for \"${containerName}\" container - LastStartedAt: ${lastStartedAt}\n"
printf "${COLOR_DEFAULT} for \"${containerName}\""
if [[ "x${status}" = "xSTOPPED" ]]; then
printf " - LastStartedAt: ${lastStartedAt}"
fi
printf "\n"
idx=$((idx+1))
done
fi
Expand All @@ -384,22 +392,44 @@ taskDefArn=$(echo "${describedTaskJson}" | jq -r ".tasks[0].taskDefinitionArn")
taskDefJson=$(${AWS_CLI_BIN} ecs describe-task-definition \
--task-definition "${taskDefArn}" \
--output json)
taskDefFamily=$(echo "${taskDefJson}" | jq -r ".taskDefinition.family")
taskDefRevision=$(echo "${taskDefJson}" | jq -r ".taskDefinition.revision")
initEnabledList=$(echo "${taskDefJson}" | jq -r ".taskDefinition.containerDefinitions[].linuxParameters.initProcessEnabled")
idx=0
printf "${COLOR_DEFAULT} Init Process Enabled | ${taskDefArn}\n"
printf "${COLOR_DEFAULT} ----------\n"
printf "${COLOR_DEFAULT} Init Process Enabled (${taskDefFamily}:${taskDefRevision})\n"
printf "${COLOR_DEFAULT} ----------\n"
for enabled in $initEnabledList; do
containerName=$(echo "${taskDefJson}" | jq -r ".taskDefinition.containerDefinitions[${idx}].name")
printf " $((idx+1)). "
printf " $((idx+1)). "
case "${enabled}" in
*true* ) printf "${COLOR_GREEN}Enabled";;
*false* ) printf "${COLOR_YELLOW}Disabled";;
* ) printf "${COLOR_YELLOW}Disabled";;
esac
printf "${COLOR_DEFAULT} - \"${containerName}\" container\n"
printf "${COLOR_DEFAULT} - \"${containerName}\"\n"
idx=$((idx+1))
done

# 8. Check the "readonlyRootFilesystem" flag added in the task definition (red)
readonlyRootFsList=$(echo "${taskDefJson}" | jq -r ".taskDefinition.containerDefinitions[].readonlyRootFilesystem")
idx=0
printf "${COLOR_DEFAULT} ----------\n"
printf "${COLOR_DEFAULT} Read-Only Root Filesystem (${taskDefFamily}:${taskDefRevision})\n"
printf "${COLOR_DEFAULT} ----------\n"
for enabled in $readonlyRootFsList; do
containerName=$(echo "${taskDefJson}" | jq -r ".taskDefinition.containerDefinitions[${idx}].name")
printf " $((idx+1)). "
case "${enabled}" in
*false* ) printf "${COLOR_GREEN}Disabled";;
*true* ) printf "${COLOR_RED}ReadOnly";;
* ) printf "${COLOR_GREEN}Disabled";;
esac
printf "${COLOR_DEFAULT} - \"${containerName}\"\n"
idx=$((idx+1))
done

# 8. Check the task role permissions
# 9. Check the task role permissions
overriddenTaskRole=true
taskRoleArn=$(echo "${describedTaskJson}" | jq -r ".tasks[0].overrides.taskRoleArn")
if [[ "x${taskRoleArn}" = "xnull" ]]; then
Expand Down Expand Up @@ -538,7 +568,7 @@ else
fi
fi

# 9. Check existing VPC Endpoints (PrivateLinks) in the task VPC.
# 10. Check existing VPC Endpoints (PrivateLinks) in the task VPC.
# If there is any VPC Endpoints configured for the task VPC, we assume you would need an additional SSM PrivateLink to be configured. (yellow)
# TODO: In the ideal world, the script should simply check if the task can reach to the internet or not :)
taskNetworkingAttachment=$(echo "${describedTaskJson}" | jq -r ".tasks[0].attachments[0]")
Expand Down

0 comments on commit d4d7bfb

Please sign in to comment.