From 7b4d6cc426d27c2fb953f8206da0d4d8044fef09 Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Thu, 2 Dec 2021 11:48:53 -0300 Subject: [PATCH 1/6] Create AMI using packer --- Makefile | 8 ++++ lib/aws-semaphore-agent-stack.js | 32 ++++++++++++- packer/linux-ami.pkr.hcl | 72 ++++++++++++++++++++++++++++ packer/scripts/install-agent.sh | 21 ++++++++ packer/scripts/install-utils.sh | 2 + packer/scripts/terminate-instance.sh | 4 ++ 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 packer/linux-ami.pkr.hcl create mode 100755 packer/scripts/install-agent.sh create mode 100755 packer/scripts/install-utils.sh create mode 100755 packer/scripts/terminate-instance.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..528f744 --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +packer.fmt: + cd packer && packer fmt . && cd - + +packer.validate: + cd packer && packer validate . && cd - + +packer.build: + cd packer && packer build linux-ami.pkr.hcl && cd - diff --git a/lib/aws-semaphore-agent-stack.js b/lib/aws-semaphore-agent-stack.js index 747c030..bf7e205 100644 --- a/lib/aws-semaphore-agent-stack.js +++ b/lib/aws-semaphore-agent-stack.js @@ -139,11 +139,41 @@ class AwsSemaphoreAgentStack extends cdk.Stack { description: "The instance type to use to launch auto scaling instances." }); + const semaphoreAgentVersionParameter = new cdk.CfnParameter(this, "semaphoreAgentVersion", { + type: "String", + description: "The agent version to use.", + default: "v2.0.16" + }); + + const semaphoreOrganizationParameter = new cdk.CfnParameter(this, "semaphoreOrganization", { + type: "String", + description: "The semaphore organization to use for the agent." + }); + + const semaphoreTokenParameter = new cdk.CfnParameter(this, "semaphoreToken", { + type: "String", + description: "The semaphore registration token to use for the agent.", + noEcho: true, + }); + + const machineUserParameter = new cdk.CfnParameter(this, "machineUser", { + type: "String", + description: "The user to run the agent on the machine.", + default: "ubuntu", + }); + let launchConfig = new autoscaling.CfnLaunchConfiguration(this, 'launchConfiguration', { launchConfigurationName: `${stackPrefix}-launch-configuration`, imageId: imageIdParameter.valueAsString, instanceType: instanceTypeParameter.valueAsString, - iamInstanceProfile: iamInstanceProfile.attrArn + iamInstanceProfile: iamInstanceProfile.attrArn, + userData: ` + export AGENT_VERSION=${semaphoreAgentVersionParameter.valueAsString} + export SEMAPHORE_ORGANIZATION=${semaphoreOrganizationParameter.valueAsString} + export SEMAPHORE_REGISTRATION_TOKEN=${semaphoreTokenParameter.valueAsString} + export SEMAPHORE_AGENT_INSTALLATION_USER=${machineUserParameter.valueAsString} + /tmp/install-agent.sh + `, // keyName: '', // securityGroups: [] }); diff --git a/packer/linux-ami.pkr.hcl b/packer/linux-ami.pkr.hcl new file mode 100644 index 0000000..fd896cf --- /dev/null +++ b/packer/linux-ami.pkr.hcl @@ -0,0 +1,72 @@ +variable "ami_prefix" { + type = string + default = "semaphore-agent-base" +} + +variable "region" { + type = string + default = "us-east-1" +} + +variable "instance_type" { + type = string + default = "t2.micro" +} + +locals { + timestamp = regex_replace(timestamp(), "[- TZ:]", "") +} + +packer { + required_plugins { + amazon = { + version = ">= 0.0.2" + source = "github.com/hashicorp/amazon" + } + } +} + +source "amazon-ebs" "ubuntu" { + ami_name = "${var.ami_prefix}-linux-${local.timestamp}" + region = "${var.region}" + instance_type = "${var.instance_type}" + ssh_username = "ubuntu" + + source_ami_filter { + most_recent = true + + // Canonical's ownerId: https://ubuntu.com/server/docs/cloud-images/amazon-ec2 + owners = ["099720109477"] + + filters = { + name = "ubuntu/images/*ubuntu-bionic-18.04-amd64-server-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + } +} + +build { + name = "semaphore-agent-base" + + sources = [ + "source.amazon-ebs.ubuntu" + ] + + # Install dependencies + provisioner "shell" { + scripts = [ + "scripts/install-utils.sh" + ] + } + + provisioner "file" { + destination = "/tmp/" + sources = [ + # Required for the asg launch configuration + "scripts/install-agent.sh", + # Required by the agent + "scripts/terminate-instance.sh" + ] + } +} \ No newline at end of file diff --git a/packer/scripts/install-agent.sh b/packer/scripts/install-agent.sh new file mode 100755 index 0000000..b820e1b --- /dev/null +++ b/packer/scripts/install-agent.sh @@ -0,0 +1,21 @@ +[[ -z "${AGENT_VERSION}" ]] && echo "AGENT_VERSION is not set" && exit 1 +[[ -z "${SEMAPHORE_ORGANIZATION}" ]] && echo "SEMAPHORE_ORGANIZATION is not set" && exit 1 +[[ -z "${SEMAPHORE_REGISTRATION_TOKEN}" ]] && echo "SEMAPHORE_REGISTRATION_TOKEN is not set" && exit 1 +[[ -z "${SEMAPHORE_AGENT_INSTALLATION_USER}" ]] && echo "SEMAPHORE_AGENT_INSTALLATION_USER is not set" && exit 1 + +# Download agent +sudo mkdir -p /opt/semaphore/agent +sudo curl -L https://github.com/semaphoreci/agent/releases/download/${AGENT_VERSION}/agent_Linux_x86_64.tar.gz -o /opt/semaphore/agent/agent.tar.gz +sudo tar -xf /opt/semaphore/agent/agent.tar.gz -C /opt/semaphore/agent +sudo rm /opt/semaphore/agent/agent.tar.gz +sudo chown $USER:$USER -R /opt/semaphore/agent/ +cd /opt/semaphore/agent/ + +# Installs agent, but keeps it stopped for now +# It will be started when the instance goes into rotation +mkdir hooks +mv /tmp/terminate-instance.sh /opt/semaphore/agent/hooks/shutdown +export SEMAPHORE_AGENT_SHUTDOWN_HOOK=/opt/semaphore/agent/hooks/shutdown +export SEMAPHORE_AGENT_DISCONNECT_AFTER_JOB=true +export SEMAPHORE_AGENT_DO_NOT_START=true +sudo -E ./install.sh diff --git a/packer/scripts/install-utils.sh b/packer/scripts/install-utils.sh new file mode 100755 index 0000000..cb5b12a --- /dev/null +++ b/packer/scripts/install-utils.sh @@ -0,0 +1,2 @@ +sudo apt-get update +sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release git make unzip policykit-1 jq awscli \ No newline at end of file diff --git a/packer/scripts/terminate-instance.sh b/packer/scripts/terminate-instance.sh new file mode 100755 index 0000000..1ab8f7c --- /dev/null +++ b/packer/scripts/terminate-instance.sh @@ -0,0 +1,4 @@ +token=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 60" --fail --silent --show-error --location "http://169.254.169.254/latest/api/token") +instance_id=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/instance-id") +region=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/placement/region") +aws autoscaling terminate-instance-in-auto-scaling-group --region "$region" --instance-id "$instance_id" "--no-should-decrement-desired-capacity" From b91a4bc0b8af7c6f60663a35cf315d93994d12a6 Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Thu, 2 Dec 2021 19:40:18 -0300 Subject: [PATCH 2/6] Install agent using SSM command --- README.md | 62 +- lambda/app.js | 40 +- lib/aws-semaphore-agent-stack.js | 112 ++-- package-lock.json | 941 ++++++++++++++++++++++++++++++- package.json | 1 + packer/linux-ami.pkr.hcl | 8 + packer/scripts/install-agent.sh | 8 +- packer/scripts/install-utils.sh | 9 +- 8 files changed, 1117 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index e3e563e..1d34ce4 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,58 @@ -# Welcome to your CDK JavaScript project! +# Semaphore agent AWS stack -This is a blank project for JavaScript development with CDK. +This project is a CDK application used to deploy a Semaphore agent stack in AWS. -The `cdk.json` file tells the CDK Toolkit how to execute your app. The build step is not required when using JavaScript. +## Requisites -## Useful commands +### AMI - * `npm run test` perform the jest unit tests - * `cdk deploy` deploy this stack to your default AWS account/region - * `cdk diff` compare deployed stack with current state - * `cdk synth` emits the synthesized CloudFormation template +The agents need an AMI id to use. If you haven't created one yet, just run: + +```bash +make packer.build +``` + +This command uses packer to create an AWS EC2 AMI with everything the agent needs. + +### CDK bootstrap + +The AWS CDK requires a few resources to be around for it to work. It creates them with the `bootstrap` command: + +```bash +cdk bootstrap aws:/// +``` + +## Generate the cloudformation stack + +Under the hood, all the AWS CDK does is create a cloudformation stack. You can check the one it creates with: + +```bash +cdk synth +``` + +## Deploying the stack + +In order to deploy it, you are required to pass a few parameters: +- `imageId`: this is the AMI you created with `make packer.build` above. +- `semaphoreOrganization`: this is your Semaphore organization. +- `semaphoreToken`: this is the registration token for your agent type. + +Other optional arguments are available: +- `instanceType`: this is the instance type the stack will use for your agents. By default, this is `t2.micro`. +- `minSize`: the minimum size for your agent auto scaling group. By default, this is 0. +- `maxSize`: the maximum size for your agent auto scaling group. By default, this is 1. +- `desiredCapacity`: the initial desired capacity for your agent auto scaling group. By default, this is 1 +- `semaphoreAgentVersion`: the version of the agent to deploy. By default, the latest one. + +```bash +cdk deploy \ + --parameters imageId=ami-09676b8af848f9e92 \ + --parameters semaphoreOrganization=semaphore \ + --parameters semaphoreToken=YOUR_VERY_SENSITIVE_TOKEN +``` + +## Destroying the stack + +```bash +cdk destroy +``` \ No newline at end of file diff --git a/lambda/app.js b/lambda/app.js index c42b3ad..105d3c1 100644 --- a/lambda/app.js +++ b/lambda/app.js @@ -58,7 +58,30 @@ function getInstanceStatus(instanceId) { }); } -function startAgentOnInstance(instanceId) { +function getAgentParameters() { + var ssm = new aws.SSM(); + + return new Promise(function(resolve, reject) { + var params = { + Name: "semaphore-agent-params" + }; + + ssm.getParameter(params, function(err, data) { + if (err) { + reject(err); + } else { + agentParams = JSON.parse(data.Parameter.Value); + + // TODO: this shouldn't be logged + console.log("Agent params: ", agentParams); + + resolve(agentParams); + } + }); + }); +} + +function startAgentOnInstance(instanceId, agentParameters) { var ssm = new aws.SSM(); return new Promise(function(resolve, reject) { @@ -66,7 +89,13 @@ function startAgentOnInstance(instanceId) { InstanceIds: [instanceId], DocumentName: 'AWS-RunShellScript', Parameters: { - commands: ['sudo systemctl start semaphore-agent'], + commands: [ + `export AGENT_VERSION=${agentParameters.agentVersion}`, + `export SEMAPHORE_ORGANIZATION=${agentParameters.organization}`, + `export SEMAPHORE_REGISTRATION_TOKEN=${agentParameters.token}`, + `export SEMAPHORE_AGENT_INSTALLATION_USER=${agentParameters.vmUser}`, + '/opt/semaphore/install-agent.sh' + ], executionTimeout: ['10'] }, }; @@ -141,8 +170,11 @@ exports.handler = async (event, context, callback) => { } // Instance is online, let's execute the command to start the agent - console.log("Instance '" + instanceId + "' is '" + instanceStatus + "'. Sending command to start agent..."); - var commandId = await startAgentOnInstance(instanceId); + console.log("Instance '" + instanceId + "' is '" + instanceStatus + "'. Grabbing agent parameters..."); + var agentParameters = await getAgentParameters(); + + console.log("Sending command to start agent...") + var commandId = await startAgentOnInstance(instanceId, agentParameters); var commandStatus = 'Pending'; // Poll the command status diff --git a/lib/aws-semaphore-agent-stack.js b/lib/aws-semaphore-agent-stack.js index bf7e205..b6bf92a 100644 --- a/lib/aws-semaphore-agent-stack.js +++ b/lib/aws-semaphore-agent-stack.js @@ -4,20 +4,32 @@ const lambda = require("@aws-cdk/aws-lambda"); const events = require("@aws-cdk/aws-events"); const eventTargets = require("@aws-cdk/aws-events-targets"); const autoscaling = require("@aws-cdk/aws-autoscaling"); +const ssm = require("@aws-cdk/aws-ssm"); const stackPrefix = "semaphore-agent"; const autoscalingGroupName = `${stackPrefix}-asg`; +const ssmParameterName = `${stackPrefix}-params`; class AwsSemaphoreAgentStack extends cdk.Stack { constructor(scope, id, props) { super(scope, id, props); + /** + * The lambda function needs information about the agent in order to install it. + * The only way for it to grab that information is through an SSM Parameter. + * + * Note that this creates a tight coupling between this script and the lambda script, + * as both of them need to use the proper parameter name and structure. So, if you + * change anything about the SSM Parameter, the lambda will probably need to change as well. + */ + let ssmParameter = this.createSSMParameter(); + /** * The lambda and EventBridge rule is created before the scaling group * because it needs to be present before the auto scaling group exists. * Otherwise, the initial instances will not have the agent started. */ - let lambdaRole = this.createRoleForLambda(); + let lambdaRole = this.createRoleForLambda(ssmParameter); let lambda = this.createLambdaFunction(lambdaRole); this.createEventBridgeRule(lambda); @@ -27,6 +39,46 @@ class AwsSemaphoreAgentStack extends cdk.Stack { this.createWarmPool(autoScalingGroup); } + // TODO: this should be encrypted + createSSMParameter() { + const semaphoreOrganizationParameter = new cdk.CfnParameter(this, "semaphoreOrganization", { + type: "String", + description: "The semaphore organization to use for the agent." + }); + + const semaphoreTokenParameter = new cdk.CfnParameter(this, "semaphoreToken", { + type: "String", + description: "The semaphore registration token to use for the agent.", + noEcho: true, + }); + + const semaphoreAgentVersionParameter = new cdk.CfnParameter(this, "semaphoreAgentVersion", { + type: "String", + description: "The agent version to use.", + default: "v2.0.16" + }); + + const machineUserParameter = new cdk.CfnParameter(this, "machineUser", { + type: "String", + description: "The user to run the agent on the machine.", + default: "ubuntu", + }); + + let parameters = { + agentVersion: semaphoreAgentVersionParameter.valueAsString, + organization: semaphoreOrganizationParameter.valueAsString, + token: semaphoreTokenParameter.valueAsString, + vmUser: machineUserParameter.valueAsString + } + + return new ssm.StringParameter(this, `SemaphoreAgentParameter`, { + description: 'Parameters required by the semaphore agent', + parameterName: ssmParameterName, + stringValue: JSON.stringify(parameters), + tier: ssm.ParameterTier.STANDARD, + }); + } + createIamInstanceProfile() { let account = cdk.Stack.of(this).account; let ec2Role = new iam.Role(this, 'ec2Role', { @@ -54,7 +106,10 @@ class AwsSemaphoreAgentStack extends cdk.Stack { return iamInstanceProfile; } - createRoleForLambda() { + createRoleForLambda(ssmParameter) { + const lambdaRoleDependencies = new cdk.ConcreteDependable(); + lambdaRoleDependencies.add(ssmParameter); + let account = cdk.Stack.of(this).account; let lambdaRole = new iam.Role(this, 'lambdaRole', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), @@ -78,6 +133,14 @@ class AwsSemaphoreAgentStack extends cdk.Stack { ] })); + lambdaRole.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ["ssm:GetParameter"], + resources: [ + `arn:aws:ssm:*:*:parameter/${ssmParameterName}` + ] + })) + lambdaRole.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ @@ -87,6 +150,7 @@ class AwsSemaphoreAgentStack extends cdk.Stack { resources: ["*"] })); + lambdaRole.node.addDependency(lambdaRoleDependencies); return lambdaRole; } @@ -136,44 +200,15 @@ class AwsSemaphoreAgentStack extends cdk.Stack { const instanceTypeParameter = new cdk.CfnParameter(this, "instanceType", { type: "String", - description: "The instance type to use to launch auto scaling instances." - }); - - const semaphoreAgentVersionParameter = new cdk.CfnParameter(this, "semaphoreAgentVersion", { - type: "String", - description: "The agent version to use.", - default: "v2.0.16" - }); - - const semaphoreOrganizationParameter = new cdk.CfnParameter(this, "semaphoreOrganization", { - type: "String", - description: "The semaphore organization to use for the agent." - }); - - const semaphoreTokenParameter = new cdk.CfnParameter(this, "semaphoreToken", { - type: "String", - description: "The semaphore registration token to use for the agent.", - noEcho: true, - }); - - const machineUserParameter = new cdk.CfnParameter(this, "machineUser", { - type: "String", - description: "The user to run the agent on the machine.", - default: "ubuntu", + description: "The instance type to use to launch auto scaling instances.", + default: "t2.micro" }); let launchConfig = new autoscaling.CfnLaunchConfiguration(this, 'launchConfiguration', { launchConfigurationName: `${stackPrefix}-launch-configuration`, imageId: imageIdParameter.valueAsString, instanceType: instanceTypeParameter.valueAsString, - iamInstanceProfile: iamInstanceProfile.attrArn, - userData: ` - export AGENT_VERSION=${semaphoreAgentVersionParameter.valueAsString} - export SEMAPHORE_ORGANIZATION=${semaphoreOrganizationParameter.valueAsString} - export SEMAPHORE_REGISTRATION_TOKEN=${semaphoreTokenParameter.valueAsString} - export SEMAPHORE_AGENT_INSTALLATION_USER=${machineUserParameter.valueAsString} - /tmp/install-agent.sh - `, + iamInstanceProfile: iamInstanceProfile.attrArn // keyName: '', // securityGroups: [] }); @@ -187,17 +222,20 @@ class AwsSemaphoreAgentStack extends cdk.Stack { const minSizeParameter = new cdk.CfnParameter(this, "minSize", { type: "String", - description: "The minSize for the semaphore-agent auto scaling group." + description: "The minSize for the semaphore-agent auto scaling group.", + default: "0" }); const maxSizeParameter = new cdk.CfnParameter(this, "maxSize", { type: "String", - description: "The maxSize for the semaphore-agent auto scaling group." + description: "The maxSize for the semaphore-agent auto scaling group.", + default: "1" }); const desiredCapacityParameter = new cdk.CfnParameter(this, "desiredCapacity", { type: "String", - description: "The desired capacity for the semaphore-agent auto scaling group." + description: "The desired capacity for the semaphore-agent auto scaling group.", + default: "1" }); const autoScalingGroupDependencies = new cdk.ConcreteDependable(); diff --git a/package-lock.json b/package-lock.json index 97a85a6..44f1d84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -143,6 +143,20 @@ "@aws-cdk/core": "1.130.0", "@aws-cdk/cx-api": "1.130.0", "constructs": "^3.3.69" + }, + "dependencies": { + "@aws-cdk/aws-ssm": { + "version": "1.130.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.130.0.tgz", + "integrity": "sha512-93q58dcxt0r9FB5B8ceg7JhqfSx3XCG7uNSTDq6MzIIq4hcRDvahneS4TiMOzYdVuLAXCYE13GZXxQSSQ0TAgQ==", + "requires": { + "@aws-cdk/aws-iam": "1.130.0", + "@aws-cdk/aws-kms": "1.130.0", + "@aws-cdk/cloud-assembly-schema": "1.130.0", + "@aws-cdk/core": "1.130.0", + "constructs": "^3.3.69" + } + } } }, "@aws-cdk/aws-cloudwatch": { @@ -267,6 +281,20 @@ "@aws-cdk/cx-api": "1.130.0", "@aws-cdk/region-info": "1.130.0", "constructs": "^3.3.69" + }, + "dependencies": { + "@aws-cdk/aws-ssm": { + "version": "1.130.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.130.0.tgz", + "integrity": "sha512-93q58dcxt0r9FB5B8ceg7JhqfSx3XCG7uNSTDq6MzIIq4hcRDvahneS4TiMOzYdVuLAXCYE13GZXxQSSQ0TAgQ==", + "requires": { + "@aws-cdk/aws-iam": "1.130.0", + "@aws-cdk/aws-kms": "1.130.0", + "@aws-cdk/cloud-assembly-schema": "1.130.0", + "@aws-cdk/core": "1.130.0", + "constructs": "^3.3.69" + } + } } }, "@aws-cdk/aws-ecr": { @@ -351,6 +379,20 @@ "@aws-cdk/core": "1.130.0", "@aws-cdk/cx-api": "1.130.0", "constructs": "^3.3.69" + }, + "dependencies": { + "@aws-cdk/aws-ssm": { + "version": "1.130.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.130.0.tgz", + "integrity": "sha512-93q58dcxt0r9FB5B8ceg7JhqfSx3XCG7uNSTDq6MzIIq4hcRDvahneS4TiMOzYdVuLAXCYE13GZXxQSSQ0TAgQ==", + "requires": { + "@aws-cdk/aws-iam": "1.130.0", + "@aws-cdk/aws-kms": "1.130.0", + "@aws-cdk/cloud-assembly-schema": "1.130.0", + "@aws-cdk/core": "1.130.0", + "constructs": "^3.3.69" + } + } } }, "@aws-cdk/aws-efs": { @@ -682,15 +724,184 @@ } }, "@aws-cdk/aws-ssm": { - "version": "1.130.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.130.0.tgz", - "integrity": "sha512-93q58dcxt0r9FB5B8ceg7JhqfSx3XCG7uNSTDq6MzIIq4hcRDvahneS4TiMOzYdVuLAXCYE13GZXxQSSQ0TAgQ==", - "requires": { - "@aws-cdk/aws-iam": "1.130.0", - "@aws-cdk/aws-kms": "1.130.0", - "@aws-cdk/cloud-assembly-schema": "1.130.0", - "@aws-cdk/core": "1.130.0", + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-ssm/-/aws-ssm-1.134.0.tgz", + "integrity": "sha512-cKubHdfexeiuXLPTk77FMTFgehpuYyD72e6rd42Oc79KNGAoytWWGzDc+tieIpz8caBOt5U4QJ3KNF/ARF1wGA==", + "requires": { + "@aws-cdk/aws-iam": "1.134.0", + "@aws-cdk/aws-kms": "1.134.0", + "@aws-cdk/cloud-assembly-schema": "1.134.0", + "@aws-cdk/core": "1.134.0", "constructs": "^3.3.69" + }, + "dependencies": { + "@aws-cdk/aws-iam": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-iam/-/aws-iam-1.134.0.tgz", + "integrity": "sha512-EZy+oyIiAl2WvAfKpn2zhSZ9Wtcu06RUTIbkrourietnQoQhqhiwpp/H84VosgUgwpHsx7BNmZ8EJJXJXs7XfA==", + "requires": { + "@aws-cdk/core": "1.134.0", + "@aws-cdk/region-info": "1.134.0", + "constructs": "^3.3.69" + } + }, + "@aws-cdk/aws-kms": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-kms/-/aws-kms-1.134.0.tgz", + "integrity": "sha512-nuXWE/lHnR9PzZdjCN9cbhT5IAHS593JVrS889v+O/9l3jLCgdSaElQ6EAjmr7WHne2npRbTo/Qw7ebT31BIRQ==", + "requires": { + "@aws-cdk/aws-iam": "1.134.0", + "@aws-cdk/cloud-assembly-schema": "1.134.0", + "@aws-cdk/core": "1.134.0", + "@aws-cdk/cx-api": "1.134.0", + "constructs": "^3.3.69" + } + }, + "@aws-cdk/cloud-assembly-schema": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-1.134.0.tgz", + "integrity": "sha512-P7HTOJ/e7MM+RfMQKpzP4cie0hbf/st/l6AmbYx0t/aayhnL1MXrnWPZd1t89TEYiekJkwsXX6x6N7S180uQvw==", + "requires": { + "jsonschema": "^1.4.0", + "semver": "^7.3.5" + }, + "dependencies": { + "jsonschema": { + "version": "1.4.0", + "bundled": true + }, + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "bundled": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true + } + } + }, + "@aws-cdk/core": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/core/-/core-1.134.0.tgz", + "integrity": "sha512-rdQYFTrGBemgy1C23r2s18ONXgnsp4dXyZMTTcy7e6QkF3JBTI4za2GUWY4XQaKnchGV9UhylPNFqh59hXzEUA==", + "requires": { + "@aws-cdk/cloud-assembly-schema": "1.134.0", + "@aws-cdk/cx-api": "1.134.0", + "@aws-cdk/region-info": "1.134.0", + "@balena/dockerignore": "^1.0.2", + "constructs": "^3.3.69", + "fs-extra": "^9.1.0", + "ignore": "^5.1.9", + "minimatch": "^3.0.4" + }, + "dependencies": { + "@balena/dockerignore": { + "version": "1.0.2", + "bundled": true + }, + "at-least-node": { + "version": "1.0.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "fs-extra": { + "version": "9.1.0", + "bundled": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "bundled": true + }, + "ignore": { + "version": "5.1.9", + "bundled": true + }, + "jsonfile": { + "version": "6.1.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "universalify": { + "version": "2.0.0", + "bundled": true + } + } + }, + "@aws-cdk/cx-api": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cx-api/-/cx-api-1.134.0.tgz", + "integrity": "sha512-D822T7LI+61Sktv4bdR6g2rKXdGNgYZXkkHrSSpATp6ov++0E0ttsQVblkLrzcOtKtB5nbaGrF7cf/0fxdoKeg==", + "requires": { + "@aws-cdk/cloud-assembly-schema": "1.134.0", + "semver": "^7.3.5" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "bundled": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true + } + } + }, + "@aws-cdk/region-info": { + "version": "1.134.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/region-info/-/region-info-1.134.0.tgz", + "integrity": "sha512-1BzvZsdXWvn1ub3yGcpALafBHqISbirgNz9fsFuqvZuBUYJBiIi97awSyFMKZKzLvGNkrAk9rsNjHo9gWnJOWw==" + } } }, "@aws-cdk/aws-stepfunctions": { @@ -2189,6 +2400,717 @@ "glob": "^7.2.0", "mime": "^2.5.2", "yargs": "^16.2.0" + }, + "dependencies": { + "@aws-cdk/cloud-assembly-schema": { + "version": "1.130.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-1.130.0.tgz", + "integrity": "sha512-FewdApVM5N4BwNn23VeiIA6EgD6CZP1tV0wZAsxU+xXl4CwsfhyeAsmTVeHvf4+g+N7j5BBp+q2d1bkSesdZWw==", + "dev": true, + "requires": { + "jsonschema": "^1.4.0", + "semver": "^7.3.5" + } + }, + "@aws-cdk/cx-api": { + "version": "1.130.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cx-api/-/cx-api-1.130.0.tgz", + "integrity": "sha512-YU5zJ1D4X4CJbEvUOvOqIQYAht7ockCp0en/hKH+2TZPoJLTRQZvCJvlcVxoYM1O9RTlAzqa5bhRnMhbdo9ceQ==", + "dev": true, + "requires": { + "@aws-cdk/cloud-assembly-schema": "1.130.0", + "semver": "^7.3.5" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "async": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8", + "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==", + "dev": true + }, + "aws-sdk": { + "version": "2.1006.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1006.0.tgz#fc2f7e267d19a6297f732e19449461bb944682af", + "integrity": "sha512-lwXAy706+1HVQqMnHaahdeBZZbdu6TWrtTY0ydeG0qanwldTFNMLczwnETTZWYsqNAU+wjl1VzmFdMO4gePLNQ==", + "dev": true, + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + }, + "dependencies": { + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + } + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "crc-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208", + "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==", + "dev": true, + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "dev": true, + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "dev": true + }, + "jsonschema": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2", + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } + } + }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz#f0e10bb7bf7bfa7e0add8baffdc54c3f7dbee6c4", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + } + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "dev": true, + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } + } } }, "chalk": { @@ -2824,8 +3746,7 @@ "mime": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" }, "minimatch": { "version": "3.0.4", diff --git a/package.json b/package.json index ef3ceae..8c28a5b 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@aws-cdk/aws-events-targets": "^1.130.0", "@aws-cdk/aws-iam": "^1.130.0", "@aws-cdk/aws-lambda": "^1.130.0", + "@aws-cdk/aws-ssm": "^1.134.0", "@aws-cdk/core": "1.130.0" } } diff --git a/packer/linux-ami.pkr.hcl b/packer/linux-ami.pkr.hcl index fd896cf..ebc4e63 100644 --- a/packer/linux-ami.pkr.hcl +++ b/packer/linux-ami.pkr.hcl @@ -69,4 +69,12 @@ build { "scripts/terminate-instance.sh" ] } + + provisioner "shell" { + inline = [ + "sudo mkdir -p /opt/semaphore/", + "sudo mv /tmp/install-agent.sh /opt/semaphore/install-agent.sh", + "sudo mv /tmp/terminate-instance.sh /opt/semaphore/terminate-instance.sh" + ] + } } \ No newline at end of file diff --git a/packer/scripts/install-agent.sh b/packer/scripts/install-agent.sh index b820e1b..ae3434e 100755 --- a/packer/scripts/install-agent.sh +++ b/packer/scripts/install-agent.sh @@ -1,3 +1,5 @@ +#!/bin/bash + [[ -z "${AGENT_VERSION}" ]] && echo "AGENT_VERSION is not set" && exit 1 [[ -z "${SEMAPHORE_ORGANIZATION}" ]] && echo "SEMAPHORE_ORGANIZATION is not set" && exit 1 [[ -z "${SEMAPHORE_REGISTRATION_TOKEN}" ]] && echo "SEMAPHORE_REGISTRATION_TOKEN is not set" && exit 1 @@ -11,11 +13,9 @@ sudo rm /opt/semaphore/agent/agent.tar.gz sudo chown $USER:$USER -R /opt/semaphore/agent/ cd /opt/semaphore/agent/ -# Installs agent, but keeps it stopped for now -# It will be started when the instance goes into rotation +# Install and start agent mkdir hooks -mv /tmp/terminate-instance.sh /opt/semaphore/agent/hooks/shutdown +mv /opt/semaphore/terminate-instance.sh /opt/semaphore/agent/hooks/shutdown export SEMAPHORE_AGENT_SHUTDOWN_HOOK=/opt/semaphore/agent/hooks/shutdown export SEMAPHORE_AGENT_DISCONNECT_AFTER_JOB=true -export SEMAPHORE_AGENT_DO_NOT_START=true sudo -E ./install.sh diff --git a/packer/scripts/install-utils.sh b/packer/scripts/install-utils.sh index cb5b12a..f59f506 100755 --- a/packer/scripts/install-utils.sh +++ b/packer/scripts/install-utils.sh @@ -1,2 +1,9 @@ +#!/bin/bash + sudo apt-get update -sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release git make unzip policykit-1 jq awscli \ No newline at end of file + +sudo apt-get install -y apt-transport-https +sudo apt-get install -y make +sudo apt-get install -y unzip +sudo apt-get install -y jq +sudo apt-get install -y awscli \ No newline at end of file From 5ba442328c2d5ae1e46bdd0669789f0dc050646d Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Thu, 2 Dec 2021 23:04:49 -0300 Subject: [PATCH 3/6] SSM parameter should be fetched from ec2 instance --- README.md | 2 +- lambda/app.js | 40 ++++---------------------------- lib/aws-semaphore-agent-stack.js | 16 ++++++------- packer/scripts/install-agent.sh | 12 ++++++---- 4 files changed, 21 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 1d34ce4..245cf5b 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Other optional arguments are available: ```bash cdk deploy \ - --parameters imageId=ami-09676b8af848f9e92 \ + --parameters imageId=ami-05a4364b75e912f89 \ --parameters semaphoreOrganization=semaphore \ --parameters semaphoreToken=YOUR_VERY_SENSITIVE_TOKEN ``` diff --git a/lambda/app.js b/lambda/app.js index 105d3c1..19817b9 100644 --- a/lambda/app.js +++ b/lambda/app.js @@ -58,30 +58,7 @@ function getInstanceStatus(instanceId) { }); } -function getAgentParameters() { - var ssm = new aws.SSM(); - - return new Promise(function(resolve, reject) { - var params = { - Name: "semaphore-agent-params" - }; - - ssm.getParameter(params, function(err, data) { - if (err) { - reject(err); - } else { - agentParams = JSON.parse(data.Parameter.Value); - - // TODO: this shouldn't be logged - console.log("Agent params: ", agentParams); - - resolve(agentParams); - } - }); - }); -} - -function startAgentOnInstance(instanceId, agentParameters) { +function startAgentOnInstance(instanceId) { var ssm = new aws.SSM(); return new Promise(function(resolve, reject) { @@ -89,13 +66,7 @@ function startAgentOnInstance(instanceId, agentParameters) { InstanceIds: [instanceId], DocumentName: 'AWS-RunShellScript', Parameters: { - commands: [ - `export AGENT_VERSION=${agentParameters.agentVersion}`, - `export SEMAPHORE_ORGANIZATION=${agentParameters.organization}`, - `export SEMAPHORE_REGISTRATION_TOKEN=${agentParameters.token}`, - `export SEMAPHORE_AGENT_INSTALLATION_USER=${agentParameters.vmUser}`, - '/opt/semaphore/install-agent.sh' - ], + commands: ['/opt/semaphore/install-agent.sh'], executionTimeout: ['10'] }, }; @@ -170,11 +141,8 @@ exports.handler = async (event, context, callback) => { } // Instance is online, let's execute the command to start the agent - console.log("Instance '" + instanceId + "' is '" + instanceStatus + "'. Grabbing agent parameters..."); - var agentParameters = await getAgentParameters(); - - console.log("Sending command to start agent...") - var commandId = await startAgentOnInstance(instanceId, agentParameters); + console.log("Instance '" + instanceId + "' is '" + instanceStatus + "'. Sending command to start agent..."); + var commandId = await startAgentOnInstance(instanceId); var commandStatus = 'Pending'; // Poll the command status diff --git a/lib/aws-semaphore-agent-stack.js b/lib/aws-semaphore-agent-stack.js index b6bf92a..71a212e 100644 --- a/lib/aws-semaphore-agent-stack.js +++ b/lib/aws-semaphore-agent-stack.js @@ -93,6 +93,14 @@ class AwsSemaphoreAgentStack extends cdk.Stack { resources: [`arn:aws:autoscaling:*:${account}:autoScalingGroup:*:autoScalingGroupName/${autoscalingGroupName}`] })); + ec2Role.addToPolicy(new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ["ssm:GetParameter"], + resources: [ + `arn:aws:ssm:*:*:parameter/${ssmParameterName}` + ] + })) + const instanceProfileDeps = new cdk.ConcreteDependable(); instanceProfileDeps.add(ec2Role); @@ -133,14 +141,6 @@ class AwsSemaphoreAgentStack extends cdk.Stack { ] })); - lambdaRole.addToPolicy(new iam.PolicyStatement({ - effect: iam.Effect.ALLOW, - actions: ["ssm:GetParameter"], - resources: [ - `arn:aws:ssm:*:*:parameter/${ssmParameterName}` - ] - })) - lambdaRole.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: [ diff --git a/packer/scripts/install-agent.sh b/packer/scripts/install-agent.sh index ae3434e..3b72db1 100755 --- a/packer/scripts/install-agent.sh +++ b/packer/scripts/install-agent.sh @@ -1,9 +1,13 @@ #!/bin/bash -[[ -z "${AGENT_VERSION}" ]] && echo "AGENT_VERSION is not set" && exit 1 -[[ -z "${SEMAPHORE_ORGANIZATION}" ]] && echo "SEMAPHORE_ORGANIZATION is not set" && exit 1 -[[ -z "${SEMAPHORE_REGISTRATION_TOKEN}" ]] && echo "SEMAPHORE_REGISTRATION_TOKEN is not set" && exit 1 -[[ -z "${SEMAPHORE_AGENT_INSTALLATION_USER}" ]] && echo "SEMAPHORE_AGENT_INSTALLATION_USER is not set" && exit 1 +token=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 60" --fail --silent --show-error --location "http://169.254.169.254/latest/api/token") +region=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/placement/region") +agent_params=$(aws ssm get-parameter --region "$region" --name "semaphore-agent-params" --query Parameter.Value --output text) + +AGENT_VERSION=$(echo $agent_params | jq '.agentVersion' | tr -d \") +SEMAPHORE_ORGANIZATION=$(echo $agent_params | jq '.organization' | tr -d \") +SEMAPHORE_REGISTRATION_TOKEN=$(echo $agent_params | jq '.token' | tr -d \") +SEMAPHORE_AGENT_INSTALLATION_USER=$(echo $agent_params | jq '.vmUser' | tr -d \") # Download agent sudo mkdir -p /opt/semaphore/agent From 7d8f6064e2e3fe93444f3bd158ee4056d28b6c79 Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Thu, 2 Dec 2021 23:11:48 -0300 Subject: [PATCH 4/6] Update comment + newlines --- lib/aws-semaphore-agent-stack.js | 14 ++++++++------ packer/linux-ami.pkr.hcl | 2 +- packer/scripts/install-utils.sh | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/aws-semaphore-agent-stack.js b/lib/aws-semaphore-agent-stack.js index 71a212e..0b23647 100644 --- a/lib/aws-semaphore-agent-stack.js +++ b/lib/aws-semaphore-agent-stack.js @@ -15,12 +15,15 @@ class AwsSemaphoreAgentStack extends cdk.Stack { super(scope, id, props); /** - * The lambda function needs information about the agent in order to install it. - * The only way for it to grab that information is through an SSM Parameter. + * When processing the lifecycle hook event for the instance going into rotation, + * the lambda executes a script in the instance to install and start the agent. + * That script needs the agent parameters (organization, token, ...). We expose + * those parameters through an SSM parameter. * - * Note that this creates a tight coupling between this script and the lambda script, - * as both of them need to use the proper parameter name and structure. So, if you - * change anything about the SSM Parameter, the lambda will probably need to change as well. + * Note that this creates a tight coupling between this cdk application and the script + * being executed to install and start the agent, as both of them need to use the proper + * parameter name and structure. So, if you change anything about the SSM Parameter here, + * the install script used by the lambda will have to change as well. */ let ssmParameter = this.createSSMParameter(); @@ -39,7 +42,6 @@ class AwsSemaphoreAgentStack extends cdk.Stack { this.createWarmPool(autoScalingGroup); } - // TODO: this should be encrypted createSSMParameter() { const semaphoreOrganizationParameter = new cdk.CfnParameter(this, "semaphoreOrganization", { type: "String", diff --git a/packer/linux-ami.pkr.hcl b/packer/linux-ami.pkr.hcl index ebc4e63..f6983ab 100644 --- a/packer/linux-ami.pkr.hcl +++ b/packer/linux-ami.pkr.hcl @@ -77,4 +77,4 @@ build { "sudo mv /tmp/terminate-instance.sh /opt/semaphore/terminate-instance.sh" ] } -} \ No newline at end of file +} diff --git a/packer/scripts/install-utils.sh b/packer/scripts/install-utils.sh index f59f506..f230a94 100755 --- a/packer/scripts/install-utils.sh +++ b/packer/scripts/install-utils.sh @@ -6,4 +6,4 @@ sudo apt-get install -y apt-transport-https sudo apt-get install -y make sudo apt-get install -y unzip sudo apt-get install -y jq -sudo apt-get install -y awscli \ No newline at end of file +sudo apt-get install -y awscli From a525aab7cf0217341b2ffa9dd73008b86197a798 Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Fri, 3 Dec 2021 12:40:28 -0300 Subject: [PATCH 5/6] Fix install-agent.sh script --- README.md | 2 +- packer/linux-ami.pkr.hcl | 5 +++-- packer/scripts/install-agent.sh | 17 +++++++++-------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 245cf5b..774082d 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Other optional arguments are available: ```bash cdk deploy \ - --parameters imageId=ami-05a4364b75e912f89 \ + --parameters imageId=ami-044a4f8505e681532 \ --parameters semaphoreOrganization=semaphore \ --parameters semaphoreToken=YOUR_VERY_SENSITIVE_TOKEN ``` diff --git a/packer/linux-ami.pkr.hcl b/packer/linux-ami.pkr.hcl index f6983ab..a206542 100644 --- a/packer/linux-ami.pkr.hcl +++ b/packer/linux-ami.pkr.hcl @@ -63,10 +63,11 @@ build { provisioner "file" { destination = "/tmp/" sources = [ - # Required for the asg launch configuration + # Required by the lambda function that processes the asg lifecycle hooks "scripts/install-agent.sh", + # Required by the agent - "scripts/terminate-instance.sh" + "scripts/terminate-instance.sh", ] } diff --git a/packer/scripts/install-agent.sh b/packer/scripts/install-agent.sh index 3b72db1..fddada1 100755 --- a/packer/scripts/install-agent.sh +++ b/packer/scripts/install-agent.sh @@ -3,23 +3,24 @@ token=$(curl -X PUT -H "X-aws-ec2-metadata-token-ttl-seconds: 60" --fail --silent --show-error --location "http://169.254.169.254/latest/api/token") region=$(curl -H "X-aws-ec2-metadata-token: $token" --fail --silent --show-error --location "http://169.254.169.254/latest/meta-data/placement/region") agent_params=$(aws ssm get-parameter --region "$region" --name "semaphore-agent-params" --query Parameter.Value --output text) - -AGENT_VERSION=$(echo $agent_params | jq '.agentVersion' | tr -d \") -SEMAPHORE_ORGANIZATION=$(echo $agent_params | jq '.organization' | tr -d \") -SEMAPHORE_REGISTRATION_TOKEN=$(echo $agent_params | jq '.token' | tr -d \") -SEMAPHORE_AGENT_INSTALLATION_USER=$(echo $agent_params | jq '.vmUser' | tr -d \") +agent_version=$(echo $agent_params | jq '.agentVersion' | tr -d \") # Download agent sudo mkdir -p /opt/semaphore/agent -sudo curl -L https://github.com/semaphoreci/agent/releases/download/${AGENT_VERSION}/agent_Linux_x86_64.tar.gz -o /opt/semaphore/agent/agent.tar.gz +sudo curl -L https://github.com/semaphoreci/agent/releases/download/${agent_version}/agent_Linux_x86_64.tar.gz -o /opt/semaphore/agent/agent.tar.gz sudo tar -xf /opt/semaphore/agent/agent.tar.gz -C /opt/semaphore/agent sudo rm /opt/semaphore/agent/agent.tar.gz + +# Create hooks directory +sudo mkdir -p /opt/semaphore/agent/hooks +sudo mv /opt/semaphore/terminate-instance.sh /opt/semaphore/agent/hooks/shutdown sudo chown $USER:$USER -R /opt/semaphore/agent/ cd /opt/semaphore/agent/ # Install and start agent -mkdir hooks -mv /opt/semaphore/terminate-instance.sh /opt/semaphore/agent/hooks/shutdown +export SEMAPHORE_ORGANIZATION=$(echo $agent_params | jq '.organization' | tr -d \") +export SEMAPHORE_REGISTRATION_TOKEN=$(echo $agent_params | jq '.token' | tr -d \") +export SEMAPHORE_AGENT_INSTALLATION_USER=$(echo $agent_params | jq '.vmUser' | tr -d \") export SEMAPHORE_AGENT_SHUTDOWN_HOOK=/opt/semaphore/agent/hooks/shutdown export SEMAPHORE_AGENT_DISCONNECT_AFTER_JOB=true sudo -E ./install.sh From b6e67113ec29464995bcd7566a0f0f133220e0ef Mon Sep 17 00:00:00 2001 From: Lucas Pinheiro Date: Fri, 3 Dec 2021 17:56:06 -0300 Subject: [PATCH 6/6] Use latest agent version --- README.md | 2 +- lambda/app.js | 2 +- lib/aws-semaphore-agent-stack.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 774082d..8a19fd0 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Other optional arguments are available: ```bash cdk deploy \ - --parameters imageId=ami-044a4f8505e681532 \ + --parameters imageId=ami-099f98f5c31d8ba1e \ --parameters semaphoreOrganization=semaphore \ --parameters semaphoreToken=YOUR_VERY_SENSITIVE_TOKEN ``` diff --git a/lambda/app.js b/lambda/app.js index 19817b9..1882aaa 100644 --- a/lambda/app.js +++ b/lambda/app.js @@ -67,7 +67,7 @@ function startAgentOnInstance(instanceId) { DocumentName: 'AWS-RunShellScript', Parameters: { commands: ['/opt/semaphore/install-agent.sh'], - executionTimeout: ['10'] + executionTimeout: ['20'] }, }; diff --git a/lib/aws-semaphore-agent-stack.js b/lib/aws-semaphore-agent-stack.js index 0b23647..10554cf 100644 --- a/lib/aws-semaphore-agent-stack.js +++ b/lib/aws-semaphore-agent-stack.js @@ -57,7 +57,7 @@ class AwsSemaphoreAgentStack extends cdk.Stack { const semaphoreAgentVersionParameter = new cdk.CfnParameter(this, "semaphoreAgentVersion", { type: "String", description: "The agent version to use.", - default: "v2.0.16" + default: "v2.0.17" }); const machineUserParameter = new cdk.CfnParameter(this, "machineUser", {