{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "authKsUsersUserPoolId": {
      "Type": "String",
      "Default": "authKsUsersUserPoolId"
    },
    "authKsUsersIdentityPoolId": {
      "Type": "String",
      "Default": "authKsUsersIdentityPoolId"
    },
    "authKsUsersAppClientID": {
      "Type": "String",
      "Default": "authKsUsersAppClientID"
    },
    "authKsUsersAppClientIDWeb": {
      "Type": "String",
      "Default": "authKsUsersAppClientIDWeb"
    },
    "AuthRoleArn": {
      "Type": "String"
    },
    "UnauthRoleArn": {
      "Type": "String"
    },
    "env": {
      "Type": "String"
    }
  },
  "Conditions": {
    "ShouldNotCreateEnvResources": {
      "Fn::Equals": [
        {
          "Ref": "env"
        },
        "NONE"
      ]
    }
  },
  "Resources": {
    "adminsGroup": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {
        "GroupName": "admins",
        "Precedence": 1,
        "RoleArn": {
          "Fn::GetAtt": ["adminsGroupRole", "Arn"]
        },
        "UserPoolId": {
          "Ref": "authKsUsersUserPoolId"
        }
      }
    },
    "adminsGroupRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "authKsUsersUserPoolId"
              },
              "-adminsGroupRole"
            ]
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Allow",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        }
      }
    },

    "editorsGroup": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {
        "GroupName": "editors",
        "Precedence": 2,
        "RoleArn": {
          "Fn::GetAtt": ["editorsGroupRole", "Arn"]
        },
        "UserPoolId": {
          "Ref": "authKsUsersUserPoolId"
        }
      }
    },
    "editorsGroupRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "authKsUsersUserPoolId"
              },
              "-editorsGroupRole"
            ]
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Allow",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        }
      }
    },

    "contributorsGroup": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {
        "GroupName": "contributors",
        "Precedence": 3,
        "RoleArn": {
          "Fn::GetAtt": ["contributorsGroupRole", "Arn"]
        },
        "UserPoolId": {
          "Ref": "authKsUsersUserPoolId"
        }
      }
    },
    "contributorsGroupRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "authKsUsersUserPoolId"
              },
              "-contributorsGroupRole"
            ]
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Allow",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        }
      }
    },

    "viewersGroup": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {
        "GroupName": "viewers",
        "Precedence": 4,
        "RoleArn": {
          "Fn::GetAtt": ["viewersGroupRole", "Arn"]
        },
        "UserPoolId": {
          "Ref": "authKsUsersUserPoolId"
        }
      }
    },
    "viewersGroupRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Ref": "authKsUsersUserPoolId"
              },
              "-viewersGroupRole"
            ]
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "",
              "Effect": "Allow",
              "Principal": {
                "Federated": "cognito-identity.amazonaws.com"
              },
              "Action": "sts:AssumeRoleWithWebIdentity"
            }
          ]
        }
      }
    },

    "LambdaExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": {
          "Fn::If": [
            "ShouldNotCreateEnvResources",
            {},
            {
              "Fn::Join": [
                "",
                [
                  "KsUsers",
                  "-ExecutionRole-",
                  {
                    "Ref": "env"
                  }
                ]
              ]
            }
          ]
        },
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": ["lambda.amazonaws.com"]
              },
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "UserGroupLogPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": "arn:aws:logs:*:*:*"
                }
              ]
            }
          },
          {
            "PolicyName": "UserGroupExecutionPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-identity:SetIdentityPoolRoles",
                    "cognito-identity:ListIdentityPools",
                    "cognito-identity:describeIdentityPool"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "UserGroupPassRolePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      }
    },
    "RoleMapFunction": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": ["LambdaExecutionRole"],
      "Properties": {
        "Code": {
          "ZipFile": {
            "Fn::Join": [
              "\n",
              [
                "const response = require('cfn-response');",
                "const AWS = require('aws-sdk');",
                "exports.handler = (event, context) => {",
                "if (event.RequestType == 'Delete') {",
                "    response.send(event, context, response.SUCCESS, {message: 'Request type delete'})",
                "};",
                "if (event.RequestType == 'Create' || event.RequestType == 'Update') {",
                "    let { identityPoolId, appClientID, appClientIDWeb, userPoolId, region }  = event.ResourceProperties;",
                "    try {",
                "       const cognitoidentity = new AWS.CognitoIdentity();",
                "       let params = {",
                "           IdentityPoolId: identityPoolId,",
                "           Roles: {",
                "               'authenticated': event.ResourceProperties.AuthRoleArn,",
                "               'unauthenticated': event.ResourceProperties.UnauthRoleArn,",
                "           },",
                "           RoleMappings: {}",
                "       };",
                "       if (appClientIDWeb) {",
                "           params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientIDWeb}`] = {",
                "               Type: 'Token',",
                "               AmbiguousRoleResolution: 'AuthenticatedRole',",
                "           }",
                "       }",
                "       if (appClientID) {",
                "           params.RoleMappings[`cognito-idp.${region}.amazonaws.com/${userPoolId}:${appClientID}`] = {",
                "               Type: 'Token',",
                "               AmbiguousRoleResolution: 'AuthenticatedRole',",
                "           }",
                "       }",
                "    cognitoidentity.setIdentityPoolRoles(params).promise();",
                "    response.send(event, context, response.SUCCESS, {message: 'Successfully updated identity pool.'})",
                "    } catch(err) {",

                "        response.send(event, context, response.FAILED, {message: 'Error updating identity pool'});",
                "    }",
                "   };",
                "};"
              ]
            ]
          }
        },
        "Handler": "index.handler",
        "Runtime": "nodejs8.10",
        "Timeout": "300",
        "Role": {
          "Fn::GetAtt": ["LambdaExecutionRole", "Arn"]
        }
      }
    },
    "RoleMapFunctionInput": {
      "Type": "Custom::LambdaCallout",
      "Properties": {
        "ServiceToken": {
          "Fn::GetAtt": ["RoleMapFunction", "Arn"]
        },
        "AuthRoleArn": {
          "Ref": "AuthRoleArn"
        },
        "UnauthRoleArn": {
          "Ref": "UnauthRoleArn"
        },
        "identityPoolId": {
          "Ref": "authKsUsersIdentityPoolId"
        },
        "userPoolId": {
          "Ref": "authKsUsersUserPoolId"
        },
        "appClientIDWeb": {
          "Ref": "authKsUsersAppClientIDWeb"
        },
        "appClientID": {
          "Ref": "authKsUsersAppClientID"
        },
        "region": {
          "Ref": "AWS::Region"
        },
        "env": {
          "Ref": "env"
        }
      },
      "DependsOn": ["RoleMapFunction"]
    }
  },
  "Outputs": {
    "adminsGroupRole": {
      "Value": {
        "Fn::GetAtt": ["adminsGroupRole", "Arn"]
      }
    },

    "editorsGroupRole": {
      "Value": {
        "Fn::GetAtt": ["editorsGroupRole", "Arn"]
      }
    },

    "contributorsGroupRole": {
      "Value": {
        "Fn::GetAtt": ["contributorsGroupRole", "Arn"]
      }
    },

    "viewersGroupRole": {
      "Value": {
        "Fn::GetAtt": ["viewersGroupRole", "Arn"]
      }
    }
  }
}
