Three layers with different jobs
A key pair proves identity for SSH, a Security Group permits traffic to the ENI, and an IAM role authorizes AWS API calls. They do not replace one another.
flowchart LR ADM["You<br/>private key .pem"] --> SG["Security Group<br/>22 from 203.0.113.10/32"] SG --> SSH["sshd on instance<br/>public key check"] SSH --> OS["Shell as ec2-user"] OS --> ROLE["IAM role<br/>temporary credentials"] ROLE --> S3["AWS APIs<br/>S3, SSM"] %% step ADM: You hold the private key; AWS kept only the public key. %% step SG: The Security Group must allow port 22 from your address, or the connection times out. %% step SSH: sshd compares your key with ~/.ssh/authorized_keys placed at launch. %% step OS: The username depends on the AMI: ec2-user or ubuntu. %% step ROLE: Inside the instance, AWS calls use the role's rotating credentials, not stored keys. %% step S3: The role's policy decides which API calls succeed.
Key pairs
AWS places the public key on the instance; the .pem private key stays with you and cannot be downloaded again from AWS. On Linux/macOS, set its mode to 400 or SSH refuses it. The username depends on the AMI: Amazon Linux uses ec2-user, Ubuntu uses ubuntu, Debian uses admin.
Lost the key? You cannot recover it, but you can: connect with Session Manager or EC2 Instance Connect and add a new public key; or stop the instance, attach its root volume to another instance and edit authorized_keys.
Security Groups
A Security Group is a stateful firewall attached to the instance's ENI: allow rules only, return traffic allowed automatically. Allow SSH only from the necessary administration CIDR, ideally /32; avoid 0.0.0.0/0 without a justified need. You can reference another SG as the source — for example "allow 3306 from sg-web" — so rules follow instances instead of IPs.
Connecting without open ports
| Method | Needs port 22? | Needs a key? |
|---|---|---|
| SSH with key pair | Yes | Yes |
| EC2 Instance Connect | Yes (from AWS's IP range or an endpoint) | No, pushes a one-time key |
| Systems Manager Session Manager | No | No, uses the instance role and SSM agent |
Session Manager is the most secure default: no inbound rules, access controlled by IAM, every session logged. The instance needs the SSM agent (pre-installed on Amazon Linux) and a role with AmazonSSMManagedInstanceCore.
Use a role instead of access keys
Attach an IAM role through an instance profile. The SDK or CLI on the instance receives rotating temporary credentials. Never store long-lived access keys in code, an AMI, or shell history, and keep the role policy least-privileged.
| Command | Purpose |
|---|---|
chmod 400 training-key.pem |
Restrict the private key file |
ssh -i training-key.pem ec2-user@203.0.113.10 |
SSH to a documentation address |
aws ssm start-session --target i-0a1b2c3d |
Shell without SSH or port 22 |
aws ec2 associate-iam-instance-profile ... |
Attach an instance profile |
Traps: opening port 22 to 0.0.0.0/0; using root or the wrong username; copying access keys onto the instance instead of attaching a role.