From a21bff31a5931f5149d132c9637f1f1420bf2152 Mon Sep 17 00:00:00 2001 From: Toni de la Fuente Date: Tue, 20 Mar 2018 22:59:34 -0400 Subject: [PATCH] create check files --- checks/check | 0 checks/check11 | 2 +- checks/check110 | 0 checks/check111 | 0 checks/check112 | 0 checks/check113 | 0 checks/check114 | 0 checks/check115 | 0 checks/check116 | 0 checks/check117 | 0 checks/check118 | 0 checks/check119 | 0 checks/check12 | 25 +++ checks/check120 | 0 checks/check121 | 0 checks/check122 | 0 checks/check123 | 0 checks/check124 | 0 checks/check13 | 0 checks/check14 | 0 checks/check15 | 0 checks/check16 | 0 checks/check17 | 0 checks/check18 | 0 checks/check19 | 0 checks/check21 | 0 checks/check22 | 0 checks/check23 | 0 checks/check24 | 0 checks/check25 | 0 checks/check26 | 0 checks/check27 | 0 checks/check28 | 0 checks/check31 | 0 checks/check310 | 0 checks/check311 | 0 checks/check312 | 0 checks/check313 | 0 checks/check314 | 0 checks/check315 | 0 checks/check32 | 0 checks/check33 | 0 checks/check34 | 0 checks/check35 | 0 checks/check36 | 0 checks/check37 | 0 checks/check38 | 0 checks/check39 | 0 checks/check41 | 0 checks/check42 | 0 checks/check43 | 0 checks/check44 | 0 checks/check45 | 0 checks/check_extra71 | 0 checks/check_extra710 | 0 checks/check_extra711 | 0 checks/check_extra712 | 0 checks/check_extra713 | 0 checks/check_extra714 | 0 checks/check_extra715 | 0 checks/check_extra716 | 0 checks/check_extra717 | 0 checks/check_extra718 | 0 checks/check_extra719 | 0 checks/check_extra72 | 0 checks/check_extra720 | 0 checks/check_extra721 | 0 checks/check_extra722 | 0 checks/check_extra723 | 0 checks/check_extra73 | 0 checks/check_extra74 | 0 checks/check_extra75 | 0 checks/check_extra76 | 0 checks/check_extra77 | 0 checks/check_extra78 | 0 checks/check_extra79 | 0 checks/list | 166 ++++++++++++++++++ checks/lista | 79 +++++++++ groups/group1 | 6 +- groups/group2 | 0 groups/group3 | 0 groups/group4 | 0 groups/group_cislevel1 | 0 groups/group_cislevel2 | 0 groups/group_extras | 0 groups/group_forensics | 0 include/aws_profile_loader | 22 +++ include/awscli_detector | 7 + include/banner | 19 +++ include/colors | 58 +++++++ include/credentials_report | 26 +++ include/csv_header | 5 + include/os_detector | 76 +++++++++ include/outputs | 81 +++++++++ include/whoami | 44 +++++ prowler => prowler1 | 0 prowler2 | 334 +++---------------------------------- 97 files changed, 635 insertions(+), 315 deletions(-) create mode 100644 checks/check create mode 100644 checks/check110 create mode 100644 checks/check111 create mode 100644 checks/check112 create mode 100644 checks/check113 create mode 100644 checks/check114 create mode 100644 checks/check115 create mode 100644 checks/check116 create mode 100644 checks/check117 create mode 100644 checks/check118 create mode 100644 checks/check119 create mode 100644 checks/check12 create mode 100644 checks/check120 create mode 100644 checks/check121 create mode 100644 checks/check122 create mode 100644 checks/check123 create mode 100644 checks/check124 create mode 100644 checks/check13 create mode 100644 checks/check14 create mode 100644 checks/check15 create mode 100644 checks/check16 create mode 100644 checks/check17 create mode 100644 checks/check18 create mode 100644 checks/check19 create mode 100644 checks/check21 create mode 100644 checks/check22 create mode 100644 checks/check23 create mode 100644 checks/check24 create mode 100644 checks/check25 create mode 100644 checks/check26 create mode 100644 checks/check27 create mode 100644 checks/check28 create mode 100644 checks/check31 create mode 100644 checks/check310 create mode 100644 checks/check311 create mode 100644 checks/check312 create mode 100644 checks/check313 create mode 100644 checks/check314 create mode 100644 checks/check315 create mode 100644 checks/check32 create mode 100644 checks/check33 create mode 100644 checks/check34 create mode 100644 checks/check35 create mode 100644 checks/check36 create mode 100644 checks/check37 create mode 100644 checks/check38 create mode 100644 checks/check39 create mode 100644 checks/check41 create mode 100644 checks/check42 create mode 100644 checks/check43 create mode 100644 checks/check44 create mode 100644 checks/check45 create mode 100644 checks/check_extra71 create mode 100644 checks/check_extra710 create mode 100644 checks/check_extra711 create mode 100644 checks/check_extra712 create mode 100644 checks/check_extra713 create mode 100644 checks/check_extra714 create mode 100644 checks/check_extra715 create mode 100644 checks/check_extra716 create mode 100644 checks/check_extra717 create mode 100644 checks/check_extra718 create mode 100644 checks/check_extra719 create mode 100644 checks/check_extra72 create mode 100644 checks/check_extra720 create mode 100644 checks/check_extra721 create mode 100644 checks/check_extra722 create mode 100644 checks/check_extra723 create mode 100644 checks/check_extra73 create mode 100644 checks/check_extra74 create mode 100644 checks/check_extra75 create mode 100644 checks/check_extra76 create mode 100644 checks/check_extra77 create mode 100644 checks/check_extra78 create mode 100644 checks/check_extra79 create mode 100644 checks/list create mode 100644 checks/lista create mode 100644 groups/group2 create mode 100644 groups/group3 create mode 100644 groups/group4 create mode 100644 groups/group_cislevel1 create mode 100644 groups/group_cislevel2 create mode 100644 groups/group_extras create mode 100644 groups/group_forensics create mode 100644 include/aws_profile_loader create mode 100644 include/awscli_detector create mode 100644 include/banner create mode 100644 include/credentials_report create mode 100644 include/csv_header create mode 100644 include/os_detector create mode 100644 include/outputs create mode 100644 include/whoami rename prowler => prowler1 (100%) diff --git a/checks/check b/checks/check new file mode 100644 index 00000000..e69de29b diff --git a/checks/check11 b/checks/check11 index adc5400a..457faed1 100644 --- a/checks/check11 +++ b/checks/check11 @@ -1,7 +1,7 @@ #!/usr/bin/env bash CHECK_ID[check11]="1.1,1.01" -CHECK_TITLE[check11]="Avoid the use of the root account (Scored)." +CHECK_TITLE[check11]="Avoid the use of the root account (Scored)" CHECK_SCORED[check11]="SCORED" CHECK_TYPE[check11]="LEVEL1" CHECK_ALTERNATE[check101]="check11" diff --git a/checks/check110 b/checks/check110 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check111 b/checks/check111 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check112 b/checks/check112 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check113 b/checks/check113 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check114 b/checks/check114 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check115 b/checks/check115 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check116 b/checks/check116 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check117 b/checks/check117 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check118 b/checks/check118 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check119 b/checks/check119 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check12 b/checks/check12 new file mode 100644 index 00000000..76d1dddc --- /dev/null +++ b/checks/check12 @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +CHECK_ID[check12]="1.2,1.02" +CHECK_TITLE[check12]="Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" +CHECK_SCORED[check12]="SCORED" +CHECK_TYPE[check12]="LEVEL1" +CHECK_ALTERNATE[check102]="check12" + +check12(){ + # "Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored)" + # List users with password enabled + COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED=$(cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$4 }' |grep true | awk '{ print $1 }') + COMMAND12=$( + for i in $COMMAND12_LIST_USERS_WITH_PASSWORD_ENABLED; do + cat $TEMP_REPORT_FILE|awk -F, '{ print $1,$8 }' |grep "$i " |grep false | awk '{ print $1 }' + done) + textTitle "$ID12" "$TITLE12" "SCORED" "LEVEL1" + if [[ $COMMAND12 ]]; then + for u in $COMMAND12; do + textWarn "User $u has Password enabled but MFA disabled" + done + else + textOK "No users found with Password enabled and MFA disabled" + fi +} diff --git a/checks/check120 b/checks/check120 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check121 b/checks/check121 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check122 b/checks/check122 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check123 b/checks/check123 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check124 b/checks/check124 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check13 b/checks/check13 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check14 b/checks/check14 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check15 b/checks/check15 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check16 b/checks/check16 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check17 b/checks/check17 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check18 b/checks/check18 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check19 b/checks/check19 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check21 b/checks/check21 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check22 b/checks/check22 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check23 b/checks/check23 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check24 b/checks/check24 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check25 b/checks/check25 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check26 b/checks/check26 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check27 b/checks/check27 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check28 b/checks/check28 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check31 b/checks/check31 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check310 b/checks/check310 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check311 b/checks/check311 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check312 b/checks/check312 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check313 b/checks/check313 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check314 b/checks/check314 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check315 b/checks/check315 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check32 b/checks/check32 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check33 b/checks/check33 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check34 b/checks/check34 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check35 b/checks/check35 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check36 b/checks/check36 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check37 b/checks/check37 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check38 b/checks/check38 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check39 b/checks/check39 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check41 b/checks/check41 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check42 b/checks/check42 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check43 b/checks/check43 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check44 b/checks/check44 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check45 b/checks/check45 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra71 b/checks/check_extra71 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra710 b/checks/check_extra710 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra711 b/checks/check_extra711 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra712 b/checks/check_extra712 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra713 b/checks/check_extra713 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra714 b/checks/check_extra714 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra715 b/checks/check_extra715 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra716 b/checks/check_extra716 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra717 b/checks/check_extra717 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra718 b/checks/check_extra718 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra719 b/checks/check_extra719 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra72 b/checks/check_extra72 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra720 b/checks/check_extra720 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra721 b/checks/check_extra721 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra722 b/checks/check_extra722 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra723 b/checks/check_extra723 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra73 b/checks/check_extra73 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra74 b/checks/check_extra74 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra75 b/checks/check_extra75 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra76 b/checks/check_extra76 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra77 b/checks/check_extra77 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra78 b/checks/check_extra78 new file mode 100644 index 00000000..e69de29b diff --git a/checks/check_extra79 b/checks/check_extra79 new file mode 100644 index 00000000..e69de29b diff --git a/checks/list b/checks/list new file mode 100644 index 00000000..bb66eca3 --- /dev/null +++ b/checks/list @@ -0,0 +1,166 @@ + _ + _ __ _ __ _____ _| | ___ _ __ + | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__| + | |_) | | | (_) \ V V /| | __/ | + | .__/|_| \___/ \_/\_/ |_|\___|_| + |_| CIS based AWS Account Hardening Tool + + Date: Tue Mar 20 21:50:38 EDT 2018 + + 1 Identity and Access Management **************************************** + + 1.1 Avoid the use of the root account (Scored). + + 1.2 Ensure multi-factor authentication (MFA) is enabled for all IAM users that have a console password (Scored) + + 1.3 Ensure credentials unused for 90 days or greater are disabled (Scored) + + 1.4 Ensure access keys are rotated every 90 days or less (Scored) + + 1.5 Ensure IAM password policy requires at least one uppercase letter (Scored) + + 1.6 Ensure IAM password policy require at least one lowercase letter (Scored) + + 1.7 Ensure IAM password policy require at least one symbol (Scored) + + 1.8 Ensure IAM password policy require at least one number (Scored) + + 1.9 Ensure IAM password policy requires minimum length of 14 or greater (Scored) + + 1.10 Ensure IAM password policy prevents password reuse: 24 or greater (Scored) + + 1.11 Ensure IAM password policy expires passwords within 90 days or less (Scored) + + 1.12 Ensure no root account access key exists (Scored) + + 1.13 Ensure MFA is enabled for the root account (Scored) + + 1.14 Ensure hardware MFA is enabled for the root account (Scored) + + 1.15 Ensure security questions are registered in the AWS account (Not Scored) + + 1.16 Ensure IAM policies are attached only to groups or roles (Scored) + + 1.17 Enable detailed billing (Scored) + + 1.18 Ensure IAM Master and IAM Manager roles are active (Scored) + + 1.19 Maintain current contact details (Scored) + + 1.20 Ensure security contact information is registered (Scored) + + 1.21 Ensure IAM instance roles are used for AWS resource access from instances (Not Scored) + + 1.22 Ensure a support role has been created to manage incidents with AWS Support (Scored) + + 1.23 Do not setup access keys during initial user setup for all IAM users that have a console password (Not Scored) + + 1.24 Ensure IAM policies that allow full "*:*" administrative privileges are not created (Scored) + + 2 Logging *************************************************************** + + 2.1 Ensure CloudTrail is enabled in all regions (Scored) + + 2.2 Ensure CloudTrail log file validation is enabled (Scored) + + 2.3 Ensure the S3 bucket CloudTrail logs to is not publicly accessible (Scored) + + 2.4 Ensure CloudTrail trails are integrated with CloudWatch Logs (Scored) + + 2.5 Ensure AWS Config is enabled in all regions (Scored) + + 2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket (Scored) + + 2.7 Ensure CloudTrail logs are encrypted at rest using KMS CMKs (Scored) + + 2.8 Ensure rotation for customer created CMKs is enabled (Scored) + + 3 Monitoring ************************************************************ + + 3.1 Ensure a log metric filter and alarm exist for unauthorized API calls (Scored) + + 3.2 Ensure a log metric filter and alarm exist for Management Console sign-in without MFA (Scored) + + 3.3 Ensure a log metric filter and alarm exist for usage of root account (Scored) + + 3.4 Ensure a log metric filter and alarm exist for IAM policy changes (Scored) + + 3.5 Ensure a log metric filter and alarm exist for CloudTrail configuration changes (Scored) + + 3.6 Ensure a log metric filter and alarm exist for AWS Management Console authentication failures (Scored) + + 3.7 Ensure a log metric filter and alarm exist for disabling or scheduled deletion of customer created CMKs (Scored) + + 3.8 Ensure a log metric filter and alarm exist for S3 bucket policy changes (Scored) + + 3.9 Ensure a log metric filter and alarm exist for AWS Config configuration changes (Scored) + + 3.10 Ensure a log metric filter and alarm exist for security group changes (Scored) + + 3.11 Ensure a log metric filter and alarm exist for changes to Network Access Control Lists (NACL) (Scored) + + 3.12 Ensure a log metric filter and alarm exist for changes to network gateways (Scored) + + 3.13 Ensure a log metric filter and alarm exist for route table changes (Scored) + + 3.14 Ensure a log metric filter and alarm exist for VPC changes (Scored) + + 3.15 Ensure appropriate subscribers to each SNS topic (Not Scored) + + 4 Networking ************************************************************ + + 4.1 Ensure no security groups allow ingress from 0.0.0.0/0 to port 22 (Scored) + + 4.2 Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389 (Scored) + + 4.3 Ensure VPC Flow Logging is Enabled in all VPCs (Scored) + + 4.4 Ensure the default security group of every VPC restricts all traffic (Scored) + + 4.5 Ensure routing tables for VPC peering are "least access" (Not Scored) + + 7 Extras **************************************************************** + + 7.1 Ensure users with AdministratorAccess policy have MFA tokens enabled (Not Scored) (Not part of CIS benchmark) + + 7.2 Ensure there are no EBS Snapshots set as Public (Not Scored) (Not part of CIS benchmark) + + 7.3 Ensure there are no S3 buckets open to the Everyone or Any AWS user (Not Scored) (Not part of CIS benchmark) + + 7.4 Ensure there are no Security Groups without ingress filtering being used (Not Scored) (Not part of CIS benchmark) + + 7.5 Ensure there are no Security Groups not being used (Not Scored) (Not part of CIS benchmark) + + 7.6 Ensure there are no EC2 AMIs set as Public (Not Scored) (Not part of CIS benchmark) + + 7.7 Ensure there are no ECR repositories set as Public (Not Scored) (Not part of CIS benchmark) + + 7.8 Ensure there are no Public Accessible RDS instances (Not Scored) (Not part of CIS benchmark) + + 7.9 Check for internet facing Elastic Load Balancers (Not Scored) (Not part of CIS benchmark) + + 7.10 Check for internet facing EC2 Instances (Not Scored) (Not part of CIS benchmark) + + 7.11 Check for Publicly Accessible Redshift Clusters (Not Scored) (Not part of CIS benchmark) + + 7.12 Check if Amazon Macie is enabled (Not Scored) (Not part of CIS benchmark) + + 7.13 Check if GuardDuty is enabled (Not Scored) (Not part of CIS benchmark) + + 7.14 Check if CloudFront distributions have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.15 Check if Elasticsearch Service domains have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.16 Check if Elasticsearch Service domains allow open access (Not Scored) (Not part of CIS benchmark) + + 7.17 Check if Elastic Load Balancers have logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.18 Check if S3 buckets have server access logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.19 Check if Route53 hosted zones are logging queries to CloudWatch Logs (Not Scored) (Not part of CIS benchmark) + + 7.20 Check if Lambda functions invoke API operations are being recorded by CloudTrail (Not Scored) (Not part of CIS benchmark) + + 7.21 Check if Redshift cluster has audit logging enabled (Not Scored) (Not part of CIS benchmark) + + 7.22 Check if API Gateway has logging enabled (Not Scored) (Not part of CIS benchmark) diff --git a/checks/lista b/checks/lista new file mode 100644 index 00000000..c31d8bc7 --- /dev/null +++ b/checks/lista @@ -0,0 +1,79 @@ +check1 +check11 +check12 +check13 +check14 +check15 +check16 +check17 +check18 +check19 +check110 +check111 +check112 +check113 +check114 +check115 +check116 +check117 +check118 +check119 +check120 +check121 +check122 +check123 +check124 +check2 +check21 +check22 +check23 +check24 +check25 +check26 +check27 +check28 +check3 +check31 +check32 +check33 +check34 +check35 +check36 +check37 +check38 +check39 +check310 +check311 +check312 +check313 +check314 +check315 +check4 +check41 +check42 +check43 +check44 +check45 +check7 +check71 +check72 +check73 +check74 +check75 +check76 +check77 +check78 +check79 +check710 +check711 +check712 +check713 +check714 +check715 +check716 +check717 +check718 +check719 +check720 +check721 +check722 diff --git a/groups/group1 b/groups/group1 index 1663ceeb..c82504e0 100644 --- a/groups/group1 +++ b/groups/group1 @@ -2,6 +2,6 @@ GROUP_ID[1]="group1" GROUP_NUMBER[1]="1.0" -GROUP_TITLE[1]="Identity and Access Management" -GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called -GROUP_CHECKS[1]="check11" +GROUP_TITLE[1]="Identity and Access Management ****************************************" +GROUP_RUN_BY_DEFAULT[1]="Y" # run it when execute_all is called +GROUP_CHECKS[1]="check11,check12" diff --git a/groups/group2 b/groups/group2 new file mode 100644 index 00000000..e69de29b diff --git a/groups/group3 b/groups/group3 new file mode 100644 index 00000000..e69de29b diff --git a/groups/group4 b/groups/group4 new file mode 100644 index 00000000..e69de29b diff --git a/groups/group_cislevel1 b/groups/group_cislevel1 new file mode 100644 index 00000000..e69de29b diff --git a/groups/group_cislevel2 b/groups/group_cislevel2 new file mode 100644 index 00000000..e69de29b diff --git a/groups/group_extras b/groups/group_extras new file mode 100644 index 00000000..e69de29b diff --git a/groups/group_forensics b/groups/group_forensics new file mode 100644 index 00000000..e69de29b diff --git a/include/aws_profile_loader b/include/aws_profile_loader new file mode 100644 index 00000000..4e7ea2a3 --- /dev/null +++ b/include/aws_profile_loader @@ -0,0 +1,22 @@ +# It checks -p optoin first and use it as profile, if not -p provided then +# check environment variables and if not, it checks and loads credentials from +# instance profile (metadata server) if runs in an EC2 instance + +if [[ $PROFILE ]]; then + PROFILE_OPT="--profile $PROFILE" +else + # if Prowler runs insinde an AWS instance with IAM instance profile attached + INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) + if [[ $INSTANCE_PROFILE ]]; then + AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') + AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') + fi + if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then + PROFILE="ENV" + PROFILE_OPT="" + else + PROFILE="default" + PROFILE_OPT="--profile $PROFILE" + fi +fi diff --git a/include/awscli_detector b/include/awscli_detector new file mode 100644 index 00000000..6794be35 --- /dev/null +++ b/include/awscli_detector @@ -0,0 +1,7 @@ +# AWS-CLI detector variable +AWSCLI=$(which aws) +if [ -z "${AWSCLI}" ]; then + echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" + EXITCODE=1 + exit $EXITCODE +fi diff --git a/include/banner b/include/banner new file mode 100644 index 00000000..19c16386 --- /dev/null +++ b/include/banner @@ -0,0 +1,19 @@ +prowlerBanner() { + echo -e "$CYAN _" + echo -e " _ __ _ __ _____ _| | ___ _ __" + echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" + echo -e " | |_) | | | (_) \ V V /| | __/ |" + echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|" + echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n" + echo -e "$YELLOW Date: $(date)" +} + +infoReferenceLong(){ + # Report review note: + echo -e "" + echo -e "For more information on the Prowler, feedback and issue reporting:" + echo -e "https://github.com/toniblyx/prowler" + echo -e "" + echo -e "For more information on the CIS benchmark:" + echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" +} diff --git a/include/colors b/include/colors index e69de29b..31fc2cd9 100644 --- a/include/colors +++ b/include/colors @@ -0,0 +1,58 @@ +if [[ $MODE != "mono" && $MODE != "text" && $MODE != "csv" ]]; then + echo "" + echo "$OPTRED ERROR!$OPTNORMAL Invalid output mode. Choose text, mono, or csv." + usage + EXITCODE=1 + exit $EXITCODE +fi + +if [[ "$MODE" == "mono" || "$MODE" == "csv" ]]; then + MONOCHROME=1 +fi + +if [[ $MONOCHROME -eq 1 ]]; then + # Colors + NORMAL='' + WARNING='' # Bad (red) + SECTION='' # Section (yellow) + NOTICE='' # Notice (yellow) + OK='' # Ok (green) + BAD='' # Bad (red) + CYAN='' + BLUE='' + BROWN='' + DARKGRAY='' + GRAY='' + GREEN='' + MAGENTA='' + PURPLE='' + RED='' + YELLOW='' + WHITE='' +else + # Colors + # NOTE: Your editor may NOT show the 0x1b / escape character left of the '[' + NORMAL="" + WARNING="" # Bad (red) + SECTION="" # Section (yellow) + NOTICE="" # Notice (yellow) + OK="" # Ok (green) + BAD="" # Bad (red) + CYAN="" + BLUE="" + BROWN="" + DARKGRAY="" + GRAY="" + GREEN="" + MAGENTA="" + PURPLE="" + RED="" + YELLOW="" + WHITE="" +fi + +printColorsCode(){ + if [[ $MONOCHROME -eq 0 ]]; then + echo -e "\n$NORMAL Colors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL" + fi +} diff --git a/include/credentials_report b/include/credentials_report new file mode 100644 index 00000000..d958a768 --- /dev/null +++ b/include/credentials_report @@ -0,0 +1,26 @@ +# Generate Credential Report +genCredReport() { + textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" + until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do + sleep 1 + done +} + +# Save report to a file, decode it, deletion at finish and after every single check +saveReport(){ + $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE + if [[ $KEEPCREDREPORT -eq 1 ]]; then + textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" + textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" + fi +} + +# Delete temporary report file +cleanTemp(){ + if [[ $KEEPCREDREPORT -ne 1 ]]; then + rm -fr $TEMP_REPORT_FILE + fi +} + +# Delete the temporary report file if we get interrupted/terminated +trap cleanTemp EXIT diff --git a/include/csv_header b/include/csv_header new file mode 100644 index 00000000..bad90f37 --- /dev/null +++ b/include/csv_header @@ -0,0 +1,5 @@ +printCsvHeader() { + >&2 echo "" + >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" + echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" +} diff --git a/include/os_detector b/include/os_detector new file mode 100644 index 00000000..d36c07ce --- /dev/null +++ b/include/os_detector @@ -0,0 +1,76 @@ +# Functions to manage dates depending on OS +if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + # function to compare in days, usage how_older_from_today date + # date format %Y-%m-%d + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) + DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + # function to convert from timestamp to date, usage timestamp_to_date timestamp + # output date format %Y-%m-%d + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } + decode_report() + { + base64 -d + } +elif [[ "$OSTYPE" == "darwin"* ]]; then + # BSD/OSX commands compatibility + TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date +%s) + DATE_FROM_IN_DAYS=$(date -jf %Y-%m-%d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -r $TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } + decode_report() + { + base64 -D + } +elif [[ "$OSTYPE" == "cygwin" ]]; then + # POSIX compatibility layer and Linux environment emulation for Windows + TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) + how_older_from_today() + { + DATE_TO_COMPARE=$1 + TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) + DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) + DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) + echo $DAYS_SINCE + } + timestamp_to_date() + { + # remove fractions of a second + TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") + OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') + echo $OUTPUT_DATE + } + decode_report() + { + base64 -d + } +else + echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" + echo "Found: $OSTYPE" + EXITCODE=1 + exit $EXITCODE +fi diff --git a/include/outputs b/include/outputs new file mode 100644 index 00000000..42ad7336 --- /dev/null +++ b/include/outputs @@ -0,0 +1,81 @@ +## Output formatting functions +textOK(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $OK OK! $NORMAL $1" + fi +} + +textNotice(){ + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $NOTICE INFO! $1 $NORMAL" + fi +} + +textWarn(){ + EXITCODE=3 + if [[ "$MODE" == "csv" ]]; then + if [[ $2 ]]; then + REPREGION=$2 + else + REPREGION=$REGION + fi + echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" + else + echo " $BAD WARNING! $1 $NORMAL" + fi +} + +textTitle(){ + TITLE_ID=$1 + if [[ $NUMERAL ]]; then + TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) + else + TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) + fi + + TITLE_TEXT=$2 + + case "$3" in + 0|No|NOT_SCORED) + ITEM_SCORED="Not Scored" + ;; + 1|Yes|SCORED) + ITEM_SCORED="Scored" + ;; + *) + ITEM_SCORED="Unspecified" + ;; + esac + + case "$4" in + LEVEL1) ITEM_LEVEL="Level 1";; + LEVEL2) ITEM_LEVEL="Level 2";; + EXTRA) ITEM_LEVEL="Extra";; + SUPPORT) ITEM_LEVEL="Support";; + *) ITEM_LEVEL="Unspecified or Invalid";; + esac + + if [[ "$MODE" == "csv" ]]; then + >&2 echo "$TITLE_ID $TITLE_TEXT" + else + if [[ "$ITEM_SCORED" == "Scored" ]]; then + echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" + else + echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" + fi + fi +} diff --git a/include/whoami b/include/whoami new file mode 100644 index 00000000..4a6f3913 --- /dev/null +++ b/include/whoami @@ -0,0 +1,44 @@ +# Get whoami in AWS, who is the user running this shell script +getWhoami(){ + ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') + if [[ "$MODE" == "csv" ]]; then + CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') + printCsvHeader + textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" + textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" + else + echo "" + echo -e " This report is being generated using credentials below:\n" + echo -e " AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" + if [[ $MONOCHROME -eq 1 ]]; then + echo -e " Caller Identity:" + $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + exit 2 + fi + else + echo -e " Caller Identity:" + $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION + if [[ 255 -eq $? ]]; then + # Failed to get own identity ... exit + echo variable $PROFILE_OPT + echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" + EXITCODE=2 + exit $EXITCODE + fi + echo "" + fi + fi +} diff --git a/prowler b/prowler1 similarity index 100% rename from prowler rename to prowler1 diff --git a/prowler2 b/prowler2 index c75439d0..38873031 100755 --- a/prowler2 +++ b/prowler2 @@ -31,12 +31,15 @@ MODE="text" SEP=',' KEEPCREDREPORT=0 EXITCODE=0 +SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) +TITLE_ID="" +TITLE_TEXT="CALLER ERROR - UNSET TITLE" # Command usage menu usage(){ echo " USAGE: - `basename $0` -p -r [ -h ] + `basename $0` [ -p -r -h ] Options: -p specify your AWS profile to use (i.e.: default) @@ -53,12 +56,13 @@ USAGE: (i.e.: 1.01 instead of 1.1) -l list all available checks only (does not perform any check) -e exclude extras + -b do not print Prowler banner -h this help " exit } -while getopts ":hlkp:r:c:f:m:M:en" OPTION; do +while getopts ":hlkp:r:c:f:m:M:enb" OPTION; do case $OPTION in h ) usage @@ -92,6 +96,9 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do n ) NUMERAL=1 ;; + b ) + NOBANNER="true" + ;; e ) EXTRAS=1 ;; @@ -113,297 +120,14 @@ while getopts ":hlkp:r:c:f:m:M:en" OPTION; do done . include/colors - -SCRIPT_START_TIME=$( date -u +"%Y-%m-%dT%H:%M:%S%z" ) - -# Functions to manage dates depending on OS -if [ "$OSTYPE" == "linux-gnu" ] || [ "$OSTYPE" == "linux-musl" ]; then - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - # function to compare in days, usage how_older_from_today date - # date format %Y-%m-%d - how_older_from_today() - { - DATE_TO_COMPARE=$1 - TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) - DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) - DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) - echo $DAYS_SINCE - } - # function to convert from timestamp to date, usage timestamp_to_date timestamp - # output date format %Y-%m-%d - timestamp_to_date() - { - # remove fractions of a second - TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") - OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') - echo $OUTPUT_DATE - } - decode_report() - { - base64 -d - } -elif [[ "$OSTYPE" == "darwin"* ]]; then - # BSD/OSX commands compatibility - TEMP_REPORT_FILE=$(mktemp -t prowler.cred_report-XXXXXX) - how_older_from_today() - { - DATE_TO_COMPARE=$1 - TODAY_IN_DAYS=$(date +%s) - DATE_FROM_IN_DAYS=$(date -jf %Y-%m-%d $DATE_TO_COMPARE +%s) - DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) - echo $DAYS_SINCE - } - timestamp_to_date() - { - # remove fractions of a second - TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") - OUTPUT_DATE=$(date -r $TIMESTAMP_TO_CONVERT +'%Y-%m-%d') - echo $OUTPUT_DATE - } - decode_report() - { - base64 -D - } -elif [[ "$OSTYPE" == "cygwin" ]]; then - # POSIX compatibility layer and Linux environment emulation for Windows - TEMP_REPORT_FILE=$(mktemp -t -p /tmp prowler.cred_report-XXXXXX) - how_older_from_today() - { - DATE_TO_COMPARE=$1 - TODAY_IN_DAYS=$(date -d "$(date +%Y-%m-%d)" +%s) - DATE_FROM_IN_DAYS=$(date -d $DATE_TO_COMPARE +%s) - DAYS_SINCE=$((($TODAY_IN_DAYS - $DATE_FROM_IN_DAYS )/60/60/24)) - echo $DAYS_SINCE - } - timestamp_to_date() - { - # remove fractions of a second - TIMESTAMP_TO_CONVERT=$(echo $1 | cut -f1 -d".") - OUTPUT_DATE=$(date -d @$TIMESTAMP_TO_CONVERT +'%Y-%m-%d') - echo $OUTPUT_DATE - } - decode_report() - { - base64 -d - } -else - echo "Unknown Operating System! Valid \$OSTYPE: linux-gnu, linux-musl, darwin* or cygwin" - echo "Found: $OSTYPE" - EXITCODE=1 - exit $EXITCODE -fi - -# It checks -p optoin first and use it as profile, if not -p provided then -# check environment variables and if not, it checks and loads credentials from -# instance profile (metadata server) if runs in an EC2 instance - -if [[ $PROFILE ]]; then - PROFILE_OPT="--profile $PROFILE" -else - # if Prowler runs insinde an AWS instance with IAM instance profile attached - INSTANCE_PROFILE=$(curl -s -m 1 http://169.254.169.254/latest/meta-data/iam/security-credentials/) - if [[ $INSTANCE_PROFILE ]]; then - AWS_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep AccessKeyId | cut -d':' -f2 | sed 's/[^0-9A-Z]*//g') - AWS_SECRET_ACCESS_KEY_ID=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} | grep SecretAccessKey | cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - AWS_SESSION_TOKEN=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${INSTANCE_PROFILE} grep Token| cut -d':' -f2 | sed 's/[^0-9A-Za-z/+=]*//g') - fi - if [[ $AWS_ACCESS_KEY_ID && $AWS_SECRET_ACCESS_KEY || $AWS_SESSION_TOKEN ]];then - PROFILE="ENV" - PROFILE_OPT="" - else - PROFILE="default" - PROFILE_OPT="--profile $PROFILE" - fi -fi - -# AWS-CLI variables -AWSCLI=$(which aws) -if [ -z "${AWSCLI}" ]; then - echo -e "\n$RED ERROR!$NORMAL AWS-CLI (aws command) not found. Make sure it is installed correctly and in your \$PATH\n" - EXITCODE=1 - exit $EXITCODE -fi - -TITLE_ID="" -TITLE_TEXT="CALLER ERROR - UNSET TITLE" - -## Output formatting functions -textOK(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}PASS${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $OK OK! $NORMAL $1" - fi -} - -textNotice(){ - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}INFO${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $NOTICE INFO! $1 $NORMAL" - fi -} - -textWarn(){ - EXITCODE=3 - if [[ "$MODE" == "csv" ]]; then - if [[ $2 ]]; then - REPREGION=$2 - else - REPREGION=$REGION - fi - echo "$PROFILE${SEP}$ACCOUNT_NUM${SEP}$REPREGION${SEP}$TITLE_ID${SEP}WARNING${SEP}$ITEM_SCORED${SEP}$ITEM_LEVEL${SEP}$TITLE_TEXT${SEP}$1" - else - echo " $BAD WARNING! $1 $NORMAL" - fi -} - -textTitle(){ - TITLE_ID=$1 - if [[ $NUMERAL ]]; then - TITLE_ID=$(echo $TITLE_ID | cut -d, -f2) - else - TITLE_ID=$(echo $TITLE_ID | cut -d, -f1) - fi - - TITLE_TEXT=$2 - - case "$3" in - 0|No|NOT_SCORED) - ITEM_SCORED="Not Scored" - ;; - 1|Yes|SCORED) - ITEM_SCORED="Scored" - ;; - *) - ITEM_SCORED="Unspecified" - ;; - esac - - case "$4" in - LEVEL1) ITEM_LEVEL="Level 1";; - LEVEL2) ITEM_LEVEL="Level 2";; - EXTRA) ITEM_LEVEL="Extra";; - SUPPORT) ITEM_LEVEL="Support";; - *) ITEM_LEVEL="Unspecified or Invalid";; - esac - - if [[ "$MODE" == "csv" ]]; then - >&2 echo "$TITLE_ID $TITLE_TEXT" - else - if [[ "$ITEM_SCORED" == "Scored" ]]; then - echo -e "\n$BLUE $TITLE_ID $NORMAL $TITLE_TEXT" - else - echo -e "\n$PURPLE $TITLE_ID $TITLE_TEXT $NORMAL" - fi - fi -} - -printCsvHeader() { - >&2 echo "" - >&2 echo "Generating \"${SEP}\" delimited report on stdout for profile $PROFILE, account $ACCOUNT_NUM" - echo "PROFILE${SEP}ACCOUNT_NUM${SEP}REGION${SEP}TITLE_ID${SEP}RESULT${SEP}SCORED${SEP}LEVEL${SEP}TITLE_TEXT${SEP}NOTES" -} - -prowlerBanner() { - echo -e "$CYAN _" - echo -e " _ __ _ __ _____ _| | ___ _ __" - echo -e " | '_ \| '__/ _ \ \ /\ / / |/ _ \ '__|" - echo -e " | |_) | | | (_) \ V V /| | __/ |" - echo -e " | .__/|_| \___/ \_/\_/ |_|\___|_|" - echo -e " |_|$NORMAL$BLUE CIS based AWS Account Hardening Tool$NORMAL\n" - echo -e "$YELLOW Date: $(date)" -} - -# Get whoami in AWS, who is the user running this shell script -getWhoami(){ - ACCOUNT_NUM=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Account" | tr -d '"') - if [[ "$MODE" == "csv" ]]; then - CALLER_ARN_RAW=$($AWSCLI sts get-caller-identity --output json $PROFILE_OPT --region $REGION --query "Arn") - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - CALLER_ARN=$(echo $CALLER_ARN_RAW | tr -d '"') - printCsvHeader - textTitle "0.0" "Show report generation info" "NOT_SCORED" "SUPPORT" - textNotice "ARN: $CALLER_ARN TIMESTAMP: $SCRIPT_START_TIME" - else - echo "" - echo "This report is being generated using credentials below:" - echo "" - echo -e "AWS-CLI Profile: $NOTICE[$PROFILE]$NORMAL AWS API Region: $NOTICE[$REGION]$NORMAL AWS Filter Region: $NOTICE[${FILTERREGION:-all}]$NORMAL\n" - if [[ $MONOCHROME -eq 1 ]]; then - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output text $PROFILE_OPT --region $REGION --query "Arn" - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - exit 2 - fi - echo "" - else - echo "Caller Identity:" - $AWSCLI sts get-caller-identity --output table $PROFILE_OPT --region $REGION - if [[ 255 -eq $? ]]; then - # Failed to get own identity ... exit - echo variable $PROFILE_OPT - echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - >&2 echo "ERROR WITH $PROFILE CREDENTIALS - EXITING!" - EXITCODE=2 - exit $EXITCODE - fi - echo "" - fi - fi -} - -printColorsCode(){ - if [[ $MONOCHROME -eq 0 ]]; then - echo -e "\nColors Code for results: $NOTICE INFORMATIVE$NORMAL,$OK OK (RECOMMENDED VALUE)$NORMAL, $BAD WARNING (FIX REQUIRED)$NORMAL \n" - fi -} - -# Generate Credential Report -genCredReport() { - textTitle "0.1" "Generating AWS IAM Credential Report..." "NOT_SCORED" "SUPPORT" - until $( $AWSCLI iam generate-credential-report --output text --query 'State' $PROFILE_OPT --region $REGION |grep -q -m 1 "COMPLETE") ; do - sleep 1 - done -} - -# Save report to a file, decode it, deletion at finish and after every single check -saveReport(){ - $AWSCLI iam get-credential-report --query 'Content' --output text $PROFILE_OPT --region $REGION | decode_report > $TEMP_REPORT_FILE - if [[ $KEEPCREDREPORT -eq 1 ]]; then - textTitle "0.2" "Saving IAM Credential Report ..." "NOT_SCORED" "SUPPORT" - textNotice "IAM Credential Report saved in $TEMP_REPORT_FILE" - fi -} - -# Delete temporary report file -cleanTemp(){ - if [[ $KEEPCREDREPORT -ne 1 ]]; then - rm -fr $TEMP_REPORT_FILE - fi -} - -# Delete the temporary report file if we get interrupted/terminated -trap cleanTemp EXIT +. include/os_detector +. include/aws_profile_loader +. include/awscli_detector +. include/outputs +. include/csv_header +. include/banner +. include/whoami +. include/credentials_report # Get a list of all available AWS Regions REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ @@ -412,17 +136,6 @@ REGIONS=$($AWSCLI ec2 describe-regions --query 'Regions[].RegionName' \ --region $REGION \ --region-names $FILTERREGION) -infoReferenceLong(){ - # Report review note: - echo -e "" - echo -e "For more information on the Prowler, feedback and issue reporting:" - echo -e "https://github.com/Alfresco/prowler" - echo -e "" - echo -e "For more information on the CIS benchmark:" - echo -e "https://benchmarks.cisecurity.org/tools2/amazon/CIS_Amazon_Web_Services_Foundations_Benchmark_v1.1.0.pdf" - -} - callCheck(){ if [[ $CHECKNUMBER ]];then case "$CHECKNUMBER" in @@ -436,20 +149,19 @@ callCheck(){ } # List only check tittles - if [[ $PRINTCHECKSONLY == "1" ]]; then prowlerBanner show_all_titles exit $EXITCODE fi -# Include all of the groups of checks inside include folder +# Load all of the groups of checks inside groups folder named as "group*" for group in $(ls groups/group*); do . "$group" done -# Include all of the checks inside include folder -# this includes also extra check since they are "check_extraNN" +# Load all of the checks inside checks folder named as "check*" +# this includes also extra checks since they are "check_extraNN" for checks in $(ls checks/check*); do . "$checks" done @@ -462,7 +174,7 @@ show_check_title() { # Function to show the title of a group, by numeric id show_group_title() { - # This would also just call textTitle in the real prowler + # when csv mode is used, no group tittle is shown if [[ "$MODE" != "csv" ]]; then textTitle "${GROUP_NUMBER[$1]}" "${GROUP_TITLE[$1]}" "NOT_SCORED" "SUPPORT" fi @@ -523,7 +235,7 @@ show_all_titles() { ### All functions defined above ... run the workflow -if [[ $MODE != "csv" ]]; then +if [[ $MODE != "csv" || $NOBANNER != "true" ]]; then prowlerBanner printColorsCode fi @@ -532,7 +244,7 @@ genCredReport saveReport callCheck -show_all_titles +execute_all # if [[ ! $EXTRAS ]]; then