AWSTemplateFormatVersion: 2010-09-09
Description: Mozilla Multi Account Manager invitation manager lambda function to run in master account.
Metadata:
  Source: https://github.com/mozilla/guardduty-multi-account-manager/tree/master/cloudformation
Parameters:
  AccountFilterList:
    Type: String
    Default: ''
    Description: >
      Space delimited list of account IDs to filter on. If this is set, only
      these accounts will be processed. If this is empty all accounts will be
      processed.
  OrganizationAccountArns:
    Type: String
    Default: ''
    Description: >
      Comma delimited list of ARNs of IAM Roles to assume in order to query the
      AWS Organization parents if the Org parents are different AWS accounts. 
      Leave this empty if you are deploying this stack within a single AWS 
      Organization parent account.
  LambdaCodeS3BucketNamePrefix:
    Type: String
    Default: public.
    Description: >
      A prefix string describing the S3 bucket name in each region containing
      the normalization.zip and plumbing.zip Lambda code. This parameter is appended with
      the region name. For example my-bucket- would be turned into
      my-bucket-us-west-2 for us-west-2. Set this to blank if your bucket name
      has no prefix.
  LambdaCodeS3BucketNameSuffix:
    Type: String
    Default: .infosec.mozilla.org
    Description: >
      A suffix string describing the S3 bucket name in each region containing
      the normalization.zip and plumbing.zip Lambda code. This parameter is prepended with
      the region name. For example -my-bucket would be turned into
      us-west-2-my-bucket for us-west-2. Set this to blank if your bucket name
      has no suffix
  LambdaCodeS3Path:
    Type: String
    Default: guardduty-multi-account-manager/lambda/
    Description: >
      The path in the S3 bucket containing the Lambda code.
    AllowedPattern: '.*\/$'
    ConstraintDescription: A path ending in the / character
Mappings:
  Variables:
    DynamoDBTable:
      Name: cloudformation-stack-emissions
      Category: GuardDuty Multi Account Member Role
Resources:
  InvitationManagerIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: "AllowRoleAssumptionOfMembers"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: sts:AssumeRole
                Resource:
                  - arn:aws:iam::*:role/multi-account-guard-duty/*
                  - arn:aws:iam::*:role/mutli-account-guard-duty/*
        - PolicyName: "AllowRoleAssumptionOfOrgReaders"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: sts:AssumeRole
                Resource: !Split [ ",", !Ref OrganizationAccountArns ]
        - PolicyName: "AllowSTSGetCallerIdentity"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: sts:GetCallerIdentity
                Resource: '*'
        - PolicyName: "AllowLocalGuardDuty"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                - guardduty:CreateDetector
                - guardduty:ListDetectors
                Resource: '*'
        - PolicyName: "AllowGuardDutyMasterManagement"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action:
                - guardduty:GetMembers
                - guardduty:ListMembers
                - guardduty:CreateMembers
                - guardduty:InviteMembers
                Resource: '*'
        - PolicyName: "AllowOrganizationListAccounts"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: organizations:ListAccounts
                Resource: '*'
        - PolicyName: "AllowScanDynamoDB"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: "Allow"
                Action: dynamodb:Scan
                Resource: !Join [ '', [ 'arn:aws:dynamodb:*:', !Ref 'AWS::AccountId', ':table/', !FindInMap [ Variables, DynamoDBTable, Name ]]]
  InvitationManagerFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.9
      Timeout: 900
      Handler: lambda_functions/invitation_manager.handle
      Role: !GetAtt InvitationManagerIAMRole.Arn
      Code:
        S3Bucket: !Join [ '', [ !Ref LambdaCodeS3BucketNamePrefix, !Ref 'AWS::Region', !Ref LambdaCodeS3BucketNameSuffix ] ]
        S3Key: !Join [ '', [ !Ref LambdaCodeS3Path, "invitation_manager.zip" ] ]
      Environment:
        Variables:
          ACCOUNT_FILTER_LIST: !Ref AccountFilterList
          DYNAMODB_TABLE_NAME: !FindInMap [ Variables, DynamoDBTable, Name ]
          DB_CATEGORY: !FindInMap [ Variables, DynamoDBTable, Category ]
          ORGANIZATION_IAM_ROLE_ARNS: !Ref OrganizationAccountArns
  InvitationManagerScheduledRule:
    Type: AWS::Events::Rule
    Properties:
      Description: "Trigger GuardDuty Invitation Manager run thrice daily"
      ScheduleExpression: "cron(14,29,44 11 * * ? *)"
      State: "ENABLED"
      Targets:
        - Arn: !GetAtt InvitationManagerFunction.Arn
          Id: "InvitationManager"
  PermissionForEventsToInvokeLambda:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName:
        Ref: InvitationManagerFunction
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: !GetAtt InvitationManagerScheduledRule.Arn
