#!/usr/bin/env bash
PROGNAME="${0##*/}"

set +u
shopt -s xpg_echo

SYNTAX_MSG="$PROGNAME N   where N is number of days to report on, default 1"

REPORT_DAYS=1
case $# in
  0);;
  1)
    case "$1" in *[^0-9]*)
      echo "Number of days not an integer.\n$SYNTAX_MSG" 1>&2; exit 2;;
    esac
    REPORT_DAYS=$1
    shift;;
  '') echo "$SYNTAX_MSG" 1>&2; exit 2;;
  *) echo "$SYNTAX_MSG" 1>&2; exit 2;;
esac

# The - 5*60*10,000,000  allows 5 minutes overlap to allow for
# the time it takes this to run.
# The time conversions convert from internal integers in 100 nanoseconds
# to seconds and then to days via:
#   24 hours/day * 3600 secs/hour * 10,000,000 100nanosecond/second

[ -d $HOME/cis/work ] || mkdir -p $HOME/cis/work
retval=0

# N.b. --file switch only works along with --csv switch!

# This block checks for failures in DiscoveryRun records
OUTFILE=$HOME/cis/work/dr.csv
ERRFILE=$HOME/cis/work/dr.err
rm -f $OUTFILE
twwrap query --csv --file=$OUTFILE "
    SEARCH DiscoveryRun
    WHERE starttime > currentTime() - $REPORT_DAYS * 24*3600*10000000 - 5*60*10000000
      AND failure_reason IS defined OR has_eca_error <> true
      AND hard_failure <> true
    SHOW failure_reason, has_eca_error, hard_failure, summary
" > $ERRFILE 2>&1
grep -qFxv 'ERROR: No results!' $ERRFILE && {
    retval=1
    echo 'DiscoveryRun Query Invocation Failure'
    cat $ERRFILE
}
[ -s $OUTFILE ] && {
    retval=1
    echo 'DiscoveryRun Failures'
    perl -pe 's/\r//g;' $OUTFILE
}

# This block checks for failures in DiscoveryAccess records
OUTFILE=$HOME/cis/work/da.csv
ERRFILE=$HOME/cis/work/da.err
rm -f $OUTFILE
twwrap query --csv --file=$OUTFILE "
    SEARCH DiscoveryAccess
    WHERE starttime > currentTime() - $REPORT_DAYS * 24*3600*10000000 - 5*60*10000000
      AND result in ["Error", "NoResponse"]
" > $ERRFILE 2>&1
grep -qFxv 'ERROR: No results!' $ERRFILE && {
    retval=1
    echo 'DiscoveryAccess Query Invocation Failure'
    cat $ERRFILE
}
[ -s $OUTFILE ] && {
    [ $retval -gt 0 ] && echo
    echo 'DiscoveryAccess Failures'
    retval=1
    perl -pe 's/\r//g;' $OUTFILE
# This block checks for failures in DiscoveryAccess records
}

# Remaining checks are for DiscoveryCloudAPIResultList record failures.
# For maintenance purposes, optimized the shared queries (currently
# 'Cloud API Failures...') and copy the results here.

# For now checking only us-east-1 because scans of the other regions are
# too noisy.
# Query here copied from shared query "Cloud API Failures / us-east-1".
# (after the $REPORT_DAYS line, since variable subst. not supported in shared qs)
OUTFILE=$HOME/cis/work/api.csv
ERRFILE=$HOME/cis/work/api.err
rm -f $OUTFILE
twwrap query --csv --file=$OUTFILE "
SEARCH DiscoveredCloudAPIResultList
WITH #DiscoveryResult:Metadata:Detail:ScriptFailure AS sf
WHERE request_time > currentTime() - $REPORT_DAYS * 24*3600*10000000 - 5*60*10000000 "'
    AND #DiscoveryResult:DiscoveryAccessResult:DiscoveryAccess:DiscoveryAccess.region = "us-east-1"
    AND method_failure defined
    AND NOT discovery_method matches "^AWS[.]Organizations[.]List"
    AND NOT sf.message has substring "An error occurred (NoSuchTagSet) when calling the GetBucketTagging operation: The TagSet does not exist"
    AND sf.message not matches regex "^An error occurred \(AccessDeniedException\) when calling the DescribeParameters operation: User: \S+ is not authorized to perform: ssm:DescribeParameters on resource: arn:aws:ssm:\S+:[*]$"
    AND sf.message not matches regex "[(]AccessDenied[)].+\bcloudfront:\w+$"
    // EXTRA non-us-east-1 criteria:  (between this line and the SHOW line:
    AND NOT sf.message matches "^Could not connect to the endpoint URL:"
    AND NOT sf.message matches "^The security token included in the request is invalid$"
    SHOW discovery_method, failure_reason, request_time,
    #DiscoveryResult:DiscoveryAccessResult:DiscoveryAccess:DiscoveryAccess.#Member:List:List:DiscoveryRun.label as Scan,
    #DiscoveryResult:DiscoveryAccessResult:DiscoveryAccess:DiscoveryAccess.region as Region,
    sf.message as "Script Message",
    nodecount(traverse DiscoveryResult:Metadata:Detail:CommandFailure) as "CF Count"
' > $ERRFILE 2>&1
grep -qFxv 'ERROR: No results!' $ERRFILE && {
    retval=1
    echo 'API Query Invocation Failure'
    cat $ERRFILE
}
[ -s $OUTFILE ] && {
    [ $retval -gt 0 ] && echo
    echo 'API Failures'
    retval=1
    perl -pe 's/\r//g;' $OUTFILE
}

exit $retval
