From 3d86bf1705957c7245e0bfca98f52deba9c87a9d Mon Sep 17 00:00:00 2001 From: Nacho Rivera <59198746+n4ch04@users.noreply.github.com> Date: Thu, 27 Oct 2022 11:47:00 +0200 Subject: [PATCH] fix(): Cloudtrail checks (#1433) --- checks/check21 | 60 +++++++++--------- checks/check22 | 56 +++++++++-------- checks/check23 | 103 ++++++++++++++---------------- checks/check24 | 50 +++++++-------- checks/check26 | 166 +++++++++++++++++++++++++++++++++---------------- checks/check27 | 41 ++++++------ 6 files changed, 260 insertions(+), 216 deletions(-) diff --git a/checks/check21 b/checks/check21 index 90ba9c9e70..9bb9c4f75f 100644 --- a/checks/check21 +++ b/checks/check21 @@ -27,42 +27,40 @@ CHECK_DOC_check21='https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cl CHECK_CAF_EPIC_check21='Logging and Monitoring' check21(){ - trail_count=0 - # "Ensure CloudTrail is enabled in all regions (Scored)" for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion, Multiregion:IsMultiRegionTrail, ARN:TrailARN}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) - - MULTIREGION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].IsMultiRegionTrail' --output text --trail-name-list $trail) - if [[ "$MULTIREGION_TRAIL_STATUS" == 'False' ]];then - textFail "$regx: Trail $trail is not enabled for all regions" "$regx" "$trail" - else - TRAIL_ON_OFF_STATUS=$($AWSCLI cloudtrail get-trail-status $PROFILE_OPT --region $TRAIL_REGION --name $trail --query IsLogging --output text) - if [[ "$TRAIL_ON_OFF_STATUS" == 'False' ]];then - textFail "$regx: Trail $trail is configured for all regions but it is OFF" "$regx" "$trail" - else - textPass "$regx: Trail $trail is enabled for all regions" "$regx" "$trail" + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_ARN TRAIL_HOME_REGION IS_MULTIREGION TRAIL_NAME + do + TRAIL_ON_OFF_STATUS=$(${AWSCLI} cloudtrail get-trail-status ${PROFILE_OPT} --region ${regx} --name ${TRAIL_ARN} --query IsLogging --output text) + if [[ "$TRAIL_ON_OFF_STATUS" == "False" ]] + then + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textFail "$regx: Trail ${TRAIL_NAME} is multiregion configured from region "${TRAIL_HOME_REGION}" but it is not logging" "${regx}" "${TRAIL_NAME}" + else + textFail "$regx: Trail ${TRAIL_NAME} is not a multiregion trail and it is not logging" "${regx}" "${TRAIL_NAME}" + fi + elif [[ "$TRAIL_ON_OFF_STATUS" == "True" ]] + then + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textPass "$regx: Trail ${TRAIL_NAME} is multiregion configured from region "${TRAIL_HOME_REGION}" and it is logging" "${regx}" "${TRAIL_NAME}" + else + textFail "$regx: Trail ${TRAIL_NAME} is not a multiregion trail and it is logging" "${regx}" "${TRAIL_NAME}" + fi fi - fi + done <<< "${REGION_TRAIL}" done - fi - if [[ $trail_count == 0 ]]; then - if [[ $FILTERREGION ]]; then - textFail "$regx: No CloudTrail trails were found in the filtered region" "$regx" "$trail" - else - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" - fi + else + textFail "$regx: No CloudTrail trails were found for the region" "${regx}" "No trails found" fi done } diff --git a/checks/check22 b/checks/check22 index 3b1a1d203c..c8eb0a2dd3 100644 --- a/checks/check22 +++ b/checks/check22 @@ -27,34 +27,40 @@ CHECK_DOC_check22='http://docs.aws.amazon.com/awscloudtrail/latest/userguide/clo CHECK_CAF_EPIC_check22='Logging and Monitoring' check22(){ - trail_count=0 - # "Ensure CloudTrail log file validation is enabled (Scored)" - for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" - continue + for regx in $REGIONS + do + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion, Multiregion:IsMultiRegionTrail, LogFileValidation:LogFileValidationEnabled}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" + continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) - - LOGFILEVALIDATION_TRAIL_STATUS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].LogFileValidationEnabled' --output text --trail-name-list $trail) - if [[ "$LOGFILEVALIDATION_TRAIL_STATUS" == 'False' ]];then - textFail "$regx: Trail $trail log file validation disabled" "$regx" "$trail" - else - textPass "$regx: Trail $trail log file validation enabled" "$regx" "$trail" - fi + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_HOME_REGION LOG_FILE_VALIDATION IS_MULTIREGION TRAIL_NAME + do + if [[ "${LOG_FILE_VALIDATION}" == "True" ]] + then + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textPass "$regx: Multiregion trail ${TRAIL_NAME} configured from region ${TRAIL_HOME_REGION} log file validation enabled" "$regx" "$TRAIL_NAME" + else + textPass "$regx: Single region trail ${TRAIL_NAME} log file validation enabled" "$regx" "$TRAIL_NAME" + fi + else + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textFail "$regx: Multiregion trail ${TRAIL_NAME} configured from region ${TRAIL_HOME_REGION} log file validation disabled" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Single region trail ${TRAIL_NAME} log file validation disabled" "$regx" "$TRAIL_NAME" + fi + fi + done <<< "${REGION_TRAIL}" done - fi - if [[ $trail_count == 0 ]]; then - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" + else + textPass "$regx: No trails found in the region" "$regx" fi done } diff --git a/checks/check23 b/checks/check23 index ea00f4a1d4..5bfe753c24 100644 --- a/checks/check23 +++ b/checks/check23 @@ -27,68 +27,61 @@ CHECK_DOC_check23='https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_po CHECK_CAF_EPIC_check23='Logging and Monitoring' check23(){ - trail_count=0 - # "Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored)" - for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + for regx in $REGIONS + do + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion, Multiregion:IsMultiRegionTrail, BucketName:S3BucketName}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_BUCKET TRAIL_HOME_REGION IS_MULTIREGION TRAIL_NAME + do + if [[ ! "${TRAIL_BUCKET}" ]] + then + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textFail "$regx: Multiregion trail ${TRAIL_NAME} configured from region ${TRAIL_HOME_REGION} does not publish to S3" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Single region trail ${TRAIL_NAME} does not publish to S3" "$regx" "$TRAIL_NAME" + fi + continue + fi - CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].[S3BucketName]' --output text --trail-name-list $trail) - if [[ -z $CLOUDTRAILBUCKET ]]; then - textFail "Trail $trail in $TRAIL_REGION does not publish to S3" "$regx" "$trail" - continue - fi + BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $TRAIL_BUCKET --output text 2>&1) + if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]] + then + textInfo "$regx: Trail ${TRAIL_NAME} with home region ${TRAIL_HOME_REGION} Access Denied getting bucket location for bucket $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + continue + fi + if [[ $BUCKET_LOCATION == "None" ]]; then + BUCKET_LOCATION="us-east-1" + fi + if [[ $BUCKET_LOCATION == "EU" ]]; then + BUCKET_LOCATION="eu-west-1" + fi - CLOUDTRAIL_ACCOUNT_ID=$(echo $trail | awk -F: '{ print $5 }') - if [ "$CLOUDTRAIL_ACCOUNT_ID" != "$ACCOUNT_NUM" ]; then - textInfo "Trail $trail in $TRAIL_REGION S3 logging bucket $CLOUDTRAILBUCKET is not in current account" "$regx" "$trail" - continue - fi + CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $TRAIL_BUCKET $PROFILE_OPT --region $BUCKET_LOCATION --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' --output text 2>&1) + if [[ $(echo "$CLOUDTRAILBUCKET_HASALLPERMISIONS" | grep AccessDenied) ]]; then + textInfo "$regx: Trail ${TRAIL_NAME} with home region ${TRAIL_HOME_REGION} Access Denied getting bucket acl for bucket $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + continue + fi - # - # LOCATION - requests referencing buckets created after March 20, 2019 - # must be made to S3 endpoints in the same region as the bucket was - # created. - # - BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $CLOUDTRAILBUCKET --output text 2>&1) - if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then - textInfo "Trail $trail in $TRAIL_REGION Access Denied getting bucket location for $CLOUDTRAILBUCKET" "$regx" "$trail" - continue - fi - if [[ $BUCKET_LOCATION == "None" ]]; then - BUCKET_LOCATION="us-east-1" - fi - if [[ $BUCKET_LOCATION == "EU" ]]; then - BUCKET_LOCATION="eu-west-1" - fi - - CLOUDTRAILBUCKET_HASALLPERMISIONS=$($AWSCLI s3api get-bucket-acl --bucket $CLOUDTRAILBUCKET $PROFILE_OPT --region $BUCKET_LOCATION --query 'Grants[?Grantee.URI==`http://acs.amazonaws.com/groups/global/AllUsers`]' --output text 2>&1) - if [[ $(echo "$CLOUDTRAILBUCKET_HASALLPERMISIONS" | grep AccessDenied) ]]; then - textInfo "Trail $trail in $TRAIL_REGION Access Denied getting bucket acl for $CLOUDTRAILBUCKET" "$regx" "$trail" - continue - fi - - if [[ -z $CLOUDTRAILBUCKET_HASALLPERMISIONS ]]; then - textPass "Trail $trail in $TRAIL_REGION S3 logging bucket $CLOUDTRAILBUCKET is not publicly accessible" "$regx" "$trail" - else - textFail "Trail $trail in $TRAIL_REGION S3 logging bucket $CLOUDTRAILBUCKET is publicly accessible" "$regx" "$trail" - fi + if [[ ! $CLOUDTRAILBUCKET_HASALLPERMISIONS ]]; then + textPass "$regx: Trail ${TRAIL_NAME} with home region ${TRAIL_HOME_REGION} S3 logging bucket $TRAIL_BUCKET is not publicly accessible" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Trail ${TRAIL_NAME} with home region ${TRAIL_HOME_REGION} S3 logging bucket $TRAIL_BUCKET is publicly accessible" "$regx" "$TRAIL_NAME" + fi + done <<< "${REGION_TRAIL}" done + else + textPass "$regx: No trails found in the region" "$regx" fi - if [[ $trail_count == 0 ]]; then - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" - fi + done + } diff --git a/checks/check24 b/checks/check24 index b117124d86..dcd0190ba0 100644 --- a/checks/check24 +++ b/checks/check24 @@ -27,40 +27,34 @@ CHECK_DOC_check24='https://docs.aws.amazon.com/awscloudtrail/latest/userguide/se CHECK_CAF_EPIC_check24='Logging and Monitoring' check24(){ - trail_count=0 - # "Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored)" for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion, ARN:TrailARN}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) - - LATESTDELIVERY_TIMESTAMP=$($AWSCLI cloudtrail get-trail-status --name $trail $PROFILE_OPT --region $TRAIL_REGION --query 'LatestCloudWatchLogsDeliveryTime' --output text|grep -v None) - if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then - textFail "$TRAIL_REGION: $trail trail is not logging in the last 24h or not configured (it is in $TRAIL_REGION)" "$TRAIL_REGION" "$trail" - else - LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) - HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) - if [ $HOWOLDER -gt "1" ];then - textFail "$TRAIL_REGION: $trail trail is not logging in the last 24h or not configured" "$TRAIL_REGION" "$trail" + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_ARN TRAIL_HOME_REGION TRAIL_NAME + do + LATESTDELIVERY_TIMESTAMP=$(${AWSCLI} cloudtrail get-trail-status ${PROFILE_OPT} --region ${regx} --name ${TRAIL_ARN} --query LatestCloudWatchLogsDeliveryTime --output text|grep -v None) + if [[ ! $LATESTDELIVERY_TIMESTAMP ]];then + textFail "$regx: $TRAIL_NAME trail is not logging in the last 24h or not configured (its home region is $TRAIL_HOME_REGION)" "$regx" "$trail" else - textPass "$TRAIL_REGION: $trail trail has been logging during the last 24h" "$TRAIL_REGION" "$trail" + LATESTDELIVERY_DATE=$(timestamp_to_date $LATESTDELIVERY_TIMESTAMP) + HOWOLDER=$(how_older_from_today $LATESTDELIVERY_DATE) + if [ $HOWOLDER -gt "1" ];then + textFail "$regx: $TRAIL_NAME trail is not logging in the last 24h or not configured" "$regx" "$TRAIL_NAME" + else + textPass "$regx: $TRAIL_NAME trail has been logging during the last 24h" "$regx" "$TRAIL_NAME" + fi fi - fi - + done <<< "${REGION_TRAIL}" done - fi - if [[ $trail_count == 0 ]]; then - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" + else + textFail "$regx: No CloudTrail trails were found for the region" "${regx}" "No trails found" fi done } diff --git a/checks/check26 b/checks/check26 index 6e81868838..13137f85f5 100644 --- a/checks/check26 +++ b/checks/check26 @@ -26,68 +26,126 @@ CHECK_DOC_check26='https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best CHECK_CAF_EPIC_check26='Logging and Monitoring' check26(){ - trail_count=0 - # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" - for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + # trail_count=0 + # # "Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored)" + # for regx in $REGIONS; do + # TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') + # if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then + # textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + # continue + # fi + # if [[ $TRAILS_AND_REGIONS ]]; then + # for reg_trail in $TRAILS_AND_REGIONS; do + # TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) + # if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region + # continue + # fi + # trail=$(echo $reg_trail | cut -d',' -f2) + # trail_count=$((trail_count + 1)) + + # CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].[S3BucketName]' --output text --trail-name-list $trail) + # if [[ -z $CLOUDTRAILBUCKET ]]; then + # textFail "$regx: Trail $trail does not publish to S3" "$TRAIL_REGION" "$trail" + # continue + # fi + + # CLOUDTRAIL_ACCOUNT_ID=$(echo $trail | awk -F: '{ print $5 }') + # if [ "$CLOUDTRAIL_ACCOUNT_ID" != "$ACCOUNT_NUM" ]; then + # textInfo "$regx: Trail $trail S3 logging bucket $CLOUDTRAILBUCKET is not in current account" "$TRAIL_REGION" "$trail" + # continue + # fi + + # # + # # LOCATION - requests referencing buckets created after March 20, 2019 + # # must be made to S3 endpoints in the same region as the bucket was + # # created. + # # + # BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $CLOUDTRAILBUCKET --output text 2>&1) + # if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then + # textInfo "$regx: Trail $trail Access Denied getting bucket location for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" + # continue + # fi + # if [[ $BUCKET_LOCATION == "None" ]]; then + # BUCKET_LOCATION="us-east-1" + # fi + # if [[ $BUCKET_LOCATION == "EU" ]]; then + # BUCKET_LOCATION="eu-west-1" + # fi + + # CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $CLOUDTRAILBUCKET $PROFILE_OPT --region $BUCKET_LOCATION --query 'LoggingEnabled.TargetBucket' --output text 2>&1) + # if [[ $(echo "$CLOUDTRAILBUCKET_LOGENABLED" | grep AccessDenied) ]]; then + # textInfo "$regx: Trail $trail Access Denied getting bucket logging for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" + # continue + # fi + + # if [[ $CLOUDTRAILBUCKET_LOGENABLED != "None" ]]; then + # textPass "$regx: Trail $trail S3 bucket access logging is enabled for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" + # else + # textFail "$regx: Trail $trail S3 bucket access logging is not enabled for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" + # fi + + # done + # fi + # if [[ $trail_count == 0 ]]; then + # textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" + # fi + # done + + for regx in $REGIONS + do + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, HomeRegion:HomeRegion, Multiregion:IsMultiRegionTrail, BucketName:S3BucketName}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_BUCKET TRAIL_HOME_REGION IS_MULTIREGION TRAIL_NAME + do + if [[ ! "${TRAIL_BUCKET}" ]] + then + if [[ "${IS_MULTIREGION}" == "True" ]] + then + textFail "$regx: Multiregion trail ${TRAIL_NAME} configured from region ${TRAIL_HOME_REGION} does not publish to S3" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Single region trail ${TRAIL_NAME} does not publish to S3" "$regx" "$TRAIL_NAME" + fi + continue + fi - CLOUDTRAILBUCKET=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].[S3BucketName]' --output text --trail-name-list $trail) - if [[ -z $CLOUDTRAILBUCKET ]]; then - textFail "$regx: Trail $trail does not publish to S3" "$TRAIL_REGION" "$trail" - continue - fi + BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $TRAIL_BUCKET --output text 2>&1) + if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]] + then + textInfo "$regx: Trail ${TRAIL_NAME} with home region ${TRAIL_HOME_REGION} Access Denied getting bucket location for bucket $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + continue + fi + if [[ $BUCKET_LOCATION == "None" ]]; then + BUCKET_LOCATION="us-east-1" + fi + if [[ $BUCKET_LOCATION == "EU" ]]; then + BUCKET_LOCATION="eu-west-1" + fi - CLOUDTRAIL_ACCOUNT_ID=$(echo $trail | awk -F: '{ print $5 }') - if [ "$CLOUDTRAIL_ACCOUNT_ID" != "$ACCOUNT_NUM" ]; then - textInfo "$regx: Trail $trail S3 logging bucket $CLOUDTRAILBUCKET is not in current account" "$TRAIL_REGION" "$trail" - continue - fi + CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $TRAIL_BUCKET $PROFILE_OPT --region $BUCKET_LOCATION --query 'LoggingEnabled.TargetBucket' --output text 2>&1) + if [[ $(echo "$CLOUDTRAILBUCKET_LOGENABLED" | grep AccessDenied) ]]; then + textInfo "$regx: Trail $TRAIL_NAME Access Denied getting bucket logging for $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + continue + fi - # - # LOCATION - requests referencing buckets created after March 20, 2019 - # must be made to S3 endpoints in the same region as the bucket was - # created. - # - BUCKET_LOCATION=$($AWSCLI s3api get-bucket-location $PROFILE_OPT --region $regx --bucket $CLOUDTRAILBUCKET --output text 2>&1) - if [[ $(echo "$BUCKET_LOCATION" | grep AccessDenied) ]]; then - textInfo "$regx: Trail $trail Access Denied getting bucket location for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" - continue - fi - if [[ $BUCKET_LOCATION == "None" ]]; then - BUCKET_LOCATION="us-east-1" - fi - if [[ $BUCKET_LOCATION == "EU" ]]; then - BUCKET_LOCATION="eu-west-1" - fi + if [[ $CLOUDTRAILBUCKET_LOGENABLED != "None" ]]; then + textPass "$regx: Trail $TRAIL_NAME S3 bucket access logging is enabled for $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Trail $TRAIL_NAME S3 bucket access logging is not enabled for $TRAIL_BUCKET" "$regx" "$TRAIL_NAME" + fi - CLOUDTRAILBUCKET_LOGENABLED=$($AWSCLI s3api get-bucket-logging --bucket $CLOUDTRAILBUCKET $PROFILE_OPT --region $BUCKET_LOCATION --query 'LoggingEnabled.TargetBucket' --output text 2>&1) - if [[ $(echo "$CLOUDTRAILBUCKET_LOGENABLED" | grep AccessDenied) ]]; then - textInfo "$regx: Trail $trail Access Denied getting bucket logging for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" - continue - fi - - if [[ $CLOUDTRAILBUCKET_LOGENABLED != "None" ]]; then - textPass "$regx: Trail $trail S3 bucket access logging is enabled for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" - else - textFail "$regx: Trail $trail S3 bucket access logging is not enabled for $CLOUDTRAILBUCKET" "$TRAIL_REGION" "$trail" - fi + done <<< "${REGION_TRAIL}" done + else + textPass "$regx: No trails found in the region" "$regx" fi - if [[ $trail_count == 0 ]]; then - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" - fi + done } diff --git a/checks/check27 b/checks/check27 index 0a5530db01..3db57ad645 100644 --- a/checks/check27 +++ b/checks/check27 @@ -27,33 +27,28 @@ CHECK_DOC_check27='https://docs.aws.amazon.com/awscloudtrail/latest/userguide/en CHECK_CAF_EPIC_check27='Logging and Monitoring' check27(){ - trail_count=0 - # "Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored)" for regx in $REGIONS; do - TRAILS_AND_REGIONS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:TrailARN, HomeRegion:HomeRegion}' --output text 2>&1 | tr " " ',') - if [[ $(echo "$TRAILS_AND_REGIONS" | grep AccessDenied) ]]; then - textInfo "$regx: Access Denied trying to describe trails" "$regx" "$trail" + TRAILS_DETAILS=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $regx --query 'trailList[*].{Name:Name, KeyID:KmsKeyId}' --output text 2>&1) + if [[ $(echo "$TRAILS_DETAILS" | grep AccessDenied) ]]; then + textInfo "$regx: Access Denied trying to describe trails" "$regx" continue fi - if [[ $TRAILS_AND_REGIONS ]]; then - for reg_trail in $TRAILS_AND_REGIONS; do - TRAIL_REGION=$(echo $reg_trail | cut -d',' -f1) - if [ $TRAIL_REGION != $regx ]; then # Only report trails once in home region - continue - fi - trail=$(echo $reg_trail | cut -d',' -f2) - trail_count=$((trail_count + 1)) - - KMSKEYID=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $TRAIL_REGION --query 'trailList[*].KmsKeyId' --output text --trail-name-list $trail) - if [[ "$KMSKEYID" ]];then - textPass "$regx: Trail $trail has encryption enabled" "$regx" "$trail" - else - textFail "$regx: Trail $trail has encryption disabled" "$regx" "$trail" - fi + if [[ $TRAILS_DETAILS ]] + then + for REGION_TRAIL in "${TRAILS_DETAILS}" + do + while read -r TRAIL_KEY_ID TRAIL_NAME + do + if [[ "${TRAIL_KEY_ID}" != "None" ]] + then + textPass "$regx: Trail $TRAIL_NAME has encryption enabled" "$regx" "$TRAIL_NAME" + else + textFail "$regx: Trail $TRAIL_NAME has encryption disabled" "$regx" "$TRAIL_NAME" + fi + done <<< "${REGION_TRAIL}" done - fi - if [[ $trail_count == 0 ]]; then - textFail "$regx: No CloudTrail trails were found in the account" "$regx" "$trail" + else + textPass "$regx: No CloudTrail trails were found for the region" "${regx}" "No trails found" fi done }