#!/usr/bin/env bash
# Author : Madhu Balaji
# Description : This script will look for all the assessment reports for each application in a
# specific region , describe the assessment , fetch reports, create summary report (html) and upload the artifacts to S3 bucket specified
# Pre-req : Required Roles assigned to the user/profile used for execution, AWS CLI and jq
Region="x"
S3Bucket="x"
HTMLContent=""
# Exception - Throw error
function throw(){
tput setaf 1; echo "Failure: $*" && tput sgr0
exit 1
}
# Input var0
if [[ "$Region" == "x" ]]; then
read -r -p "Region [us-east-1] : " Region
fi
if [ -z "$Region" ]; then
Region="us-east-1"
fi
# Input var1
# Validate Input params
if [[ "$S3Bucket" == "x" ]]; then
read -r -p "S3 Bucket Name : " S3Bucket
fi
if [ -z "$S3Bucket" ]; then
throw "S3 bucket name is mandatory."
fi
# Check Command to validate required libraries
function check_command {
type -P $1 &>/dev/null || throw "Unable to find $1, please install it and run this script again."
}
# Verify if AWS CLI Credentials are setup
if ! grep -q aws_access_key_id ~/.aws/config; then
if ! grep -q aws_access_key_id ~/.aws/credentials; then
throw "AWS config not found or CLI not installed. Please run \"aws configure\"."
fi
fi
# Verify AWS CLI profile
if [ $# -eq 0 ]; then
scriptname=`basename "$0"`
echo "Usage: ./$scriptname profile"
echo "Where profile is the AWS CLI profile name"
echo "Using default profile"
echo
profile=default
else
profile=$1
fi
# Check required commands
check_command "aws"
check_command "jq"
#Not working 100%- Fix this
function createbucket(){
aws s3 mb s3://$S3Bucket --region $Region
}
#Delete local JSON file (optional)
function deleteJSONFile(){
rm -rf ./*.json
}
#Delete local report file (optional)
function deleteHTMLFile(){
rm -rf ./*.html
}
function createHTMLTemplate(){
HEADER="
"
BODY=" AWS Resilience Hub Assessment Report "
TABLE=" region
App Name | App Compliance Status | Assessment Name | Assessment Compliance Status | Resiliency Score | Start Time | End Time |
"
FOOTER="
"
TR=""
TD=""
CLSTD=" | "
CLSTR="
"
EMPTYTD=" | "
TDCOL4=""
}
#Main Function to download assessment reports
function GetAppAssessments(){
# Create S3 bucket if it does't exists
createbucket
# List all the app assessments in a region
Assessments=$(aws resiliencehub list-app-assessments --region $Region --output=json --profile $profile --query 'sort_by(assessmentSummaries, &appArn)[].{appArn: appArn,assessmentArn: assessmentArn, complianceStatus: complianceStatus,resiliencyScore: resiliencyScore}' 2>&1)
#echo $Assessments > "applicationSummaries.json"
#Initialize HTMl content
createHTMLTemplate
#Loop thru all the assessments to extract content, create JSON and Summary HTML, upload to S3 bucket
counter=0
SUMMARYTBL=""
FolderName=$(date +%Y%m%d%H%M)
echo $Assessments >> "assessment_list.json"
for row in $(echo "${Assessments}" | jq -r '.[] | @base64'); do
_jq() {
echo "${row}" | base64 --decode | jq -r "${1}"
}
apparn=$(_jq '.appArn')
assessmentArn=$(_jq '.assessmentArn')
resiliencyScore=$(_jq '.resiliencyScore')
AppCompStatus=$(_jq '.complianceStatus')
if [ "$AppCompStatus" == 'PolicyBreached' ]; then
AppCompStatus="$AppCompStatus"
elif [ "$AppCompStatus" == 'PolicyMet' ]; then
AppCompStatus="$AppCompStatus"
fi
ROWCONTENT=""
AppName=$(aws resiliencehub describe-app --app-arn $apparn --region $Region --profile $profile --query 'app.name' 2>&1)
AName=${AppName:1:${#AppName}-2}
DescribeAssessment=$(aws resiliencehub describe-app-assessment --assessment-arn $assessmentArn --region $Region --profile $profile 2>&1)
AssessName=$(echo "$DescribeAssessment" | jq -r '.assessment | .assessmentName')
CompStatus=$(echo "$DescribeAssessment" | jq -r '.assessment | .complianceStatus')
if [ "$CompStatus" == 'PolicyBreached' ]; then
CompStatus="$CompStatus"
elif [ "$CompStatus" == 'PolicyMet' ]; then
CompStatus="$CompStatus"
fi
StartTime=$(echo "$DescribeAssessment" | jq -r '.assessment | .startTime')
EndTime=$(echo "$DescribeAssessment" | jq -r '.assessment | .endTime')
AZRTOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .AZ | .rtoInSecs')
AZRPOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .AZ | .rpoInSecs')
HWRTOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Hardware | .rtoInSecs')
HWRPOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Hardware | .rpoInSecs')
SWRTOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Software | .rtoInSecs')
SWRPOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Software | .rpoInSecs')
REGRTOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Region | .rtoInSecs')
REGRPOTarget=$(echo "$DescribeAssessment" | jq -r '.assessment | .policy | .policy | .Region | .rpoInSecs')
ROWCONTENT=$TR$TD$AName$CLSTD$TD$ROWCONTENT$AppCompStatus$CLSTD$TD$ROWCONTENT$AssessName$CLSTD$TD$ROWCONTENT$CompStatus$CLSTDSTD$TD$ROWCONTENT$resiliencyScore$CLSTD$TD$ROWCONTENT$StartTime$CLSTD$TD$ROWCONTENT$EndTime$CLSTD$CLSTR
SUBROW=""
UNREC="2592001"
Results=$(aws resiliencehub list-app-component-compliances --assessment-arn $assessmentArn --region $Region --profile $profile 2>&1)
ARNNAME=${assessmentArn:(-36)}
echo $Results >> "assessment-components-"$ARNNAME".json"
Output=$(echo "$Results" | jq -r '.componentCompliances')
ROWCONTENT=$ROWCONTENT$TR$EMPTYTD" | "
SUBROW="Component Name | Application | Infrastructure | Availability Zone | Region | "
ADDSUBROW=" | Targeted RTO(s) | Estimated RTO(s) | Targeted RPO(s) | Estimated RPO(s) | Targeted RTO(s) | Estimated RTO(s) | Targeted RPO(s) | Estimated RPO(s) | Targeted RTO(s) | Estimated RTO(s) | Targeted RPO(s) | Estimated RPO(s) | Targeted RTO(s) | Estimated RTO(s) | Targeted RPO(s) | Estimated RPO(s) | "
SUBROW=$SUBROW$ADDSUBROW
for row in $(echo "${Output}" | jq -r '.[] | @base64'); do
_jqr() {
echo "${row}" | base64 --decode | jq -r "${1}"
}
componentName=$(_jqr '.appComponentName')
AZRTOEstimate=$(_jqr '.compliance.AZ.currentRtoInSecs')
if [ "$AZRTOEstimate" == "$UNREC" ]; then
AZRTOEstimate="unrecoverable"
fi
AZRTODesc=$(_jqr '.compliance.AZ.rtoDescription')
AZRPODesc=$(_jqr '.compliance.AZ.rpoDescription')
AZRPOEstimate=$(_jqr '.compliance.AZ.currentRpoInSecs')
if [ "$AZRPOEstimate" == "$UNREC" ]; then
AZRPOEstimate="unrecoverable"
fi
HWRTOEstimate=$(_jqr '.compliance.Hardware.currentRtoInSecs')
if [ "$HWRTOEstimate" == "$UNREC" ]; then
HWRTOEstimate="unrecoverable"
fi
HWRTODesc=$(_jqr '.compliance.Hardware.rtoDescription')
HWRPODesc=$(_jqr '.compliance.Hardware.rpoDescription')
HWRPOEstimate=$(_jqr '.compliance.Hardware.currentRpoInSecs')
if [ "$HWRPOEstimate" == "$UNREC" ]; then
HWRPOEstimate="unrecoverable"
fi
SWRTOEstimate=$(_jqr '.compliance.Software.currentRtoInSecs')
if [ "$SWRTOEstimate" == "$UNREC" ]; then
SWRTOEstimate="unrecoverable"
fi
SWRTODesc=$(_jqr '.compliance.Software.rtoDescription')
SWRPODesc=$(_jqr '.compliance.Software.rpoDescription')
SWRPOEstimate=$(_jqr '.compliance.Software.currentRpoInSecs')
if [ "$SWRPOEstimate" == "$UNREC" ]; then
SWRPOEstimate="unrecoverable"
fi
REGRTOEstimate=$(_jqr '.compliance.Region.currentRtoInSecs')
if [ "$REGRTOEstimate" == "$UNREC" ]; then
REGRTOEstimate="unrecoverable"
fi
REGRTODesc=$(_jqr '.compliance.Region.rtoDescription')
REGRPODesc=$(_jqr '.compliance.Region.rpoDescription')
REGRPOEstimate=$(_jqr '.compliance.Region.currentRpoInSecs')
if [ "$REGRPOEstimate" == "$UNREC" ]; then
REGRPOEstimate="unrecoverable"
fi
SUBROW=$SUBROW$TR$TDCOL4$componentName$CLSTD$TD$SWRTOTarget$CLSTD$TD$SWRTOEstimate$CLSTD$TD$SWRPOTarget$CLSTD$TD$SWRPOEstimate$CLSTD
SUBROW=$SUBROW$TD$HWRTOTarget$CLSTD$TD$HWRTOEstimate$CLSTD$TD$HWRPOTarget$CLSTD$TD$HWRPOEstimate$CLSTD
SUBROW=$SUBROW$TD$AZRTOTarget$CLSTD$TD$AZRTOEstimate$CLSTD$TD$AZRPOTarget$CLSTD$TD$AZRPOEstimate$CLSTD
SUBROW=$SUBROW$TD$REGRTOTarget$CLSTD$TD$REGRTOEstimate$CLSTD$TD$REGRPOTarget$CLSTD$TD$REGRPOEstimate$CLSTD$CLSTR
done
SUBROW=$SUBROW" "
ROWCONTENT=$ROWCONTENT$SUBROW$CLSTD$CLSTR
Filename="assessment-"$ARNNAME
echo $DescribeAssessment > $Filename.json
aws s3 cp ./$Filename'.json' 's3://'$S3Bucket'/reports'$FolderName'/'$Filename'.json' --region $Region --profile $profile 2>&1
EMPTYROW=" | |
"
SUMMARYTBL=$SUMMARYTBL$ROWCONTENT$EMPTYROW$EMPTYROW
counter=$[$counter +1]
done
HTMLFILE=$HEADER$BODY$Region$TABLE$SUMMARYTBL$FOOTER
echo $HTMLFILE > 'report.html'
aws s3 cp ./report.html 's3://'$S3Bucket'/reports'$FolderName'/report.html' --region $Region
#Optional cleanup - Delete JSON and HTML files generated locally. Comment it if you want to persist local copy
deleteJSONFile
deleteHTMLFile
}
GetAppAssessments