{
    "Description": "AD Join/Leave CloudFormation Template",
    "Metadata": {
        "AWS::CloudFormation::Interface": {
            "ParameterGroups": [
                {
                    "Label": {
                        "default": ""
                    },
                    "Parameters": [
                        "s3CodeBucket",
                        "adJoinLambdaCodeFileName",
                        "adJoinLambdaCodeVersion",
                        "DynamoDBTableName",
                        "CreateDynamoDBTable",
                        "ADToolsHostTagKey",
                        "ADToolsHostTagValue",
                        "snsTopicName"
                    ]
                }
            ]
        }
    },
    "Parameters": {
        "s3CodeBucket": {
            "Type": "String",
            "Default": "-s3CodeBucketName-",
            "Description": "S3 Code bucket containing Lambda code zip files."
        },
        "adJoinLambdaCodeFileName": {
            "Type": "String",
            "Default": "-zipFileWithCodeAndScripts-",
            "Description": "AD Join Lambda Code File Name."
        },
        "adJoinLambdaCodeVersion": {
            "Type": "String",
            "Default": "-s3ObjectVersionNumber-",
            "Description": "AD Join Lambda S3 code file version."
        },
        "DynamoDBTableName": {
            "Type": "String",
            "Default": "-dynamoDBAccountTableName-",
            "Description": "DynamoDB table to keep information about various AWS accounts and associated configuration."
        },
        "CreateDynamoDBTable": {
            "Type": "String",
            "Default": "False",
            "Description": "Flag to indicate creation of DynamoDB table (True=create)."
        },
        "ADToolsHostTagKey": {
            "Type": "String",
            "Default": "",
            "Description": "Tag key for ADTools instance."
        },
        "ADToolsHostTagValue": {
            "Type": "String",
            "Default": "",
            "Description": "Tag value for ADTools instance."
        },
        "snsTopicName": {
            "Type": "String",
            "Default": "ec2RunTerminateEvents",
            "Description": "SNS Topic name from other regions that forwards EC2 state events to main account's SQS queue."
        }
    },
    "Conditions": {
        "CreateDynamoDBTable": {
            "Fn::Equals": [
                {
                    "Ref": "CreateDynamoDBTable"
                },
                "True"
            ]
        }
    },
    "Resources": {
        "adLambdaExecutionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": {
                    "Fn::Sub": "${AWS::StackName}-LambdaRole"
                },
                "Policies": [
                    {
                        "PolicyName": {
                            "Fn::Sub": "${AWS::StackName}-LambdaPolicy"
                        },
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Sid": "MADAutoJoinPermissions",
                                    "Effect": "Allow",
                                    "Action": [
                                        "ssm:SendCommand",
                                        "ec2:DescribeInstances",
                                        "ds:DescribeDirectories",
                                        "ssm:GetParameter",
                                        "ssm:PutParameter",
                                        "ssm:StartAutomationExecution",
                                        "dynamodb:Scan",
                                        "dynamodb:Query",
                                        "sts:AssumeRole"
                                    ],
                                    "Resource": "*"
                                },
                                {
                                    "Sid": "SQSPermissions",
                                    "Effect": "Allow",
                                    "Action": [
                                        "sqs:SendMessage"
                                    ],
                                    "Resource": {
                                        "Fn::GetAtt": [
                                            "EC2RunTerminateEventsQueue",
                                            "Arn"
                                        ]
                                    }
                                },
                                {
                                    "Sid": "CloudWatchLogsPermissions",
                                    "Effect": "Allow",
                                    "Action": [
                                        "logs:CreateLogGroup",
                                        "logs:CreateLogStream",
                                        "logs:PutLogEvents"
                                    ],
                                    "Resource": {
                                        "Fn::Sub": "arn:${AWS::Partition}:logs:*:*:*"
                                    }
                                }
                            ]
                        }
                    }
                ],
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                }
            }
        },
        "EC2RunEventsSQSToLambda": {
            "Type": "AWS::Lambda::EventSourceMapping",
            "Properties": {
                "EventSourceArn": {
                    "Fn::GetAtt": [
                        "EC2RunTerminateEventsQueue",
                        "Arn"
                    ]
                },
                "FunctionName": {
                    "Ref": "JoinDomainLambdaFunction"
                }
            }
        },
        "EC2RunTerminateEventsQueue": {
            "Type": "AWS::SQS::Queue",
            "Properties": {
                "DelaySeconds": 300,
                "QueueName": {
                    "Fn::Sub": "${AWS::StackName}-EC2RunEvents"
                },
                "VisibilityTimeout": 300,
                "MessageRetentionPeriod": 7200
            }
        },
        "EC2RunTerminateEventsQueuePolicy": {
            "Type": "AWS::SQS::QueuePolicy",
            "Properties": {
                "PolicyDocument": {
                    "Id": "QueuePolicy",
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "AWS": [
                                    {
                                        "Fn::GetAtt": [
                                            "adLambdaExecutionRole",
                                            "Arn"
                                        ]
                                    }
                                ]
                            },
                            "Action": [
                                "sqs:ReceiveMessage",
                                "sqs:DeleteMessage",
                                "sqs:GetQueueAttributes"
                            ],
                            "Resource": [
                                {
                                    "Fn::GetAtt": [
                                        "EC2RunTerminateEventsQueue",
                                        "Arn"
                                    ]
                                }
                            ]
                        },
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "events.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sqs:SendMessage"
                            ],
                            "Resource": [
                                {
                                    "Fn::GetAtt": [
                                        "EC2RunTerminateEventsQueue",
                                        "Arn"
                                    ]
                                }
                            ]
                        },
                        {
                            "Effect": "Allow",
                            "Principal": "*",
                            "Action": [
                                "sqs:SendMessage"
                            ],
                            "Resource": [
                                {
                                    "Fn::GetAtt": [
                                        "EC2RunTerminateEventsQueue",
                                        "Arn"
                                    ]
                                }
                            ],
                            "Condition": {
                                "ArnEquals": {
                                    "aws:SourceArn": {
                                        "Fn::Sub": "arn:aws:sns:*:${AWS::AccountId}:${snsTopicName}"
                                    }
                                }
                            }
                        }
                    ]
                },
                "Queues": [
                    {
                        "Ref": "EC2RunTerminateEventsQueue"
                    }
                ]
            }
        },
        "JoinDomainLambdaFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "FunctionName": "adJoinInstanceToDomain",
                "Handler": "adJoinInstanceToDomain.lambda_handler",
                "Role": {
                    "Fn::GetAtt": [
                        "adLambdaExecutionRole",
                        "Arn"
                    ]
                },
                "Code": {
                    "S3Bucket": {
                        "Ref": "s3CodeBucket"
                    },
                    "S3Key": {
                        "Ref": "adJoinLambdaCodeFileName"
                    },
                    "S3ObjectVersion": {
                        "Ref": "adJoinLambdaCodeVersion"
                    }
                },
                "DeadLetterConfig": {
                    "TargetArn": {
                        "Fn::GetAtt": [
                            "EC2RunTerminateEventsQueue",
                            "Arn"
                        ]
                    }
                },
                "Runtime": "python3.6",
                "Timeout": 30,
                "Environment": {
                    "Variables": {
                        "dynamoDBTableName": {
                            "Ref": "DynamoDBTableName"
                        },
                        "ADToolsHostTagKey": {
                            "Ref": "ADToolsHostTagKey"
                        },
                        "ADToolsHostTagValue": {
                            "Ref": "ADToolsHostTagValue"
                        },
                        "LogLevel": "10"
                    }
                }
            }
        },
        "AdJoinEventRule": {
            "Type": "AWS::Events::Rule",
            "Properties": {
                "Description": "EventRule",
                "EventPattern": {
                    "source": [
                        "aws.ec2"
                    ],
                    "detail-type": [
                        "EC2 Instance State-change Notification"
                    ],
                    "detail": {
                        "state": [
                            "running",
                            "terminated"
                        ]
                    }
                },
                "Targets": [
                    {
                        "Arn": {
                            "Fn::GetAtt": [
                                "EC2RunTerminateEventsQueue",
                                "Arn"
                            ]
                        },
                        "Id": "TargetQueueV1"
                    }
                ]
            }
        },
        "PermissionForEventsToInvokeLambda": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "FunctionName": {
                    "Ref": "JoinDomainLambdaFunction"
                },
                "Action": "lambda:InvokeFunction",
                "Principal": "sqs.amazonaws.com",
                "SourceArn": {
                    "Fn::GetAtt": [
                        "EC2RunTerminateEventsQueue",
                        "Arn"
                    ]
                }
            }
        },
        "accountCfgTable": {
            "Type": "AWS::DynamoDB::Table",
            "Condition": "CreateDynamoDBTable",
            "DeletionPolicy": "Retain",
            "UpdateReplacePolicy" : "Retain",
            "Properties": {
                "TableName": {
                    "Ref": "DynamoDBTableName"
                },
                "AttributeDefinitions": [
                    {
                        "AttributeName": "accountId",
                        "AttributeType": "S"
                    }
                ],
                "KeySchema": [
                    {
                        "AttributeName": "accountId",
                        "KeyType": "HASH"
                    }
                ],
                "ProvisionedThroughput": {
                    "ReadCapacityUnits": "5",
                    "WriteCapacityUnits": "5"
                }
            }
        }
    }
}