{
  "Description": "Root Stack for AWS Amplify Console",
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "DeploymentBucketName": {
      "Type": "String",
      "Default": "DeploymentBucket",
      "Description": "Name of the common deployment bucket provided by the parent stack"
    },
    "AuthRoleName": {
      "Type": "String",
      "Default": "AuthRoleName",
      "Description": "Name of the common deployment bucket provided by the parent stack"
    },
    "UnauthRoleName": {
      "Type": "String",
      "Default": "UnAuthRoleName",
      "Description": "Name of the common deployment bucket provided by the parent stack"
    }
  },
  "Outputs": {
    "Region": {
      "Description": "CloudFormation provider root stack Region",
      "Value": {
        "Ref": "AWS::Region"
      },
      "Export": {
        "Name": {
          "Fn::Sub": "${AWS::StackName}-Region"
        }
      }
    },
    "StackName": {
      "Description": "CloudFormation provider root stack ID",
      "Value": {
        "Ref": "AWS::StackName"
      },
      "Export": {
        "Name": {
          "Fn::Sub": "${AWS::StackName}-StackName"
        }
      }
    },
    "StackId": {
      "Description": "CloudFormation provider root stack name",
      "Value": {
        "Ref": "AWS::StackId"
      },
      "Export": {
        "Name": {
          "Fn::Sub": "${AWS::StackName}-StackId"
        }
      }
    },
    "AuthRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "AuthRole",
          "Arn"
        ]
      }
    },
    "UnauthRoleArn": {
      "Value": {
        "Fn::GetAtt": [
          "UnauthRole",
          "Arn"
        ]
      }
    },
    "DeploymentBucketName": {
      "Description": "CloudFormation provider root stack deployment bucket name",
      "Value": {
        "Ref": "DeploymentBucketName"
      },
      "Export": {
        "Name": {
          "Fn::Sub": "${AWS::StackName}-DeploymentBucketName"
        }
      }
    },
    "AuthRoleName": {
      "Value": {
        "Ref": "AuthRole"
      }
    },
    "UnauthRoleName": {
      "Value": {
        "Ref": "UnauthRole"
      }
    }
  },
  "Resources": {
    "DeploymentBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": {
          "Ref": "DeploymentBucketName"
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {
              "ServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
              }
            }
          ]
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain"
    },
    "AuthRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Deny",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        },
        "RoleName": {
          "Ref": "AuthRoleName"
        }
      }
    },
    "UnauthRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Deny",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        },
        "RoleName": {
          "Ref": "UnauthRoleName"
        }
      }
    },
    "apiapicde40323": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/api/apicde40323-cloudformation-template.json",
        "Parameters": {
          "functionflexsdkjsaws477da9b8Name": {
            "Fn::GetAtt": [
              "functionflexsdkjsaws477da9b8",
              "Outputs.Name"
            ]
          },
          "functionflexsdkjsaws477da9b8Arn": {
            "Fn::GetAtt": [
              "functionflexsdkjsaws477da9b8",
              "Outputs.Arn"
            ]
          },
          "env": "dev"
        }
      }
    },
    "functionflexsdkjsaws477da9b8": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/function/flexsdkjsaws477da9b8-cloudformation-template.json",
        "Parameters": {
          "deploymentBucketName": "amplify-flexsdkjsaws-dev-195646-deployment",
          "s3Key": "amplify-builds/flexsdkjsaws477da9b8-446e3137593758576864-build.zip",
          "env": "dev"
        }
      }
    },
    "functionflexsdkjsawsac385f5f": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/function/flexsdkjsawsac385f5f-cloudformation-template.json",
        "Parameters": {
          "deploymentBucketName": "amplify-flexsdkjsaws-dev-195646-deployment",
          "s3Key": "amplify-builds/flexsdkjsawsac385f5f-634d6239474f37765676-build.zip",
          "env": "dev"
        }
      }
    },
    "functionflexsdkjsaws598376fb": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/function/flexsdkjsaws598376fb-cloudformation-template.json",
        "Parameters": {
          "deploymentBucketName": "amplify-flexsdkjsaws-dev-195646-deployment",
          "s3Key": "amplify-builds/flexsdkjsaws598376fb-6536502f56796f636766-build.zip",
          "env": "dev"
        }
      }
    },
    "functionsendVerificationEmail": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/function/sendVerificationEmail-cloudformation-template.json",
        "Parameters": {
          "deploymentBucketName": "amplify-flexsdkjsaws-dev-195646-deployment",
          "s3Key": "amplify-builds/sendVerificationEmail-76466e656d534951576f-build.zip",
          "env": "dev"
        }
      }
    },
    "authflexsdkjsaws": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": "https://s3.amazonaws.com/amplify-flexsdkjsaws-dev-195646-deployment/amplify-cfn-templates/auth/flexsdkjsaws-cloudformation-template.json",
        "Parameters": {
          "identityPoolName": "flexsdkjsaws_identitypool_149a0f5f",
          "allowUnauthenticatedIdentities": true,
          "resourceNameTruncated": "flexsd149a0f5f",
          "userPoolName": "flexsdkjsaws_userpool_149a0f5f",
          "autoVerifiedAttributes": "email",
          "mfaConfiguration": "OFF",
          "mfaTypes": "SMS Text Message",
          "smsAuthenticationMessage": "Your authentication code is {####}",
          "smsVerificationMessage": "Your verification code is {####}",
          "emailVerificationSubject": "Your verification code",
          "emailVerificationMessage": "Your verification code is {####}",
          "defaultPasswordPolicy": false,
          "passwordPolicyMinLength": 8,
          "passwordPolicyCharacters": "",
          "requiredAttributes": "email",
          "aliasAttributes": "",
          "userpoolClientGenerateSecret": false,
          "userpoolClientRefreshTokenValidity": 30,
          "userpoolClientWriteAttributes": "email",
          "userpoolClientReadAttributes": "email",
          "userpoolClientLambdaRole": "flexsd149a0f5f_userpoolclient_lambda_role",
          "userpoolClientSetAttributes": false,
          "authSelections": "identityPoolAndUserPool",
          "resourceName": "flexsdkjsaws",
          "sharedId": "149a0f5f",
          "serviceName": "Cognito",
          "useDefault": "manual",
          "authRoleArn": {
            "Fn::GetAtt": [
              "AuthRole",
              "Arn"
            ]
          },
          "unauthRoleArn": {
            "Fn::GetAtt": [
              "UnauthRole",
              "Arn"
            ]
          },
          "breakCircularDependency": true,
          "useEnabledMfas": true,
          "dependsOn": "",
          "env": "dev"
        }
      }
    },
    "UpdateRolesWithIDPFunction": {
      "DependsOn": [
        "AuthRole",
        "UnauthRole",
        "authflexsdkjsaws"
      ],
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": {
            "Fn::Join": [
              "\n",
              [
                "const response = require('cfn-response');",
                "const aws = require('aws-sdk');",
                "let responseData = {};",
                "exports.handler = function(event, context) {",
                "  try {",
                "    let authRoleName = event.ResourceProperties.authRoleName;",
                "    let unauthRoleName = event.ResourceProperties.unauthRoleName;",
                "    let idpId = event.ResourceProperties.idpId;",
                "    let promises = [];",
                "    let getPromises = [];",
                "    let authParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'authenticated'}}}]};",
                "    let unauthParamsJson = { 'Version': '2012-10-17','Statement': [{'Effect': 'Allow','Principal': {'Federated': 'cognito-identity.amazonaws.com'},'Action': 'sts:AssumeRoleWithWebIdentity','Condition': {'StringEquals': {'cognito-identity.amazonaws.com:aud': idpId},'ForAnyValue:StringLike': {'cognito-identity.amazonaws.com:amr': 'unauthenticated'}}}]};",
                "    if (event.RequestType == 'Delete') {",
                "        delete authParamsJson.Statement[0].Condition;",
                "        delete unauthParamsJson.Statement[0].Condition;",
                "        let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};",
                "        let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};",
                "        const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});",
                "        getPromises.push(iam.getRole({RoleName: authParams.RoleName}).promise());",
                "        getPromises.push(iam.getRole({RoleName: unauthParams.RoleName}).promise());",
                "        Promise.all(getPromises)",
                "         .then((res) => {",
                "        console.log('in res' , res)",
                "           promises.push(iam.updateAssumeRolePolicy(authParams).promise());",
                "           promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());",
                "           return Promise.all(promises)",
                "             .then((res) => {",
                "               console.log(\"delete response data\" + JSON.stringify(res));",
                "               response.send(event, context, response.SUCCESS, {});",
                "             });",
                "          })",
                "           .catch((err) => {",
                "             console.log(err.stack);",
                "             responseData = {Error: err};",
                "             response.send(event, context, response.SUCCESS, responseData);",
                "             })",
                "    }",
                "    if (event.RequestType == 'Update' || event.RequestType == 'Create') {",
                "       const iam = new aws.IAM({ apiVersion: '2010-05-08', region: event.ResourceProperties.region});",
                "        let authParams = { PolicyDocument: JSON.stringify(authParamsJson),RoleName: authRoleName};",
                "        let unauthParams = {PolicyDocument: JSON.stringify(unauthParamsJson),RoleName: unauthRoleName};",
                "        promises.push(iam.updateAssumeRolePolicy(authParams).promise());",
                "        promises.push(iam.updateAssumeRolePolicy(unauthParams).promise());",
                "        Promise.all(promises)",
                "         .then((res) => {",
                "            console.log(\"createORupdate\" + res);",
                "            console.log(\"response data\" + JSON.stringify(res));",
                "            response.send(event, context, response.SUCCESS, {});",
                "         });",
                "    }",
                "  } catch(err) {",
                "       console.log(err.stack);",
                "       responseData = {Error: err};",
                "       response.send(event, context, response.FAILED, responseData);",
                "       throw err;",
                "  }",
                "};"
              ]
            ]
          }
        },
        "Handler": "index.handler",
        "Runtime": "nodejs14.x",
        "Timeout": 300,
        "Role": {
          "Fn::GetAtt": [
            "UpdateRolesWithIDPFunctionRole",
            "Arn"
          ]
        }
      }
    },
    "UpdateRolesWithIDPFunctionOutputs": {
      "Type": "Custom::LambdaCallout",
      "Properties": {
        "ServiceToken": {
          "Fn::GetAtt": [
            "UpdateRolesWithIDPFunction",
            "Arn"
          ]
        },
        "region": {
          "Ref": "AWS::Region"
        },
        "idpId": {
          "Fn::GetAtt": [
            "authflexsdkjsaws",
            "Outputs.IdentityPoolId"
          ]
        },
        "authRoleName": {
          "Ref": "AuthRole"
        },
        "unauthRoleName": {
          "Ref": "UnauthRole"
        }
      }
    },
    "UpdateRolesWithIDPFunctionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "AuthRole"
              },
              "-idp"
            ]
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "UpdateRolesWithIDPFunctionPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "arn:aws:logs:*:*:*"
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:UpdateAssumeRolePolicy",
                    "iam:GetRole"
                  ],
                  "Resource": {
                    "Fn::GetAtt": [
                      "AuthRole",
                      "Arn"
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:UpdateAssumeRolePolicy",
                    "iam:GetRole"
                  ],
                  "Resource": {
                    "Fn::GetAtt": [
                      "UnauthRole",
                      "Arn"
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}