Skip to content

EC2 SSH Access (SSM)

Overview

This pattern grants SSH access to EC2 Linux instances without opening inbound SSH or running a bastion. At checkout the broker generates an ephemeral SSH key pair locally and uses an AWS Systems Manager (SSM) document (addSSHKey) to push the public key onto the target instance; it returns the private key. At checkin a second document (removeSSHKey) removes the key. Because SSM drives the change, the broker only needs AWS API access — not network reachability to the instance.

Before You Begin

  • The Access Broker is deployed and connected
  • AWS CLI on the broker host, with permission to call ssm send-command and ssm list-command-invocations
  • The target EC2 instances have the SSM Agent running and an instance profile that allows SSM
  • The addSSHKey and removeSSHKey SSM documents registered in the account/region

How It Works

checkout → ssh-keygen (ephemeral) → ssm send-command addSSHKey
         → poll until Success → return private key

checkin  → ssm send-command removeSSHKey

Environment Variables

VariableNotes
BRITIVE_ACTIONInjected — checkout or checkin
BRITIVE_USER_EMAILInjected — username derived from local-part (non-alphanumerics stripped)
INSTANCETarget EC2 instance ID
BRITIVE_SUDO1 to grant sudo, 0 otherwise (default 0)

Script

Full script: EC2/Linux/addLocalUser/ec2-ssh-user.sh

if [ "$ACTION" = "checkout" ]; then
  KEY_PATH="$(mktemp -d)/britive-id_rsa"
  ssh-keygen -q -N "" -t rsa -f "$KEY_PATH"

  COMMAND_ID=$(aws ssm send-command \
    --document-name "addSSHKey" \
    --targets "Key=InstanceIds,Values=$INSTANCE" \
    --parameters "username=[\"$USER\"],group=[\"$GROUP\"],sshPublicKey=[\"$(cat $KEY_PATH.pub)\"],sudo=[\"$SUDO\"],userEmail=[\"$USER_EMAIL\"]" \
    --region "us-west-2" --query "Command.CommandId" --output text)

  # poll list-command-invocations until Status = Success, then:
  cat "$KEY_PATH"          # return the private key
else
  aws ssm send-command --document-name "removeSSHKey" \
    --targets "Key=InstanceIds,Values=$INSTANCE" \
    --parameters "username=[\"$USER\"]" --region "us-west-2"
fi

The example hardcodes us-west-2. Parameterize the region (e.g. an AWS_REGION variable) for multi-region fleets.

Configure in Britive

Create the permission

Resource Manager → Resource Type Permissions → New Permission. Language = Shell. Paste the script into both Checkout and Checkin — it branches on BRITIVE_ACTION. Declare INSTANCE and BRITIVE_SUDO; BRITIVE_ACTION and BRITIVE_USER_EMAIL are system-defined. Attach a response template that surfaces the private key.

Create a profile and policy

Create a profile (e.g. 2h), associate the instances (by resource label), add the permission, and add a policy assigning members by tag.

Verify

Check out and connect

Check out the profile, save the returned private key, then:

ssh -i britive-id_rsa <username>@<instance-private-ip>

Check in and confirm removal

After checkin, the key is removed — a new SSH attempt with it is rejected.

Troubleshoot

SymptomCauseFix
send-command returns emptyInstance not SSM-managedConfirm the SSM Agent is running and the instance profile allows SSM
Command stuck pendingSSM document missingRegister the addSSHKey / removeSSHKey documents in the region
AccessDeniedBroker IAM can’t call SSMGrant ssm:SendCommand and ssm:ListCommandInvocations
Wrong regionHardcoded us-west-2Parameterize the region for the instance’s region

Next Steps

Last updated on