AWSTemplateFormatVersion: "2010-09-09"

# SINGLE ACCOUNT DEPLOYMENT (CloudFormation Stack):
# Use the Quick Create link from Cyquins UI or run:
# aws cloudformation create-stack \
#  --capabilities CAPABILITY_IAM --capabilities CAPABILITY_NAMED_IAM \
#  --template-body "file://prowler-scan-role-cyquins.yml" \
#  --stack-name "ProwlerScanRole" \
#  --parameters "ParameterKey=ExternalId,ParameterValue=YOUR_EXTERNAL_ID"
#
# MULTI-ACCOUNT DEPLOYMENT (CloudFormation StackSets for AWS Organizations):
# 1. Log into AWS Management Account
# 2. Navigate to CloudFormation > StackSets > Create StackSet
# 3. Choose "Service-managed permissions"
# 4. Template S3 URL: https://prowler-cyquins-scan-templates-951042686288.s3.us-east-1.amazonaws.com/templates/v1/prowler-scan-role-cyquins.yml
# 5. Set External ID and Role Name parameters
# 6. Deploy to organization or specific OUs
#
# CLI STACKSET DEPLOYMENT:
# aws cloudformation create-stack-set \
#   --stack-set-name ProwlerScanRole \
#   --template-url https://prowler-cyquins-scan-templates-951042686288.s3.us-east-1.amazonaws.com/templates/v1/prowler-scan-role-cyquins.yml \
#   --parameters ParameterKey=ExternalId,ParameterValue=YOUR_EXTERNAL_ID \
#   --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM \
#   --permission-model SERVICE_MANAGED \
#   --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false
#
# aws cloudformation create-stack-instances \
#   --stack-set-name ProwlerScanRole \
#   --deployment-targets OrganizationalUnitIds=YOUR_ORG_ROOT_ID \
#   --regions us-east-1

Description: |
  This template creates the ProwlerScan IAM Role with all read-only permissions
  to scan your AWS account(s) for security issues.
  Contains two AWS managed policies (SecurityAudit and ViewOnlyAccess) and an inline policy.

  DEPLOYMENT OPTIONS:
  - Single Account: Use CloudFormation Stack (Quick Create link in Cyquins UI)
  - AWS Organizations: Use CloudFormation StackSets (deploys to all member accounts)

  If you are deploying this template to be used in Prowler Cloud please do not edit
  the AccountId and IAMPrincipal parameters.
Parameters:
  ExternalId:
    Description: |
      This is the External ID that Prowler will use to assume the ProwlerScan IAM Role.
      Get this value from the Cyquins scan setup page.
    Type: String
    MinLength: 1
    AllowedPattern: ".+"
    ConstraintDescription: "ExternalId must not be empty."
  AccountId:
    Description: |
      AWS Account ID that will assume the role created (Prowler Cloud account).
      Do not edit unless using a different Prowler deployment.
    Type: String
    Default: "232136659152"
    MinLength: 12
    MaxLength: 12
    AllowedPattern: "[0-9]{12}"
    ConstraintDescription: "AccountId must be a valid AWS Account ID."
  IAMPrincipal:
    Description: |
      The IAM principal type and name that will be allowed to assume the role created.
      Leave as default for Prowler Cloud deployments.
    Type: String
    Default: role/prowler*
  RoleName:
    Description: |
      Name of the IAM role to create. For StackSets, this must be identical across all accounts.
      Do not change this unless you know what you're doing.
    Type: String
    Default: ProwlerScan
    MinLength: 1
    MaxLength: 64
    AllowedPattern: '[\w+=,.@_-]+'
    ConstraintDescription: "Role name must be a valid IAM role name."

Resources:
  ProwlerScan:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Ref RoleName
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub "arn:${AWS::Partition}:iam::${AccountId}:root"
            Action: "sts:AssumeRole"
            Condition:
              StringEquals:
                "sts:ExternalId": !Sub ${ExternalId}
              StringLike:
                "aws:PrincipalArn": !Sub "arn:${AWS::Partition}:iam::${AccountId}:${IAMPrincipal}"
      MaxSessionDuration: 3600
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/SecurityAudit"
        - "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
      Policies:
        - PolicyName: ProwlerScan
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: AllowMoreReadOnly
                Effect: Allow
                Action:
                  - "account:Get*"
                  - "appstream:Describe*"
                  - "appstream:List*"
                  - "backup:List*"
                  - "bedrock:List*"
                  - "bedrock:Get*"
                  - "cloudtrail:GetInsightSelectors"
                  - "codeartifact:List*"
                  - "codebuild:BatchGet*"
                  - "codebuild:ListReportGroups"
                  - "cognito-idp:GetUserPoolMfaConfig"
                  - "dlm:Get*"
                  - "drs:Describe*"
                  - "ds:Get*"
                  - "ds:Describe*"
                  - "ds:List*"
                  - "dynamodb:GetResourcePolicy"
                  - "ec2:GetEbsEncryptionByDefault"
                  - "ec2:GetSnapshotBlockPublicAccessState"
                  - "ec2:GetInstanceMetadataDefaults"
                  - "ecr:Describe*"
                  - "ecr:GetRegistryScanningConfiguration"
                  - "elasticfilesystem:DescribeBackupPolicy"
                  - "glue:GetConnections"
                  - "glue:GetSecurityConfiguration*"
                  - "glue:SearchTables"
                  - "lambda:GetFunction*"
                  - "logs:FilterLogEvents"
                  - "lightsail:GetRelationalDatabases"
                  - "macie2:GetMacieSession"
                  - "macie2:GetAutomatedDiscoveryConfiguration"
                  - "s3:GetAccountPublicAccessBlock"
                  - "shield:DescribeProtection"
                  - "shield:GetSubscriptionState"
                  - "securityhub:BatchImportFindings"
                  - "securityhub:GetFindings"
                  - "servicecatalog:Describe*"
                  - "servicecatalog:List*"
                  - "ssm:GetDocument"
                  - "ssm-incidents:List*"
                  - "states:ListTagsForResource"
                  - "support:Describe*"
                  - "tag:GetTagKeys"
                  - "wellarchitected:List*"
                Resource: "*"
              - Sid: AllowAPIGatewayReadOnly
                Effect: Allow
                Action:
                  - "apigateway:GET"
                Resource:
                  - "arn:*:apigateway:*::/restapis/*"
                  - "arn:*:apigateway:*::/apis/*"
      Tags:
        - Key: "Service"
          Value: "https://prowler.com"
        - Key: "Support"
          Value: "support@prowler.com"
        - Key: "CloudFormation"
          Value: "true"
        - Key: "Name"
          Value: !Ref RoleName

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Required Parameters
        Parameters:
          - ExternalId
      - Label:
          default: Advanced Configuration (Do not modify unless necessary)
        Parameters:
          - AccountId
          - IAMPrincipal
          - RoleName

Outputs:
  ProwlerScanRoleArn:
    Description: "ARN of the ProwlerScan IAM Role"
    Value: !GetAtt ProwlerScan.Arn
    Export:
      Name: !Sub "${AWS::StackName}-ProwlerScanRoleArn"
  RoleName:
    Description: "Name of the created IAM Role"
    Value: !Ref RoleName
  AccountId:
    Description: "Account ID where this role was created"
    Value: !Ref AWS::AccountId
