{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "API for SSM",
    "Metadata": {
        "PowerShell": [
            "$ssmUrl = \"\"",
            "Write-Host \"Downloading SSM\"",
            "(New-Object System.Net.WebClient).DownloadFile(\"https://amazon-ssm-ap-southeast-2.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe\", \"$env:temp\\AmazonSSMAgentSetup.exe\")",
            "Write-Host \"Getting Instance ID\"",
            "$instanceId = Invoke-RestMethod -Method GET -Uri http://169.254.169.254/latest/meta-data/instance-id",
            "# Get activation code for SSM",
            "Write-Host \"Getting Activation Code for $instanceId\"",
            "$activation = Invoke-RestMethod -Method GET -Uri \"https://$ssmUrl/latest/activate?name=$instanceId\"",
            "$activationId = $activation.ActivationId",
            "$activationCode = $activation.ActivationCode",
            "#Install SSM",
            "Write-Host \"Installing SSM with $activationId and $activationCode\"",
            "Start-Process $env:temp\\AmazonSSMAgentSetup.exe -ArgumentList \"/quiet /log $env:temp\\ssm-agent-install.log CODE=$activationCode ID=$activationId REGION=ap-southeast-2\" -Wait",
            "$managedInstanceId = (Get-Content ($env:ProgramData + \"\\Amazon\\SSM\\InstanceData\\registration\") | ConvertFrom-Json).ManagedInstanceID",
            "Get-Service -Name \"AmazonSSMAgent\"",
            "Write-Host \"Registered with Managed Instance ID $managedInstanceId\"",
            "# Tag instance in SSM",
            "$body = @{tags = ",
            "    @(",
            "        @{",
            "            name = \"Custom\"",
            "            value = \"Value\"",
            "        }",
            "    )",
            "} ",
            "Write-Host \"Tagging Instance\"",
            "Invoke-RestMethod -Method POST -Uri \"https://$ssmUrl/latest/tags/$managedInstanceId\" -Body ($body | ConvertTo-Json)"
        ]
    },
    "Resources": {
        "EC2RoleforSSM": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "RoleName": "AmazonEC2RunCommandRoleForManagedInstances",
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "ssm.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "Path": "/",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
                ]
            }
        },
        "ActivateFunctionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
                ],
                "Policies": [
                    {
                        "PolicyName": "ssm",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "iam:PassRole",
                                        "ssm:CreateActivation"
                                    ],
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "ActivateFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "\n",
                            [
                                "// v2",
                                "const AWS = require('aws-sdk');",
                                "const ssm = new AWS.SSM();",
                                "const {",
                                "    role",
                                "} = process.env;",
                                "exports.handler = (event) => {",
                                "    return new Promise((resolve, reject) => {",
                                "        const {",
                                "            name",
                                "        } = event.queryStringParameters;",
                                "        ssm.createActivation({",
                                "            IamRole: role,",
                                "            DefaultInstanceName: name,",
                                "        }).promise()",
                                "            .then((data) => {",
                                "                resolve({",
                                "                    statusCode: '200',",
                                "                    body: JSON.stringify(data)",
                                "                });",
                                "            })",
                                "            .catch((err) => {",
                                "                reject(err);",
                                "            });",
                                "    });",
                                "};"
                            ]
                        ]
                    }
                },
                "Handler": "index.handler",
                "Role": {
                    "Fn::GetAtt": [
                        "ActivateFunctionRole",
                        "Arn"
                    ]
                },
                "Runtime": "nodejs14.x",
                "Environment": {
                    "Variables": {
                        "role": {
                            "Ref": "EC2RoleforSSM"
                        }
                    }
                }
            }
        },
        "TagFunction": {
            "Type": "AWS::Lambda::Function",
            "Properties": {
                "Code": {
                    "ZipFile": {
                        "Fn::Join": [
                            "\n",
                            [
                                "const AWS = require('aws-sdk');",
                                "const ssm = new AWS.SSM();",
                                "exports.handler = (event) => {",
                                "    return new Promise((resolve, reject) => {",
                                "        const {",
                                "            managedInstanceId",
                                "        } = event.pathParameters;",
                                "        const body = JSON.parse(event.body);",
                                "        ssm.addTagsToResource({",
                                "            ResourceId: managedInstanceId,",
                                "            ResourceType: 'ManagedInstance',",
                                "            Tags: body.tags.map((tag) => {",
                                "                return {",
                                "                    Key: tag.name,",
                                "                    Value: tag.value",
                                "                };",
                                "            })",
                                "        }).promise()",
                                "            .then(() => {",
                                "                resolve({",
                                "                    statusCode: '200',",
                                "                });",
                                "            })",
                                "            .catch((err) => { reject(err); });",
                                "    });",
                                "};"
                            ]
                        ]
                    }
                },
                "Handler": "index.handler",
                "Role": {
                    "Fn::GetAtt": [
                        "TagFunctionRole",
                        "Arn"
                    ]
                },
                "Runtime": "nodejs14.x"
            }
        },
        "TagFunctionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "lambda.amazonaws.com"
                                ]
                            },
                            "Action": [
                                "sts:AssumeRole"
                            ]
                        }
                    ]
                },
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
                ],
                "Policies": [
                    {
                        "PolicyName": "ssm",
                        "PolicyDocument": {
                            "Version": "2012-10-17",
                            "Statement": [
                                {
                                    "Effect": "Allow",
                                    "Action": [
                                        "ssm:AddTagsToResource"
                                    ],
                                    "Resource": "*"
                                }
                            ]
                        }
                    }
                ]
            }
        },
        "RestApi": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "Body": {
                    "swagger": "2.0",
                    "info": {
                        "title": "ssm"
                    },
                    "paths": {
                        "/activate": {
                            "get": {
                                "parameters": [
                                    {
                                        "in": "query",
                                        "name": "name",
                                        "type": "string",
                                        "description": "Instance name",
                                        "required": true
                                    }
                                ],
                                "produces": [
                                    "application/json"
                                ],
                                "responses": {
                                    "200": {
                                        "description": "200 response",
                                        "schema": {
                                            "$ref": "#/definitions/Activation"
                                        }
                                    }
                                },
                                "x-amazon-apigateway-request-validator": "Validate query string parameters and headers",
                                "x-amazon-apigateway-integration": {
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${ActivateFunction}/invocations"
                                    },
                                    "responses": {
                                        "default": {
                                            "statusCode": "200"
                                        }
                                    },
                                    "passthroughBehavior": "when_no_match",
                                    "httpMethod": "POST",
                                    "contentHandling": "CONVERT_TO_TEXT",
                                    "type": "aws_proxy"
                                }
                            }
                        },
                        "/tags/{managedInstanceId}": {
                            "post": {
                                "parameters": [
                                    {
                                        "name": "managedInstanceId",
                                        "in": "path",
                                        "required": true,
                                        "type": "string"
                                    },
                                    {
                                        "in": "body",
                                        "name": "Tags",
                                        "required": true,
                                        "schema": {
                                            "$ref": "#/definitions/Tags"
                                        }
                                    }
                                ],
                                "produces": [
                                    "application/json"
                                ],
                                "responses": {
                                    "200": {
                                        "description": "200 response",
                                        "schema": {
                                            "$ref": "#/definitions/Empty"
                                        }
                                    }
                                },
                                "x-amazon-apigateway-request-validator": "Validate body",
                                "x-amazon-apigateway-integration": {
                                    "uri": {
                                        "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${TagFunction}/invocations"
                                    },
                                    "responses": {
                                        "default": {
                                            "statusCode": "200"
                                        }
                                    },
                                    "passthroughBehavior": "when_no_match",
                                    "httpMethod": "POST",
                                    "contentHandling": "CONVERT_TO_TEXT",
                                    "type": "aws_proxy"
                                }
                            }
                        }
                    },
                    "definitions": {
                        "Empty": {
                            "type": "object",
                            "title": "Empty Schema"
                        },
                        "Activation": {
                            "type": "object",
                            "required": [
                                "ActivationCode",
                                "ActivationId"
                            ],
                            "properties": {
                                "ActivationId": {
                                    "type": "string"
                                },
                                "ActivationCode": {
                                    "type": "string"
                                }
                            }
                        },
                        "Tags": {
                            "type": "object",
                            "required": [
                                "tags"
                            ],
                            "properties": {
                                "tags": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "name": {
                                                "type": "string"
                                            },
                                            "value": {
                                                "type": "string"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "x-amazon-apigateway-request-validators": {
                        "Validate body": {
                            "validateRequestParameters": false,
                            "validateRequestBody": true
                        },
                        "Validate query string parameters and headers": {
                            "validateRequestParameters": true,
                            "validateRequestBody": false
                        }
                    }
                },
                "Parameters": {
                    "endpointConfigurationTypes": "REGIONAL"
                }
            }
        },
        "Deployment": {
            "Type": "AWS::ApiGateway::Deployment",
            "Properties": {
                "RestApiId": {
                    "Ref": "RestApi"
                }
            }
        },
        "Stage": {
            "Type": "AWS::ApiGateway::Stage",
            "Properties": {
                "DeploymentId": {
                    "Ref": "Deployment"
                },
                "RestApiId": {
                    "Ref": "RestApi"
                },
                "StageName": "latest"
            }
        },
        "TagFunctionPermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:invokeFunction",
                "FunctionName": {
                    "Fn::GetAtt": [
                        "TagFunction",
                        "Arn"
                    ]
                },
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {
                    "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*"
                }
            }
        },
        "ActivateFunctionPermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:invokeFunction",
                "FunctionName": {
                    "Fn::GetAtt": [
                        "ActivateFunction",
                        "Arn"
                    ]
                },
                "Principal": "apigateway.amazonaws.com",
                "SourceArn": {
                    "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*"
                }
            }
        }
    },
    "Outputs": {
        "URL": {
            "Description": "SSM API URL",
            "Value": {
                "Fn::Sub": "https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com"
            }
        }
    }
}