Skip to content

enable SSM

Enable SSM

Allow EC2 can be sshed in with session manager.

Install SSM agent

yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm

Add SSM Role

The following script will add the role to ALL regions it can access under specific AWS account:

#!/bin/bash

# 1. Define your dedicated SSM Role and Instance Profile names for instances without a role
SSM_ROLE_NAME="EC2-SSM-Execution-Role"
SSM_PROFILE_NAME="EC2-SSM-Execution-Role"
SSM_POLICY_ARN="arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"

echo "Checking / creating IAM Role and Instance Profile ($SSM_ROLE_NAME)..."

if ! aws iam get-role --role-name "$SSM_ROLE_NAME" >/dev/null 2>&1; then
  echo "-> Role '$SSM_ROLE_NAME' not found. Creating it..."
  aws iam create-role \
    --role-name "$SSM_ROLE_NAME" \
    --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ec2.amazonaws.com"},"Action":"sts:AssumeRole"}]}' \
    --description "Allows EC2 instances to communicate with AWS Systems Manager" >/dev/null 2>&1
fi

aws iam attach-role-policy \
  --role-name "$SSM_ROLE_NAME" \
  --policy-arn "$SSM_POLICY_ARN" >/dev/null 2>&1

if ! aws iam get-instance-profile --instance-profile-name "$SSM_PROFILE_NAME" >/dev/null 2>&1; then
  echo "-> Instance profile '$SSM_PROFILE_NAME' not found. Creating it..."
  aws iam create-instance-profile --instance-profile-name "$SSM_PROFILE_NAME" >/dev/null 2>&1
  sleep 5
fi

aws iam add-role-to-instance-profile \
  --instance-profile-name "$SSM_PROFILE_NAME" \
  --role-name "$SSM_ROLE_NAME" >/dev/null 2>&1

echo "IAM Role and Instance Profile are ready."
echo "Fetching all active regions..."
REGIONS=$(aws ec2 describe-regions --query "Regions[].RegionName" --output text)

for REGION in $REGIONS; do
  echo "=========================================================="
  echo " PROCESSING REGION: $REGION"
  echo "=========================================================="

  instance_data=$(aws ec2 describe-instances \
    --region "$REGION" \
    --filters "Name=instance-state-name,Values=running,stopped" \
    --query "Reservations[].Instances[].[InstanceId, State.Name, PlatformDetails || 'Linux', IamInstanceProfile.Arn || 'NONE']" \
    --output text)

  if [ -z "$instance_data" ]; then
    echo "No matching instances found in $REGION."
    continue
  fi

  echo "$instance_data" | while IFS=$'\t' read -r instance_id state platform profile_arn; do
    [ -z "$instance_id" ] && continue
    echo "------------------------------------------------"
    echo "Instance: $instance_id | State: $state | OS: $platform | Region: $REGION"

    if [ "$profile_arn" == "NONE" ] || [ -z "$profile_arn" ]; then
      echo "-> No IAM role found. Attaching dedicated SSM Instance Profile..."
      err_output=$(aws ec2 associate-iam-instance-profile \
        --region "$REGION" \
        --instance-id "$instance_id" \
        --iam-instance-profile Name="$SSM_PROFILE_NAME" 2>&1)
      if [ $? -eq 0 ]; then
        echo "Successfully attached SSM role to $instance_id"
      else
        echo "Failed to attach SSM role to $instance_id"
        echo "   Error: $err_output"
      fi
    else
      echo "-> Instance already has a profile: $profile_arn"
      existing_profile_name=$(echo "$profile_arn" | awk -F'/' '{print $NF}')
      existing_role_name=$(aws iam get-instance-profile \
        --instance-profile-name "$existing_profile_name" \
        --query "InstanceProfile.Roles[0].RoleName" \
        --output text 2>&1)
      if [ $? -eq 0 ] && [ "$existing_role_name" != "None" ] && [ -n "$existing_role_name" ]; then
        echo "-> Appending SSM permissions to IAM role: $existing_role_name"
        attach_err=$(aws iam attach-role-policy \
          --role-name "$existing_role_name" \
          --policy-arn "$SSM_POLICY_ARN" 2>&1)
        if [ $? -eq 0 ]; then
          echo "Successfully added SSM policy to existing role $existing_role_name on $instance_id"
        else
          echo "Failed to attach policy to role $existing_role_name"
          echo "   Error: $attach_err"
        fi
      else
        echo "Could not resolve role name for profile $existing_profile_name"
        echo "   Error: $existing_role_name"
      fi
    fi
  done
done

echo "=========================================================="
echo "Multi-region bulk process complete!"
Or you change this line:
REGIONS=$(aws ec2 describe-regions --query "Regions[].RegionName" --output text)
to specify the resion/s.

One liner to export AWS profiles

export AWS_ACCESS_KEY_ID="AKIAxxxxxxxxxxxxxxxx" AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" AWS_DEFAULT_REGION="ca-central-1"