AWSTemplateFormatVersion: "2010-09-09"
Description: >-
  Ops-Free SES: lets Ops-Free send email through YOUR Amazon SES account.
  Creates one IAM role that only Ops-Free can assume (and only with your
  ExternalId). Nothing is stored; delete this stack to revoke access.
Metadata:
  TemplateVersion: "2026-10-02"

Parameters:
  ConnectionId:
    Type: String
    Description: Names the role. Set for you; leave as is.
    AllowedPattern: "[A-Za-z0-9]{6,32}"
  ExternalId:
    Type: String
    Description: Proves this request came from your Ops-Free account. Set for you; leave as is.
    AllowedPattern: "[A-Za-z0-9_+=,.@:/-]{16,200}"
    NoEcho: false
  PlatformPrincipalArn:
    Type: String
    Description: The Ops-Free identity allowed to assume the role. Set for you; leave as is.
    AllowedPattern: "arn:aws:iam::[0-9]{12}:(user|role)/[A-Za-z0-9_+=,.@/-]+"
  CallbackTopicArn:
    Type: String
    Description: Where this stack reports the role's ARN. Set for you; leave as is.
    AllowedPattern: "arn:aws:sns:[a-z0-9-]+:[0-9]{12}:[A-Za-z0-9_-]+"

Resources:
  OpsFreeRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "OpsFreeSES-${ConnectionId}"
      Description: Lets Ops-Free send email through this account's Amazon SES.
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref PlatformPrincipalArn
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                sts:ExternalId: !Ref ExternalId
      Policies:
        - PolicyName: OpsFreeSES
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Sid: SesAndEvents
                Effect: Allow
                Action:
                  - ses:GetAccount
                  - ses:SendEmail
                  - ses:CreateEmailIdentity
                  - ses:GetEmailIdentity
                  - ses:CreateConfigurationSet
                  - ses:CreateConfigurationSetEventDestination
                  - ses:UpdateConfigurationSetEventDestination
                  - ses:PutEmailIdentityConfigurationSetAttributes
                  - sns:CreateTopic
                  - sns:Subscribe
                Resource: "*"
              - Sid: OptionalRoute53DkimRecords
                Effect: Allow
                Action:
                  - route53:ListHostedZonesByName
                  - route53:ChangeResourceRecordSets
                Resource: "*"

  TellOpsFree:
    Type: Custom::OpsFreeConnect
    Properties:
      ServiceToken: !Ref CallbackTopicArn
      ExternalId: !Ref ExternalId
      RoleArn: !GetAtt OpsFreeRole.Arn

Outputs:
  RoleArn:
    Description: The role Ops-Free assumes.
    Value: !GetAtt OpsFreeRole.Arn
