AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ParallelCluster UI Cognito User Pool

Parameters:
  AdminUserEmail:
    Description: Email address of administrative user setup by default.
    Type: String
    MinLength: 1
  PermissionsBoundaryPolicy:
    Type: String
    Description: 'ARN of the IAM policy to use as permissions boundary for every IAM role'
    Default: ''
    AllowedPattern: "^(arn:.*:iam::.*:policy\\/([a-zA-Z0-9_-]+))|()$"
  IAMRoleAndPolicyPrefix:
    Type: String
    Description: 'Prefix applied to the name of every IAM role and policy (max length: 10)'
    Default: ''
    MaxLength: 10
  CustomDomain:
    Type: String
    Description: (Optional) Custom domain name. If omitted, the default domain name will be used.
    Default: ''
  CustomDomainCertificateArn:
    Type: String
    Description: '(Optional) ARN of the ACM Certificate issued for the custom domain. This is required only if `CustomDomain` is specified.'
    Default: ''

Conditions:
  GovCloud: !Equals [!Ref AWS::Region, 'us-gov-west-1']
  UsePermissionBoundary: !Not [ !Equals [ !Ref PermissionsBoundaryPolicy, '' ] ]
  UseCustomDomain: !Not [!Equals [!Ref CustomDomain, '']]

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Admin info
        Parameters:
          - AdminUserEmail
      - Label:
          default: (Optional) Permissions
        Parameters:
          - IAMRoleAndPolicyPrefix
          - PermissionsBoundaryPolicy
      - Label:
          default: (Optional) Custom Domain
        Parameters:
          - CustomDomain
          - CustomDomainCertificateArn
    ParameterLabels:
      AdminUserEmail:
        default: Initial Admin's Email
      IAMRoleAndPolicyPrefix:
        default: Prefix for IAM Roles and Policies
      PermissionsBoundaryPolicy:
        default: Permissions Boundary


Resources:
  SNSRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub
        - ${IAMRoleAndPolicyPrefix}SNSRole-${StackIdSuffix}
        - { StackIdSuffix: !Select [ 0, !Split [ '-', !Select [ 2, !Split [ '/', !Ref 'AWS::StackId' ] ] ] ] }
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - cognito-idp.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: !Sub ${IAMRoleAndPolicyPrefix}SNSPermissions
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: sns:publish
                Resource: '*'
      PermissionsBoundary: !If [ UsePermissionBoundary, !Ref PermissionsBoundaryPolicy, !Ref 'AWS::NoValue' ]

  UserPoolDomain:
    Type: AWS::Cognito::UserPoolDomain
    Properties:
      UserPoolId: !Ref CognitoUserPool
      Domain: !If
        - UseCustomDomain
        - !Ref CustomDomain
        - !Join [ "-", ["pcui-auth", !Select [2, !Split [ "/", !Ref 'AWS::StackId']]]]
      CustomDomainConfig: !If
        - UseCustomDomain
        - { CertificateArn: !Ref CustomDomainCertificateArn }
        - !Ref AWS::NoValue

  CognitoUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      AutoVerifiedAttributes:
        - email
      Schema: [{Name: email, AttributeDataType: String, Mutable: true, Required: true}]
      UserPoolName: !Sub ${AWS::StackName}-userpool
      UsernameConfiguration:
        CaseSensitive: false
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
        InviteMessageTemplate:
          EmailSubject: "[AWS ParallelCluster UI] Welcome to AWS ParallelCluster UI, please verify your account."
          EmailMessage: "You are invited to manage clusters with ParallelCluster UI. Your administrator will contact you with the link to access. Your username is {username} and your temporary password (you will need to change it in your first access) is <br><br> {####}"
      UsernameAttributes:
        - 'email'


  CognitoAdminGroup:
    Type: AWS::Cognito::UserPoolGroup
    Properties:
      Description: User group that can manage clusters and users
      GroupName: admin
      Precedence: 1
      UserPoolId: !Ref CognitoUserPool

  CognitoAdminUser:
    Type: AWS::Cognito::UserPoolUser
    Properties:
      DesiredDeliveryMediums:
        - EMAIL
      UserAttributes:
        - Name: email
          Value: !Ref AdminUserEmail
        - Name: email_verified
          Value: True
      Username: !Ref AdminUserEmail
      UserPoolId: !Ref CognitoUserPool

  CognitoUserToAdminGroup:
    Type: AWS::Cognito::UserPoolUserToGroupAttachment
    Properties:
      GroupName: !Ref CognitoAdminGroup
      Username: !Ref CognitoAdminUser
      UserPoolId: !Ref CognitoUserPool

Outputs:

  UserPoolAuthDomain:
    Description: The domain of the authorization server.
    Value: !If
      - UseCustomDomain
      - !Sub https://${UserPoolDomain}
      - !Sub
        - https://${Domain}.${Auth}.${AWS::Region}.amazoncognito.com
        - {Domain: !Ref UserPoolDomain, Auth: !If [GovCloud, 'auth-fips', 'auth']}

  CustomDomainEndpoint:
    Condition: UseCustomDomain
    Description: |
      The endpoint associated with the custom domain name. 
      Add an A record in your DNS for the custom domain name pointing to this endpoint.
    Value: !GetAtt UserPoolDomain.CloudFrontDistribution

  UserPoolId:
    Description: Cognito UserPool Id
    Value:  !Ref CognitoUserPool

  SNSRole:
    Description: Role for SNS
    Value: !GetAtt SNSRole.Arn
