{
    "AWSTemplateFormatVersion":"2010-09-09",
    "Description":"AES - Flowlogs - Cognito.  **Attention** This template creates AWS resources that will incur charges on your account.",
    "Parameters":{
        "NetworkStackName": {
            "Description": "Name of an active CloudFormation stack that contains the networking resources.",
            "Type": "String"
        }
    },
    "Resources":{
        "LambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": { "Fn::Join": [ "", [ {"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}, "-lambda_role"]]},
                "Path": "/",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [{
			"Effect": "Allow",
			"Principal": { "Service": "lambda.amazonaws.com"},
			"Action": "sts:AssumeRole"
                    }] 
                },
                "Policies": [{
                
                    "PolicyName": { "Fn::Join": [ "", [ {"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}, "-lambda-execution"]]},
                    "PolicyDocument": {
                        "Version":"2012-10-17",
                        "Statement":[
                        {
			    "Effect": "Allow",
			    "Action": "lambda:InvokeFunction",
			    "Resource": "arn:aws:lambda:*:*:function:*"
			},
			{
			    "Effect":"Allow",
			    "Action":[
			        "logs:CreateLogGroup",
			        "logs:CreateLogStream",
			        "logs:PutLogEvents"
			    ],
			    "Resource":"arn:aws:logs:*:*:*:*"
			},
			{
			    "Effect": "Allow",
			    "Action": [ "cognito-idp:*" ],
			    "Resource": "arn:aws:cognito-idp:*:*:userpool/*"
			},
			{
			    "Effect": "Allow",
			    "Action": [ "es:*" ],
			    "Resource": [ "*" ]
			}]
                    }
                } 
                ]
            }
        },
        
        "AuthUserRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": { "Fn::Join": [ "", [ {"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}, "-Cognito-AuthRole" ] ]},
                "Path": "/",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [{
                        "Effect": "Allow",
                        "Principal": { "Federated": "cognito-identity.amazonaws.com"},
                        "Action": "sts:AssumeRoleWithWebIdentity",
                        "Condition": {
                            "StringEquals": {
                                "cognito-identity.amazonaws.com:aud": { "Ref" : "CognitoIdentityPool"}
                            },
                            "ForAnyValue:StringLike": {
                                "cognito-identity.amazonaws.com:amr": "authenticated"
                            }
                        }
                    }] 
                },
                "Policies": [{
                    "PolicyName": { "Fn::Join": [ "", [ {"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}, "-lambda-execution"]]},
                    "PolicyDocument": {
                        "Version":"2012-10-17",
                        "Statement":[{
                            "Effect": "Allow",
                            "Action": [
                                 "mobileanalytics:PutEvents",
                                 "cognito-sync:*",
                                 "cognito-identity:*"
                            ],
                            "Resource": [ "*" ]
                        }]
                    }
                }]
            }
        },
        "CognitoUserPool": {
            "Type" : "AWS::Cognito::UserPool",
            "Properties" : {
                "UserPoolName" : {"Fn::Join":["", [ "user-pool-",{"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}]]}
            }
        },
        "CognitoIdentityPool": {
            "Type" : "AWS::Cognito::IdentityPool",
            "Properties" : {
                "IdentityPoolName" : {"Fn::Join":["", [ "identity-pool-",{"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}]]},
                "AllowUnauthenticatedIdentities" : "true"
            }
        },
        "IdentityPoolRoleAttachment": {
            "DependsOn": "AuthUserRole",
            "Type" : "AWS::Cognito::IdentityPoolRoleAttachment",
            "Properties" : {
                "IdentityPoolId": { "Ref": "CognitoIdentityPool"},
                "Roles": {
                    "authenticated": { "Fn::GetAtt": ["AuthUserRole", "Arn"]}
                }
            }
        },
        "CognitoDomain":{
	    "DependsOn": "CognitoUserPool",	
            "Type" : "AWS::Cognito::UserPoolDomain",
            "Properties" : {
                "Domain" : {"Fn::Join":["",["domain-",{"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}}]]},
                "UserPoolId" : {"Ref":"CognitoUserPool"}
            }
        },
	"WiringFunction": {
            "Type": "AWS::Lambda::Function",
            "DependsOn": ["LambdaExecutionRole","CognitoUserPool","CognitoIdentityPool"],
            "Properties" : {
                "Handler": "index.handler",
                "Role": { "Fn::GetAtt" : [ "LambdaExecutionRole", "Arn" ]},
                "Runtime": "python3.7",
                "Timeout": 300,
                "Environment": {
                    "Variables" : { 
                        "REGION": { "Ref" : "AWS::Region"},
                        "STACK_PREFIX": {"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}},
                        "USER_POOL_ID": { "Ref": "CognitoUserPool"}
                    }
                },
                "Code": {
                    "ZipFile": {"Fn::Join": ["",[
                        "from __future__ import print_function\n",
			"\n",
			"import json\n",
			"import os\n",
			"import random\n",
			"import uuid\n",
			"\n",
			"import boto3\n",
			"from botocore.vendored import requests\n",
			"\n",
			"def handler(event, context):\n",
			"    if event['RequestType'] == 'Create':\n",
			"        try:\n",
			"            create_cognito_user()\n",
			"        except Exception as e:\n",
			"            send_response(event, context, 'FAILED')\n",
			"            return False\n",
			"    send_response(event, context, 'SUCCESS')\n",
			"    return True\n",
			"\n",
			"def create_cognito_user():\n",
			"    cognito_idp = boto3.client('cognito-idp')\n",
			"    try:\n",
			"        response = cognito_idp.admin_create_user(\n",
			"            UserPoolId=os.environ['USER_POOL_ID'],\n",
			"            Username='kibana',\n",
			"            TemporaryPassword='Ab",
			{"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}},
			"!'\n",
			"        )\n",
			"    except Exception as e:\n",
			"        print('Exception creating Cognito user.\\nMessage: {}'.format(e.message))\n",
			"\n",
			"def send_response(event, context, status_code):\n",
			"    response_body = {'Status': status_code,\n",
			"                     'Reason': 'See CloudWatch Log Stream: ' + context.log_stream_name,\n",
			"                     'PhysicalResourceId': context.log_stream_name,\n",
			"                     'StackId': event['StackId'],\n",
			"                     'RequestId': event['RequestId'],\n",
			"                     'LogicalResourceId': event['LogicalResourceId'],\n",
			"                     'Data': {'Data': 'No data'}}\n",
			"    json_response_body = json.dumps(response_body)\n",
			"    print('Response: {}'.format(json_response_body))\n",
			"    headers = {\n",
			"        'content-type' : '',\n",
			"        'content-length' : str(len(json_response_body))\n",
			"    }\n",
			"    try:\n",
			"        req = requests.put(event['ResponseURL'],\n",
			"                           data=json_response_body,\n",
			"                           headers=headers)\n",
			"        if req.status_code != 200:\n",
			"            print('Received non 200 response while sending to CFN\\nText: {}'.format(req.text))\n",
			"            raise Exception('Recieved non 200 response while sending response to CFN.')\n",
			"        print('Successfully sent response to CFN\\n{}'.format(req.text))\n",
			"        return\n",
			"    except requests.exceptions.RequestException as e:\n",
			"        print(e)\n",
			"        raise\n",			
			"\n"
			]]
		    }
                }
            }
        },
        "WiringFunctionInvocation": {
            "Type": "Custom::WiringFunctionInvocation",
            "DependsOn": "WiringFunction",
            "Properties": {
                "ServiceToken": { "Fn::GetAtt": [ "WiringFunction", "Arn" ]},
                "Region": { "Ref": "AWS::Region"}
            }
        }
    },                                                                                              
    "Outputs":{
        "StackName":{
            "Description":"This is the stack name.",
            "Value": {"Ref":"AWS::StackName"},
            "Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-StackName" }}
	},
	"CognitoUser":{
            "Description":"This is the cognito user.",
            "Value": "kibana",
            "Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-CognitoUser" }}
	},
	"CognitoPassword":{
            "Description":"This is the cognito password.",
            "Value":{"Fn::Join":["",["Ab",{"Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-EnvTag"}},"!"]]},
            "Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-CognitoPassword" }}
	},	
	"CognitoUserPoolEndpoint":{
            "Description":"The endpoint of the Cognito User Pool",
            "Value":{"Fn::Join":["",[{"Ref":"CognitoDomain"},".auth.",{"Ref":"AWS::Region"},".amazoncognito.com"]]},
	    "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-CognitoUserPoolEndpoint" }}
	},
	"AuthRoleARN":{
	    "Description":"ARN of the Authentication Role for Cognito Users",
            "Value": { "Fn::GetAtt": [ "AuthUserRole", "Arn" ]},
            "Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-AuthRoleARN" }}

	}        
    }
}
