Wiki

Clone wiki

sftpgateway-public / SFTP Gateway 2.0 Send SSM commands to multiple instances

When running SFTP Gateway in a multi instance configuration, there are times when you need to run a bash command on each instance. Fortunately, commonly used configuration files are stored on EFS, so they have a single point of change. But to apply the configuration changes, you need to restart a service on each EC2 instance.

It’s not practical to SSH into each EC2 instance to run the same commands. Instead, you can use SSM to send a single command to all instances within an autoscaling group.

You need to send the SSM command from your own desktop or bastion host, and you need an AWS profile with proper IAM permissions. For security reasons, the SFTP Gateway instance IAM roles do not have the permissions to send SSM commands.

The Bash Commands

Here are the bash commands you will need to run. You can run these from your Mac Terminal, or from an EC2 instance with proper IAM permissions. Be sure to edit these appropriately.

#1
export AWS_PROFILE=default

#2
CLOUDFORMATION_STACK_NAME="my-sftpgw-multi-instance-cf-stack"
REGION="us-east-1"

#3
COMMAND="sudo service sshd restart"
COMMENT="this restarts the sshd service"

#4
ASG_NAME=$(aws cloudformation describe-stack-resources --stack-name $CLOUDFORMATION_STACK_NAME --query 'StackResources[?ResourceType==`AWS::AutoScaling::AutoScalingGroup`][PhysicalResourceId][0]' --output text)

#5
COMMAND_ID=$(aws ssm send-command --document-name "AWS-RunShellScript" --targets Key=tag:aws:autoscaling:groupName,Values=$ASG_NAME --comment "$COMMENT" --parameters commands="$COMMAND" --region $REGION --query Command.CommandId  --output text)

#6
aws ssm list-command-invocations --command-id $COMMAND_ID --query CommandInvocations

Explanation of the Bash Commands

These are what the commands mean:

(1) If you're running these bash commands from your Mac, include this line if you configured an AWS profile. For example, I have multiple AWS profiles configured, so I would modify this line to:

export AWS_PROFILE=sftpgateway-dev

(2) You define some variables based on your CloudFormation stack name and region. Since these are likely to be the only lines you modify, I have moved them to the top.

(3) You define more variables. These variables define the actual command you want to run on your instances. In this case, you are restarting the sshd service. You could re-purpose these commands to do something else if you wanted to, such as restarting Nginx.

(4) This is a long command, but all it's doing is defining another variable. In this case, it's setting the autoscaling group name, since you're blasting this command to all instance in this autoscaling group. This line figures out the autoscaling group name based on the CloudFormation stack. Or, you could just hard-code this to your autoscaling group if you wanted to.

(5) This is the actual command. Here, you send the SSM command to all instances in your autoscaling group. This SSM command contains the bash code to restart sshd. This ssm command also returns a Command ID, which you hang onto for later.

(6) The ssm command might take some time to run, and might even fail on one or two of your instances. This line checks the status of your ssm command. It uses the Command ID you saved earlier, and then it lists the status for each instance. The output looks something like this (you want to see "Success" for each instance):

[
    {
        "Comment": "this restarts the sshd service", 
        "Status": "Success", 
        "InstanceId": "i-0588e705a76619387", 
        "DocumentName": "AWS-RunShellScript"
    }, 
    {
        "Comment": "this restarts the sshd service", 
        "Status": "Success", 
        "InstanceId": "i-09366d26cdbee2af4", 
        "DocumentName": "AWS-RunShellScript"
    }
]

Updated