AWSTemplateFormatVersion: "2010-09-09"
Description: >-
  RestoreProof read-only scanner access. Creates one IAM role that RestoreProof
  can assume to read backup configuration and restore history. It cannot read
  objects, rows or logs, and it cannot change anything.
  Source: https://restoreproof.dglabs.cloud/readonly-role.yaml

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: RestoreProof connection
        Parameters:
          - RestoreProofAccountId
          - ExternalId
      - Label:
          default: Role settings
        Parameters:
          - RoleName
    ParameterLabels:
      RestoreProofAccountId:
        default: RestoreProof AWS account ID
      ExternalId:
        default: ExternalId (from your scan form)
      RoleName:
        default: IAM role name

Parameters:
  RestoreProofAccountId:
    Type: String
    AllowedPattern: "^[0-9]{12}$"
    ConstraintDescription: Must be a 12-digit AWS account ID.
    Description: >-
      The AWS account that runs the scan (shown on the scan form and in the
      Role ARN we give you).

  ExternalId:
    Type: String
    NoEcho: true
    MinLength: 16
    MaxLength: 128
    AllowedPattern: "^[A-Za-z0-9_+=,.@:\\-]{16,128}$"
    ConstraintDescription: 16-128 characters. Copy it from the scan form.
    Description: >-
      Secret string that only you and RestoreProof know. It prevents the
      confused-deputy problem: without it, nobody else can assume this role,
      not even by guessing the role ARN.

  RoleName:
    Type: String
    Default: RestoreProofReadOnly
    AllowedPattern: "^[A-Za-z0-9+=,.@_\\-]{1,64}$"
    Description: Name for the IAM role.

Resources:
  RestoreProofReadOnlyRole:
    Type: AWS::IAM::Role
    Metadata:
      Comment: Read-only metadata access for RestoreProof restore-age scans.
    Properties:
      RoleName: !Ref RoleName
      Description: >-
        Read-only access used by RestoreProof to compute restore age from
        backup metadata. Created from the public CloudFormation template.
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowRestoreProofScanner
            Effect: Allow
            Principal:
              AWS: !Sub "arn:aws:iam::${RestoreProofAccountId}:root"
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Ref ExternalId
      Policies:
        - PolicyName: RestoreProofReadOnlyMetadata
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: RdsDescribe
                Effect: Allow
                Action:
                  - rds:DescribeDBInstances
                  - rds:DescribeDBClusters
                  - rds:DescribeDBSnapshots
                  - rds:DescribeDBClusterSnapshots
                  - rds:DescribeDBClusterAutomatedBackups
                  - rds:ListTagsForResource
                Resource: "*"

              - Sid: S3ListBuckets
                Effect: Allow
                Action:
                  - s3:ListAllMyBuckets
                Resource: "*"

              - Sid: S3BucketConfiguration
                Effect: Allow
                Action:
                  - s3:GetBucketLocation
                  - s3:GetBucketVersioning
                  - s3:GetBucketReplication
                  - s3:GetBucketLifecycleConfiguration
                  - s3:ListBucketInventoryConfigurations
                Resource: "arn:aws:s3:::*"

              - Sid: AwsBackupDescribe
                Effect: Allow
                Action:
                  - backup:ListBackupVaults
                  - backup:ListBackupPlans
                  - backup:ListBackupSelections
                  - backup:GetBackupSelection
                  - backup:ListRecoveryPointsByResource
                  - backup:ListRestoreJobs
                  - backup:ListRestoreJobsByProtectedResource
                  - backup:DescribeRestoreJob
                  - backup:ListRestoreTestingPlans
                  - backup:ListRestoreTestingSelections
                  - backup:GetRestoreTestingPlan
                Resource: "*"

              - Sid: DenyDataAccess
                Effect: Deny
                Action:
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetObjectAttributes
                  - s3:ListBucket
                  - s3:ListBucketVersions
                  - s3:PutObject
                  - s3:DeleteObject
                  - cloudtrail:LookupEvents
                  - cloudtrail:GetTrail
                  - logs:GetLogEvents
                  - logs:FilterLogEvents
                  - rds:RestoreDBInstanceFromDBSnapshot
                  - rds:RestoreDBClusterFromSnapshot
                  - rds:ModifyDBInstance
                  - rds:DeleteDBInstance
                  - rds:CreateDBSnapshot
                  - backup:StartRestoreJob
                  - backup:DeleteRecoveryPoint
                  - backup:PutBackupVaultAccessPolicy
                Resource: "*"

Outputs:
  RoleArn:
    Description: Paste this value into the RestoreProof scan form.
    Value: !GetAtt RestoreProofReadOnlyRole.Arn
    Export:
      Name: !Sub "${AWS::StackName}-RestoreProofRoleArn"

  AccountId:
    Description: Account that will be scanned.
    Value: !Ref AWS::AccountId

  RevokeInstructions:
    Description: How to remove RestoreProof access.
    Value: >-
      Delete this stack (or the role) and access is gone immediately. No other
      resource is created by this template.
