#!/usr/bin/env bash # Prowler - the handy cloud security tool (c) by Toni de la Fuente # # This Prowler check is licensed under a # Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. # # You should have received a copy of the license along with this # work. If not, see . CHECK_ID_check31="3.1,3.01" CHECK_TITLE_check31="[check31] Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" CHECK_SCORED_check31="SCORED" CHECK_TYPE_check31="LEVEL1" CHECK_ALTERNATE_check301="check31" check31(){ # "Ensure a log metric filter and alarm exist for unauthorized API calls (Scored)" CLOUDWATCH_GROUP=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text| tr ' ' ' ' | awk -F: '{ print $7 }') if [[ $CLOUDWATCH_GROUP ]];then for group in $CLOUDWATCH_GROUP; do CLOUDWATCH_LOGGROUP_REGION=$($AWSCLI cloudtrail describe-trails $PROFILE_OPT --region $REGION --query 'trailList[*].CloudWatchLogsLogGroupArn' --output text | tr ' ' ' ' | grep $group | awk -F: '{ print $4 }') #METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'metricFilters' | awk '/UnauthorizedOperation/ || /AccessDenied/ {print $3}') METRICFILTER_SET=$($AWSCLI logs describe-metric-filters --log-group-name $group $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --output text | grep METRICFILTERS | awk 'BEGIN {IGNORECASE=1}; /UnauthorizedOperation/ || /AccessDenied/ {print $3};') if [[ $METRICFILTER_SET ]];then for metric in $METRICFILTER_SET; do metric_name=$($AWSCLI logs describe-metric-filters $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --log-group-name $group --filter-name-prefix $metric --output text --query 'metricFilters[0].metricTransformations[0].metricName') HAS_ALARM_ASSOCIATED=$($AWSCLI cloudwatch describe-alarms $PROFILE_OPT --region $CLOUDWATCH_LOGGROUP_REGION --query 'MetricAlarms[?MetricName==`'$metric_name'`]' --output text) if [[ $HAS_ALARM_ASSOCIATED ]];then CHECK31OK="$CHECK31OK $group:$metric" else CHECK31WARN="$CHECK31WARN $group:$metric" fi done else CHECK31WARN="$CHECK31WARN $group" fi done if [[ $CHECK31OK ]]; then for group in $CHECK31OK; do metric=${group#*:} group=${group%:*} textPass "CloudWatch group $group found with metric filter $metric and alarms set for Unauthorized Operation and Access Denied" done fi if [[ $CHECK31WARN ]]; then for group in $CHECK31WARN; do case $group in *:*) metric=${group#*:} group=${group%:*} textFail "CloudWatch group $group found with metric filter $metric but no alarms associated" ;; *) textFail "CloudWatch group $group found but no metric filters or alarms associated" esac done fi else textFail "No CloudWatch group found for CloudTrail events" fi }