{"id":117,"date":"2022-03-27T16:09:00","date_gmt":"2022-03-27T16:09:00","guid":{"rendered":"http:\/\/localhost:8080\/?p=117"},"modified":"2026-09-07T16:15:02","modified_gmt":"2026-09-07T16:15:02","slug":"automating-prowler-for-compliance-checking-in-aws","status":"publish","type":"post","link":"https:\/\/jamesmonek.com\/?p=117","title":{"rendered":"Automating Prowler for Compliance Checking in AWS"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Whether you are looking to improve your AWS security posture or checking compliance against cybersecurity frameworks,&nbsp;<a href=\"https:\/\/github.com\/prowler-cloud\/prowler\">Prowler<\/a>&nbsp;is an amazing open source tool developed by&nbsp;<a href=\"https:\/\/blyx.com\/\">Toni de la Fuente<\/a>. Toni has created a tool to check over 200 security controls in AWS ranging from ensuring S3 buckers are not publicly accessible to encryption everywhere.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Toni\u2019s Github portal provides extensive documentation on how to use the tool, but I wanted to share a CloudFormation template that I created to automate the deployment in AWS to run compliance checks and then decommission the stack and remove all resources.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Launching EC2 Instance for Prowler<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#launching-ec2-instance-for-prowler\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">First, we will want launch an EC2 instance and run a bash script to download the necessary software, install, and configure Prowler.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  ProwlerInstance:\n    Type: 'AWS::EC2::Instance'\n    Properties:\n      ImageId: !Ref ImageId\n      InstanceType: !Ref InstanceType\n      SubnetId: !Ref SubnetId\n      SecurityGroupIds:\n        - !Ref InstanceSecurityGroup\n      KeyName: !Ref KeyName\n      IamInstanceProfile: !Ref ProwlerInstanceProfile\n      Tags:\n        -\n          Key: Name\n          Value: Prowler\n      BlockDeviceMappings:\n        - DeviceName: \/dev\/xvda\n          Ebs:\n            VolumeSize: 8\n            Encrypted: true\n# Run bash to install and configure Prowler\n      UserData:\n        Fn::Base64:\n          !Sub |\n            #!\/bin\/bash -xe\n            sudo yum update -y\n            sudo yum remove -y awscli\n            cd \/home\/ec2-user\n            curl \"https:\/\/awscli.amazonaws.com\/awscli-exe-linux-x86_64.zip\" -o \"\/home\/ec2-user\/awscliv2.zip\"\n            unzip \/home\/ec2-user\/awscliv2.zip\n            sudo \/home\/ec2-user\/aws\/install\n            sudo yum install -y python3 jq git\n            sudo pip3 install detect-secrets==1.0.3\n            git clone https:\/\/github.com\/prowler-cloud\/prowler \/home\/ec2-user\/prowler\n            chown -R ec2-user:ec2-user \/home\/ec2-user\/prowler<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Create an instance profile<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#create-an-instance-profile\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create an instance profile tied to a role with necessary permissions to run the audit.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  ProwlerInstanceProfile:\n    Type: AWS::IAM::InstanceProfile\n    Properties:\n      InstanceProfileName: prowler-ec2-instance-profile\n      Path: \/\n      Roles:\n       - !Ref ProwlerEc2InstanceRole<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Provide access to run Prowler<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#provide-access-to-run-prowler\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Next we will want to generate a role that has view-only and security audit permission that is required by Prowler to run compliance checks.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  ProwlerEc2InstanceRole:\n    Type: AWS::IAM::Role\n    Properties:\n      RoleName: prowler-ec2-instance-role\n      AssumeRolePolicyDocument:\n        Version: 2012-10-17\n        Statement:\n          -\n            Effect: Allow\n            Principal:\n              Service:\n                - ec2.amazonaws.com\n            Action:\n              - sts:AssumeRole\n      ManagedPolicyArns:\n        - arn:aws:iam::aws:policy\/SecurityAudit\n        - arn:aws:iam::aws:policy\/job-function\/ViewOnlyAccess\n      Path: \/<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Security Group<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#security-group\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We\u2019ll want to create a security group to only allow SSH access into the EC2 instance.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  InstanceSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n        GroupDescription: Allow ssh from specific host\n        GroupName: ProwlerSecurityGroup\n        VpcId: !Ref VpcId\n        SecurityGroupIngress:\n          - IpProtocol: 'tcp'\n            FromPort: '22'\n            ToPort: '22'\n            CidrIp: !Ref CidrIp<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Parameters<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#parameters\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lastly, to improve automation, we will pass parameters into the CloudFormation template. If you launch the template via the console, some of these settings will be selected via a dropdown. For launching via the command-line interface, pass the parameters through a JSON file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ImageId : Default is AWS Linux 2 ami-0e1d30f2c40c4c701\nInstanceType : Default is t3.micro\nVpcId : VPC to launch EC2 instance into\nSubnetId : Subnet for EC2 instance\nKeyName : Keypair to use\nCidrIp : CIDR range for SSH x.x.x.x\/x\n\nParameters:\n  ImageId:\n    Type: String\n    Description: AMI - Linux 2\n    Default: 'ami-0e1d30f2c40c4c701'\n  InstanceType:\n    Type: String\n    Description: Instance type to be used - t3.micro default\n    Default: t3.micro\n  VpcId:\n    Type: AWS::EC2::VPC::Id\n    Description: VPC to be used\n  SubnetId:\n    Type: AWS::EC2::Subnet::Id\n    Description: Subnet to be used\n  KeyName:\n    Type: AWS::EC2::KeyPair::KeyName\n    Description: Keyname\n  CidrIp:\n    Type: String\n    Description: CidrIp to be used to connect from x.x.x.x\/x\nMetadata:\n  AWS::CloudFormation::Interface:\n    ParameterGroups:\n      -\n        Label:\n          default: \"Network Configuration\"\n        Parameters:\n          - ImageId\n          - InstanceType\n          - VpcId\n          - SubnetId\n          - KeyName\n          - CidrIp<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Final YAML Script<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#final-yaml-script\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After putting all this together. The final YAML scripts looks like the following. The code is also available at&nbsp;<a href=\"https:\/\/github.com\/jamesmonek\/prowler-cloudformation\">Github<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: \"2010-09-09\"\nDescription: \"Create EC2 instanace with Prowler pre-configured and tied to roles to run\"\n# Template Parameters\n# ImageId : Default is AWS Linux 2 ami-0e1d30f2c40c4c701\n# InstanceType : Default is t3.micro\n# VpcId : VPC to launch in\n# SubnetId : Subnet to connect\n# KeyName : Keypair to use\n# CidrIp : CIDR range for SSH x.x.x.x\/x\nResources:\n# Create Prowler Instance - Parameters for ImageId, InstanceType, SubnetId, SecurityGroupIds, and KeyName\n  ProwlerInstance:\n    Type: 'AWS::EC2::Instance'\n    Properties:\n      ImageId: !Ref ImageId\n      InstanceType: !Ref InstanceType\n      SubnetId: !Ref SubnetId\n      SecurityGroupIds:\n        - !Ref InstanceSecurityGroup\n      KeyName: !Ref KeyName\n      IamInstanceProfile: !Ref ProwlerInstanceProfile\n      Tags:\n        -\n          Key: Name\n          Value: Prowler\n      BlockDeviceMappings:\n        - DeviceName: \/dev\/xvda\n          Ebs:\n            VolumeSize: 8\n            Encrypted: true\n# Run bash to install and configure Prowler\n      UserData:\n        Fn::Base64:\n          !Sub |\n            #!\/bin\/bash -xe\n            sudo yum update -y\n            sudo yum remove -y awscli\n            cd \/home\/ec2-user\n            curl \"https:\/\/awscli.amazonaws.com\/awscli-exe-linux-x86_64.zip\" -o \"\/home\/ec2-user\/awscliv2.zip\"\n            unzip \/home\/ec2-user\/awscliv2.zip\n            sudo \/home\/ec2-user\/aws\/install\n            sudo yum install -y python3 jq git\n            sudo pip3 install detect-secrets==1.0.3\n            git clone https:\/\/github.com\/prowler-cloud\/prowler \/home\/ec2-user\/prowler\n            chown -R ec2-user:ec2-user \/home\/ec2-user\/prowler\n  ProwlerInstanceProfile:\n    Type: AWS::IAM::InstanceProfile\n    Properties:\n      InstanceProfileName: prowler-ec2-instance-profile\n      Path: \/\n      Roles:\n       - !Ref ProwlerEc2InstanceRole\n# Create Security Group\n  InstanceSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n        GroupDescription: Allow ssh from specific host\n        GroupName: ProwlerSecurityGroup\n        VpcId: !Ref VpcId\n        SecurityGroupIngress:\n          - IpProtocol: 'tcp'\n            FromPort: '22'\n            ToPort: '22'\n            CidrIp: !Ref CidrIp\n# Create EC2 Instance Role to run security checks and attach to instance\n  ProwlerEc2InstanceRole:\n    Type: AWS::IAM::Role\n    Properties:\n      RoleName: prowler-ec2-instance-role\n      AssumeRolePolicyDocument:\n        Version: 2012-10-17\n        Statement:\n          -\n            Effect: Allow\n            Principal:\n              Service:\n                - ec2.amazonaws.com\n            Action:\n              - sts:AssumeRole\n      ManagedPolicyArns:\n        - arn:aws:iam::aws:policy\/SecurityAudit\n        - arn:aws:iam::aws:policy\/job-function\/ViewOnlyAccess\n      Path: \/\n# Parameters for cloudformation template with some defaults\nParameters:\n  ImageId:\n    Type: String\n    Description: AMI - Linux 2\n    Default: 'ami-0e1d30f2c40c4c701'\n  InstanceType:\n    Type: String\n    Description: Instance type to be used - t3.micro default\n    Default: t3.micro\n  VpcId:\n    Type: AWS::EC2::VPC::Id\n    Description: VPC to be used\n  SubnetId:\n    Type: AWS::EC2::Subnet::Id\n    Description: Subnet to be used\n  KeyName:\n    Type: AWS::EC2::KeyPair::KeyName\n    Description: Keyname\n  CidrIp:\n    Type: String\n    Description: CidrIp to be used to connect from x.x.x.x\/x\nMetadata:\n  AWS::CloudFormation::Interface:\n    ParameterGroups:\n      -\n        Label:\n          default: \"Network Configuration\"\n        Parameters:\n          - ImageId\n          - InstanceType\n          - VpcId\n          - SubnetId\n          - KeyName\n          - CidrIp\nConditions: {}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Running Prowler<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#running-prowler\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After launching the CloudFormation template, simply sign into the EC2 instance and change into the \/home\/ec2-user\/prowler directory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To start, I recommend running Prowler with the HTML output file option. This provides a dynamic HTML file that you can review all the findings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">.\/prowler -M html You can run direct output to multiple formats at once such as csv and json<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">.\/prowler -M csv,json,html Decommissioning the resources<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After you run Prowler, copy the output files to another system or S3 for review and record keeping. Go back into CloudFormation and delete the stack to remove all the resources that were generated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next steps<a href=\"https:\/\/jamesmonek.com\/posts\/automating-prowler-for-compliance-checking-in-aws\/#next-steps\"><\/a><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Prowler is also supported by AWS Security Hub, so you can send your findings directly to Security Hub. There\u2019s also a workshop available to build security dashboards in Quicksight from Prowler data. Details for this integration can be found at&nbsp;<a href=\"https:\/\/catalog.us-east-1.prod.workshops.aws\/workshops\/b1cdc52b-eb11-44ed-8dc8-9dfe5fb254f5\/en-US\">Building Prowler into a QuickSight powered AWS Security Dashboard<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Whether you are looking to improve your AWS security posture or checking compliance against cybersecurity frameworks,&nbsp;Prowler&nbsp;is an amazing open source tool developed by&nbsp;Toni de la Fuente. Toni has created a tool to check over 200 security controls in AWS ranging from ensuring S3 buckers are not publicly accessible to encryption everywhere. Toni\u2019s Github portal provides [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":119,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-117","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/posts\/117","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=117"}],"version-history":[{"count":1,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/posts\/117\/revisions"}],"predecessor-version":[{"id":118,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/posts\/117\/revisions\/118"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=\/wp\/v2\/media\/119"}],"wp:attachment":[{"href":"https:\/\/jamesmonek.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=117"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jamesmonek.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}