diff --git a/util/org-multi-account/serverless_codebuild/README.md b/util/org-multi-account/serverless_codebuild/README.md new file mode 100644 index 00000000..f2c12235 --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/README.md @@ -0,0 +1,48 @@ +# Organizational Prowler with Serverless + +Langage: [Korean](README_kr.md) + +This project is created to apply prowler in a multi-account environment within AWS Organizations. +CloudWatch triggers CodeBuild every fixed time. +CodeBuild executes the script which clones the latest prowler from [here](https://github.com/toniblyx/prowler) and performs security assessment on all the accounts in AWS Organizations. The assessment reports are sent to S3 bucket in Log Archive Account. + +For more information on how to use prowler, see [here](https://github.com/toniblyx/prowler#usage). + +![Untitled](docs/images/prowler_org_architecture.png) + +1. **Log Archive Account** + 1. Deploy [ProwlerS3.yaml](templates/ProwlerS3.yaml) in CloudFormation console. + The template creates S3 bucket for reports and bucket policy that limits API actions to principals from its AWS Organizations. + - AwsOrgId : AWS Organizations' Organization ID + - S3Prefix : The prefix included in the bucket name +2. **Master Account** + 1. Deploy [ProwlerRole.yaml](templates/ProwlerRole.yaml) stack to CloudFormation in a bid to create resources to master account itself. + (The template will be also deployed for other member accounts as a StackSet) + - ProwlerCodeBuildAccount : Audit Acccount ID where CodeBuild resides. (preferably Audit/Security account) + - ProwlerCodeBulidRole : Role name to use in CodeBuild service + - ProwlerCrossAccountRole : Role name to assume for Cross account + - ProwlerS3 : The S3 bucket name where reports will be put + 1. Create **StackSet** with [ProwlerRole.yaml](templates/ProwlerRole.yaml) to deploy Role into member accounts in AWS Organizations. + - ProwlerCodeBuildAccount : Audit Acccount ID where CodeBuild resides. (preferably Audit/Security account) + - ProwlerCodeBulidRole : Role name to use in CodeBuild service + - ProwlerCrossAccountRole : Role name to assume for Cross account + - ProwlerS3 : The S3 bucket name where reports will be put + - Permission : Service-managed permissions + - Deploy target : Deploy to organization 선택, Enable, Delete stacks 선택 + - Specify regions : Region to deploy +3. **Audit Account** + 1. Go to S3 console, create a bucket, upload [run-prowler-reports.sh.zip](src/run-prowler-reports.sh.zip) + - bucket name : prowler-util-*[Account ID]*-*[region]* + ![Untitled](docs/images/s3_screenshot.png) + + 1. Deploy [ProwlerCodeBuildStack.yaml](templates/ProwlerCodeBuildStack.yaml) which creates CloudWatch Rule to trigger CodeBuild every fixed time, allowing prowler to audit multi-accounts. + - AwsOrgId : AWS Organizations' Organization ID + - CodeBuildRole : Role name to use in CodeBuild service + - CodeBuildSourceS3 : Object location uploaded from i + - prowler-util-*[Account ID]*-*[region]/**run-prowler-reports.sh.zip** + - CrossAccountRole : Role name for cross account created in the process **2** above. + - ProwlerReportS3 : The S3 bucket name where reports will be put + - ProwlerReportS3Account : The account where the report S3 bucket resides. + 1. If you'd like to change the scheduled time, + 1. You can change the cron expression of ScheduleExpression within [ProwlerCodeBuildStack.yaml](templates/ProwlerCodeBuildStack.yaml). + 2. Alternatively, you can make changes directrly from Events > Rules > ProwlerExecuteRule > Actions > Edit in CloudWatch console. \ No newline at end of file diff --git a/util/org-multi-account/serverless_codebuild/README_kr.md b/util/org-multi-account/serverless_codebuild/README_kr.md new file mode 100644 index 00000000..1570ab9f --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/README_kr.md @@ -0,0 +1,62 @@ +# Organizational Prowler with Serverless + +Langage: [English](README.md) + +이 문서는 AWS Organization 내의 multi account 환경에서 prowler 를 적용하기 위해 작성된 문서입니다. +일정 시간마다 CloudWatch는 CodeBuild 를 트리거합니다. +CodeBuild 는 최신의 [prowler](https://github.com/toniblyx/prowler) 소스를 클론받고, +Organization 내의 모든 Account 에 대해 security assessment 를 수행합니다. +prowler 의 자세한 사용방법은 [이 곳](https://github.com/toniblyx/prowler#usagee) 을 참고합니다. + +![Untitled](docs/images/prowler_org_architecture.png) + +1. **Log Archive Account**에 접속합니다. + 1. 아래 템플릿을 CloudFormation console 에서 배포합니다. 이를 통해 prowler 의 security assessment report 가 저장되는 bucket 과 bucket policy 를 생성합니다. + + [ProwlerS3.yaml](templates/ProwlerS3.yaml) + + - AwsOrgId : AWS Organizations의 Organization ID + - S3Prefix : 생성될 버킷의 이름에 포함되는 prefix +2. **Master Account** 에 접속합니다. + 1. 아래 템플릿을 이용하여 CloudFormation **Stack**을 생성합니다. StackSet은 Master account 에 적용되지 않으므로 Stack 으로도 배포가 필요합니다. + + [ProwlerRole.yaml](templates/ProwlerRole.yaml) + + - ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Acccount ID + - ProwlerCodeBulidRole : CodeBuild의 생성될 Role 이름 + - ProwlerCrossAccountRole : Cross account 용 Assume할 Role 이름 + - ProwlerS3 : report 가 저장될 S3 bucket 명 + 2. 아래 템플릿을 이용하여 CloudFormation **StackSet**을 생성하여, Organazation에 포함된 account 대상으로도 아래 템플릿을 배포합니다. + + [ProwlerRole.yaml](templates/ProwlerRole.yaml) + + - ProwlerCodeBuildAccount : CodeBuild 가 있는 Audit Acccount + - ProwlerCodeBulidRole : CodeBuild에서 사용할 Role 이름 + - ProwlerCrossAccountRole : Cross account 용 Assume할 Role 이름 + - ProwlerS3 : report 가 저장될 S3 bucket 명 + - Permission : Service-managed permissions + - Deploy target : Deploy to organization 선택, Enable, Delete stacks 선택 + - Specify regions : 배포할 대상 리전을 선택 +3. **Audit Account**에 접속합니다. + 1. **S3 console** 로 이동하여 버킷을 생성하고 아래 항목을 **업로드**한 후, 버킷명을 복사해둡니다. + + [run-prowler-reports.sh.zip](src/run-prowler-reports.sh.zip) + + - bucket name : prowler-util-**-** + + ![Untitled](docs/images/s3_screenshot.png) + + 2. 아래 템플릿으로 **CloudFormation stack** 을 생성합니다. 이 템플릿은 CloudWatch Rule 을 생성하여 일정 시간마다 CodeBuild 를 실행하여 prowler 가 multi accounts 를 audit 할 수 있도록 합니다. + + [ProwlerCodeBuildStack.yaml](templates/ProwlerCodeBuildStack.yaml) + + - AwsOrgId : AWS Organizations의 Organization ID + - CodeBuildRole : CodeBuild의 서비스 Role 이름 + - CodeBuildSourceS3 : a 에서 업로드한 object 위치 + - prowler-util-**-*/***run-prowler-reports.sh.zip** + - CrossAccountRole : 2번에서 생성한 Cross Account 용 Role 이름 + - ProwlerReportS3 : report 가 저장될 S3 bucket 명 + - ProwlerReportS3Account : report 가 저장될 S3 bucket이 위치한 Account + 3. 스케줄 된 시간을 변경하고 싶은 경우 + 1. [ProwlerCodeBuildStack.yaml](templates/ProwlerCodeBuildStack.yaml) 내에서 ScheduleExpression의 크론 표현식을 변경할 수 있습니다. + 2. 또는 CloudWatch console 에서 Events > Rules > ProwlerExecuteRule > Actions > Edit 에서 직접 변경할 수 있습니다. \ No newline at end of file diff --git a/util/org-multi-account/serverless_codebuild/docs/images/prowler_org_architecture.png b/util/org-multi-account/serverless_codebuild/docs/images/prowler_org_architecture.png new file mode 100644 index 00000000..0996ae00 Binary files /dev/null and b/util/org-multi-account/serverless_codebuild/docs/images/prowler_org_architecture.png differ diff --git a/util/org-multi-account/serverless_codebuild/docs/images/s3_screenshot.png b/util/org-multi-account/serverless_codebuild/docs/images/s3_screenshot.png new file mode 100644 index 00000000..4dd14057 Binary files /dev/null and b/util/org-multi-account/serverless_codebuild/docs/images/s3_screenshot.png differ diff --git a/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh b/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh new file mode 100644 index 00000000..2b7350cc --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh @@ -0,0 +1,119 @@ +#!/bin/bash -e +# +# Run Prowler against All AWS Accounts in an AWS Organization + +# Change Directory (rest of the script, assumes your in the ec2-user home directory) +# cd /home/ec2-user || exit + +# Show Prowler Version, and Download Prowler, if it doesn't already exist +if ! ./prowler/prowler -V 2>/dev/null; then + git clone https://github.com/toniblyx/prowler.git + ./prowler/prowler -V +fi + +# Source .awsvariables (to read in Environment Variables from CloudFormation Data) +# shellcheck disable=SC1091 +# source .awsvariables + +# Get Values from Environment Variables Created on EC2 Instance from CloudFormation Data +echo "S3: $S3" +echo "S3ACCOUNT: $S3ACCOUNT" +echo "ROLE: $ROLE" +echo "FORMAT: $FORMAT" + +# CleanUp Last Ran Prowler Reports, as they are already stored in S3. +rm -rf prowler/output/*.html + +# Function to unset AWS Profile Variables +unset_aws() { + unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN +} +unset_aws + +# Find THIS Account AWS Number +CALLER_ARN=$(aws sts get-caller-identity --output text --query "Arn") +PARTITION=$(echo "$CALLER_ARN" | cut -d: -f2) +THISACCOUNT=$(echo "$CALLER_ARN" | cut -d: -f5) +echo "THISACCOUNT: $THISACCOUNT" +echo "PARTITION: $PARTITION" + +# Function to Assume Role to THIS Account & Create Session +this_account_session() { + unset_aws + role_credentials=$(aws sts assume-role --role-arn arn:"$PARTITION":iam::"$THISACCOUNT":role/"$ROLE" --role-session-name ProwlerRun --output json) + AWS_ACCESS_KEY_ID=$(echo "$role_credentials" | jq -r .Credentials.AccessKeyId) + AWS_SECRET_ACCESS_KEY=$(echo "$role_credentials" | jq -r .Credentials.SecretAccessKey) + AWS_SESSION_TOKEN=$(echo "$role_credentials" | jq -r .Credentials.SessionToken) + echo "this_account_session done..." + export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN +} + +# Find AWS Master Account +this_account_session +AWSMASTER=$(aws organizations describe-organization --query Organization.MasterAccountId --output text) +echo "AWSMASTER: $AWSMASTER" + +# Function to Assume Role to Master Account & Create Session +master_account_session() { + unset_aws + role_credentials=$(aws sts assume-role --role-arn arn:"$PARTITION":iam::"$AWSMASTER":role/"$ROLE" --role-session-name ProwlerRun --output json) + AWS_ACCESS_KEY_ID=$(echo "$role_credentials" | jq -r .Credentials.AccessKeyId) + AWS_SECRET_ACCESS_KEY=$(echo "$role_credentials" | jq -r .Credentials.SecretAccessKey) + AWS_SESSION_TOKEN=$(echo "$role_credentials" | jq -r .Credentials.SessionToken) + echo "master_account_session done..." + export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN +} + +# Lookup All Accounts in AWS Organization +master_account_session +ACCOUNTS_IN_ORGS=$(aws organizations list-accounts --query Accounts[*].Id --output text) + +# Function to Assume Role to S3 Account & Create Session +s3_account_session() { + unset_aws + role_credentials=$(aws sts assume-role --role-arn arn:"$PARTITION":iam::"$S3ACCOUNT":role/"$ROLE" --role-session-name ProwlerRun --output json) + AWS_ACCESS_KEY_ID=$(echo "$role_credentials" | jq -r .Credentials.AccessKeyId) + AWS_SECRET_ACCESS_KEY=$(echo "$role_credentials" | jq -r .Credentials.SecretAccessKey) + AWS_SESSION_TOKEN=$(echo "$role_credentials" | jq -r .Credentials.SessionToken) + echo "s3_account_session done..." + export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN +} + +# Run Prowler against Accounts in AWS Organization +echo "AWS Accounts in Organization" +echo "$ACCOUNTS_IN_ORGS" +PARALLEL_ACCOUNTS="1" +for accountId in $ACCOUNTS_IN_ORGS; do + # shellcheck disable=SC2015 + test "$(jobs | wc -l)" -ge $PARALLEL_ACCOUNTS && wait || true + { + START_TIME=$SECONDS + # Unset AWS Profile Variables + unset_aws + # Run Prowler + echo -e "Assessing AWS Account: $accountId, using Role: $ROLE on $(date)" + # remove -g cislevel for a full report and add other formats if needed + ./prowler/prowler -R "$ROLE" -A "$accountId" -g cislevel1 -M $FORMAT + echo "Report stored locally at: prowler/output/ directory" + TOTAL_SEC=$((SECONDS - START_TIME)) + echo -e "Completed AWS Account: $accountId, using Role: $ROLE on $(date)" + printf "Completed AWS Account: $accountId in %02dh:%02dm:%02ds" $((TOTAL_SEC / 3600)) $((TOTAL_SEC % 3600 / 60)) $((TOTAL_SEC % 60)) + echo "" + } & +done + +# Wait for All Prowler Processes to finish +wait +echo "Prowler Assessments Completed against All Accounts in the AWS Organization. Starting S3 copy operations..." + +# Upload Prowler Report to S3 +s3_account_session +aws s3 cp prowler/output/ "$S3/reports/" --recursive --include "*.html" --acl bucket-owner-full-control +echo "Assessment reports successfully copied to S3 bucket" + +# Final Wait for All Prowler Processes to finish +wait +echo "Prowler Assessments Completed" + +# Unset AWS Profile Variables +unset_aws diff --git a/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh.zip b/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh.zip new file mode 100644 index 00000000..e73fdaba Binary files /dev/null and b/util/org-multi-account/serverless_codebuild/src/run-prowler-reports.sh.zip differ diff --git a/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml b/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml new file mode 100644 index 00000000..d89c5452 --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/templates/ProwlerCodeBuildStack.yaml @@ -0,0 +1,210 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: Creates a CodeBuild project to audit an AWS account with Prowler and stores the html report in a S3 bucket. +Parameters: + AwsOrgId: + Type: String + Description: Enter AWS Organizations ID + AllowedPattern: ^o-[a-z0-9]{10,32}$ + ConstraintDescription: The Org Id must be a 12 character string starting with o- and followed by 10 lower case alphanumeric characters. + Default: o-itdezkbz6h + CodeBuildRole: + Description: Enter Name for CodeBuild Role to create + Type: String + AllowedPattern: ^[\w+=,.@-]{1,64}$ + ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] + Default: ProwlerCodeBuild-Role + CodeBuildSourceS3: + Type: String + Description: Enter like //.zip + ConstraintDescription: Max 63 characters. Can't start or end with dash. Can use numbers and lowercase letters. + Default: prowler-util-411267690458-ap-northeast-2/run-prowler-reports.sh.zip + ProwlerReportS3: + Type: String + Description: Enter S3 Bucket for Prowler Reports. prefix-awsaccount-awsregion + AllowedPattern: ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ + ConstraintDescription: Max 63 characters. Can't start or end with dash. Can use numbers and lowercase letters. + Default: prowler-954896828174-ap-northeast-2 + ProwlerReportS3Account: + Type: String + Description: Enter AWS Account Number where Prowler S3 Bucket resides. + AllowedPattern: ^\d{12}$ + ConstraintDescription: An AWS Account Number must be a 12 digit numeric string. + Default: 954896828174 + CrossAccountRole: + Type: String + Description: Enter CrossAccount Role Prowler will be using to assess AWS Accounts in the AWS Organization. (ProwlerCrossAccountRole) + AllowedPattern: ^[\w+=,.@-]{1,64}$ + ConstraintDescription: Max 64 alphanumeric characters. Also special characters [+, =, ., @, -] + Default: ProwlerXA-CBRole + ProwlerReportFormat: + Type: String + Description: Enter Prowler Option like html, csv, json + Default: html + +Resources: + ProwlerCodeBuildRole: + Type: AWS::IAM::Role + Properties: + Description: Prowler CodeBuild Role + RoleName: !Ref CodeBuildRole + Tags: + - Key: App + Value: Prowler + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - codebuild.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: Prowler-S3 + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowGetPutListObject + Effect: Allow + Resource: + - !Sub arn:${AWS::Partition}:s3:::${ProwlerReportS3} + - !Sub arn:${AWS::Partition}:s3:::${ProwlerReportS3}/* + Action: + - s3:GetObject + - s3:PutObject + - s3:ListBucket + - s3:PutObjectAcl + - Sid: AllowReadOnlyS3Access + Effect: Allow + Resource: "*" + Action: + - "s3:Get*" + - "s3:List*" + - PolicyName: Prowler-CrossAccount-AssumeRole + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowStsAssumeRole + Effect: Allow + Resource: !Sub arn:${AWS::Partition}:iam::*:role/${CrossAccountRole} + Action: sts:AssumeRole + Condition: + StringEquals: + aws:PrincipalOrgId: !Ref AwsOrgId + - PolicyName: Prowler-CloudWatch + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowCreateLogs + Effect: Allow + Resource: !Sub arn:${AWS::Partition}:logs:*:*:log-group:* + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - Sid: AllowPutevent + Effect: Allow + Resource: !Sub arn:${AWS::Partition}:logs:*:*:log-group:*:log-stream:* + Action: + - logs:PutLogEvents + + ProwlerCodeBuild: + Type: AWS::CodeBuild::Project + Properties: + Artifacts: + Type: NO_ARTIFACTS + Source: + Type: S3 + Location: !Ref CodeBuildSourceS3 + BuildSpec: | + version: 0.2 + phases: + install: + runtime-versions: + python: 3.8 + commands: + - echo "Updating yum..." + - yum -y update + build: + commands: + - echo "Running Prowler with script" + - chmod +x run-prowler-reports.sh + - ./run-prowler-reports.sh + post_build: + commands: + - echo "Done!" + Environment: + # AWS CodeBuild free tier includes 100 build minutes of BUILD_GENERAL1_SMALL per month. + # BUILD_GENERAL1_SMALL: Use up to 3 GB memory and 2 vCPUs for builds. $0.005/minute. + # BUILD_GENERAL1_MEDIUM: Use up to 7 GB memory and 4 vCPUs for builds. $0.01/minute. + # BUILD_GENERAL1_LARGE: Use up to 15 GB memory and 8 vCPUs for builds. $0.02/minute. + # BUILD_GENERAL1_2XLARGE: Use up to 144 GB memory and 72 vCPUs for builds. $0.20/minute. + ComputeType: "BUILD_GENERAL1_SMALL" + Image: "aws/codebuild/amazonlinux2-x86_64-standard:3.0" + Type: "LINUX_CONTAINER" + EnvironmentVariables: + - Name: "S3" + Value: !Sub s3://${ProwlerReportS3} + Type: PLAINTEXT + - Name: "S3ACCOUNT" + Value: !Ref ProwlerReportS3Account + Type: PLAINTEXT + - Name: "ROLE" + Value: !Ref CrossAccountRole + Type: PLAINTEXT + - Name: "FORMAT" + Value: !Ref ProwlerReportFormat + Type: PLAINTEXT + Description: Run Prowler assessment + ServiceRole: !GetAtt ProwlerCodeBuildRole.Arn + TimeoutInMinutes: 300 + + ProwlerCWRuleRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - events.amazonaws.com + Action: + - sts:AssumeRole + Description: ProwlerCWRuleRole + RoleName: ProwlerCWRule-Role + Policies: + - PolicyName: Rule-Events + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AWSEventInvokeCodeBuild + Effect: Allow + Resource: "*" + Action: + - codebuild:StartBuild + + ProwlerRule: + Type: AWS::Events::Rule + Properties: + Description: This rule will trigger CodeBuild to audit AWS Accounts in my Organization with Prowler + ScheduleExpression: cron(0 21 * * ? *) + RoleArn: !GetAtt ProwlerCWRuleRole.Arn + Name: ProwlerExecuteRule + State: ENABLED + Targets: + - Arn: !Sub ${ProwlerCodeBuild.Arn} + Id: Prowler-CodeBuild-Target + RoleArn: !GetAtt ProwlerCWRuleRole.Arn + + +Outputs: + ProwlerEc2Account: + Description: AWS Account Number where Prowler EC2 Instance resides. + Value: !Ref AWS::AccountId + ProwlerCodeBuildRole: + Description: Instance Role given to the Prowler EC2 Instance (needed to grant sts:AssumeRole rights). + Value: !Ref ProwlerCodeBuildRole + ProwlerReportS3: + Description: S3 Bucket for Prowler Reports + Value: !Ref ProwlerReportS3 diff --git a/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml b/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml new file mode 100644 index 00000000..138d8809 --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/templates/ProwlerRole.yaml @@ -0,0 +1,123 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Create the Cross-Account IAM Prowler Role + +Metadata: + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: CodeBuild Settings + Parameters: + - ProwlerCodeBuildAccount + - ProwlerCodeBulidRole + - Label: + default: S3 Settings + Parameters: + - ProwlerS3 + - Label: + default: CrossAccount Role + Parameters: + - ProwlerCrossAccountRole + +Parameters: + ProwlerS3: + Type: String + Description: Enter S3 Bucket for Prowler Reports. prefix-awsaccount-awsregion + AllowedPattern: ^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$ + Default: prowler-954896828174-ap-northeast-2 + ProwlerCodeBuildAccount: + Type: String + Description: Enter AWS Account Number where Prowler CodeBuild Instance will reside. + AllowedPattern: ^\d{12}$ + ConstraintDescription: An AWS Account Number must be a 12 digit numeric string. + Default: 411267690458 + ProwlerCodeBulidRole: + Type: String + Description: Enter Instance Role that will be given to the Prowler CodeBuild (needed to grant sts:AssumeRole rights). + AllowedPattern: ^[\w+=,.@-]{1,64}$ + ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] + Default: ProwlerCodeBuild-Role + ProwlerCrossAccountRole: + Type: String + Description: Enter Name for CrossAccount Role to be created for Prowler to assess all Accounts in the AWS Organization. + AllowedPattern: ^[\w+=,.@-]{1,64}$ + ConstraintDescription: Max 64 alphanumeric characters. Also special characters supported [+, =, ., @, -] + Default: ProwlerXA-CBRole + +Resources: + ProwlerRole: + Type: AWS::IAM::Role + Properties: + Description: Provides Prowler CodeBuild permissions to assess security of Accounts in AWS Organization + RoleName: !Ref ProwlerCrossAccountRole + Tags: + - Key: App + Value: Prowler + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + AWS: + - !Sub arn:${AWS::Partition}:iam::${ProwlerCodeBuildAccount}:root + Action: + - sts:AssumeRole + Condition: + StringLike: + aws:PrincipalArn: !Sub arn:${AWS::Partition}:iam::${ProwlerCodeBuildAccount}:role/${ProwlerCodeBulidRole} + ManagedPolicyArns: + - !Sub arn:${AWS::Partition}:iam::aws:policy/SecurityAudit + - !Sub arn:${AWS::Partition}:iam::aws:policy/job-function/ViewOnlyAccess + Policies: + - PolicyName: Prowler-Additions-Policy + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowMoreReadForProwler + Effect: Allow + Resource: "*" + Action: + - access-analyzer:List* + - apigateway:Get* + - apigatewayv2:Get* + - aws-marketplace:ViewSubscriptions + - dax:ListTables + - ds:ListAuthorizedApplications + - ds:DescribeRoles + - ecr:Describe* + - lambda:GetAccountSettings + - lambda:GetFunctionConfiguration + - lambda:GetLayerVersionPolicy + - lambda:GetPolicy + - opsworks-cm:Describe* + - opsworks:Describe* + - secretsmanager:ListSecretVersionIds + - sns:List* + - sqs:ListQueueTags + - states:ListActivities + - support:Describe* + - tag:GetTagKeys + - PolicyName: Prowler-S3-Reports + PolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: AllowGetPutListObject + Effect: Allow + Resource: + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3} + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/* + Action: + - s3:GetObject + - s3:PutObject + - s3:ListBucket + Metadata: + cfn_nag: + rules_to_suppress: + - id: W11 + reason: "Prowler requires these rights to perform its Security Assessment." + - id: W28 + reason: "Using a defined Role Name." + +Outputs: + ProwlerCrossAccountRole: + Description: CrossAccount Role to be used by Prowler to assess AWS Accounts in the AWS Organization. + Value: !Ref ProwlerCrossAccountRole diff --git a/util/org-multi-account/serverless_codebuild/templates/ProwlerS3.yaml b/util/org-multi-account/serverless_codebuild/templates/ProwlerS3.yaml new file mode 100644 index 00000000..fc0ef4d9 --- /dev/null +++ b/util/org-multi-account/serverless_codebuild/templates/ProwlerS3.yaml @@ -0,0 +1,106 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Create Prowler S3 Bucket for Prowler Reports + +Parameters: + AwsOrgId: + Type: String + Description: > + Enter AWS Organizations ID. + This is used to restrict permissions to least privilege. + AllowedPattern: ^o-[a-z0-9]{10,32}$ + ConstraintDescription: The Org Id must be a 12 character string starting with o- and followed by 10 lower case alphanumeric characters. + Default: o-abcde12345 + S3Prefix: + Type: String + Description: > + Enter S3 Bucket Name Prefix (in lowercase). + Bucket will be named: prefix-awsaccount-awsregion (i.e., prowler-123456789012-us-east-1) + AllowedPattern: ^[a-z0-9][a-z0-9-]{1,33}[a-z0-9]$ + ConstraintDescription: > + Max 35 characters, as "-awsaccount-awsregion" will be added, and max name is 63 characters. + Can't start or end with dash. Can use numbers and lowercase letters. + Default: prowler + +Resources: + ProwlerS3: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub ${S3Prefix}-${AWS::AccountId}-${AWS::Region} + BucketEncryption: + ServerSideEncryptionConfiguration: + - ServerSideEncryptionByDefault: + SSEAlgorithm: "AES256" + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: True + BlockPublicPolicy: True + IgnorePublicAcls: True + RestrictPublicBuckets: True + VersioningConfiguration: + Status: Enabled + Tags: + - Key: App + Value: Prowler + Metadata: + cfn_nag: + rules_to_suppress: + - id: W35 + reason: "This S3 Bucket is only being used by the AWS Organization to download/upload prowler reports." + + ProwlerS3BucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref ProwlerS3 + PolicyDocument: + Statement: + - Sid: AllowGetPutListObject + Effect: Allow + Principal: "*" + Action: + - s3:GetObject + - s3:PutObject + - s3:ListBucket + - s3:PutObjectAcl + Resource: + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3} + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/* + Condition: + StringEquals: + aws:PrincipalOrgId: !Ref AwsOrgId + - Sid: DenyNonSSLRequests + Effect: Deny + Action: s3:* + Resource: + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3} + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/* + Principal: "*" + Condition: + Bool: + aws:SecureTransport: false + - Sid: DenyIncorrectEncryptionHeader + Effect: Deny + Principal: "*" + Action: s3:PutObject + Resource: + - !Sub arn:${AWS::Partition}:s3:::${ProwlerS3}/* + # Allow uploads with No Encryption, as S3 Default Encryption still applies. + # If Encryption is set, only allow uploads with AES256. + Condition: + "Null": + s3:x-amz-server-side-encryption: false + StringNotEquals: + s3:x-amz-server-side-encryption: AES256 + Metadata: + cfn_nag: + rules_to_suppress: + - id: F16 + reason: "This S3 Bucket Policy has a condition that only allows access to the AWS Organization." + + +Outputs: + ProwlerS3: + Description: S3 Bucket for Prowler Reports + Value: !Ref ProwlerS3 + ProwlerS3Account: + Description: AWS Account Number where Prowler S3 Bucket resides. + Value: !Ref AWS::AccountId