# Packages
# README
amazon-ec2-ssh-utils
š§ Under construction.
Pending evaluation by AWS.
Utilities for configuring SSH in EC2 instances for EC2 Key Pairs and EC2 Instance Connect.
Connecting to instances with AWS Systems Manager Session Manager is handled by the AWS Systems Manager Agent instead.
Utilities
amazon-ec2-openssh-authorized-keys
This is an OpenSSH AuthorizedKeysCommand
program which gets public keys for EC2 Key Pairs and EC2 Instance Connect from IMDS.
The simplest way to make the instance's OpenSSH daemon use this utility is to add the following lines to the instance's /etc/ssh/sshd_config
file:
AuthorizedKeysCommand {path to installation folder, e.g. /usr/bin}/amazon-ec2-openssh-authorized-keys -f %f -u %u
# This can be any user, but the OpenSSH documentation recommends a dedicated user that has no other role on the host than running authorized keys commands.
AuthorizedKeysCommandUser amazon-ec2-ssh
EC2 Key Pairs
EC2 Key Pair public keys can be used to log in as any user.
Logging in as
root
requires the server's OpenSSH daemon to have itsPermitRootLogin
option be something besidesno
(default for Amazon-managed AMIs).
The default user for Amazon-managed AMIs (e.g. ec2-user
) has passwordless sudo
access. Since the default user can switch to any user (e.g. sudo su {user}
), the authorization scope is equivalent to saving the public key in {default user home}/.ssh/authorized_keys
.
Unlike the AWS-customized cloud-init (Amazon Linux 2, Amazon Linux 2023) which saves public keys to disk, using this utility helps prevent accidentally baking public keys into AMIs (security vulnerability).
This may be vulnerable to man-in-the-middle attacks since EC2 Key Pairs don't have any signing mechanism like EC2 Instance Connect.
https://blog.champtar.fr/Metadata_MITM_root_EKS_GKE
Saving the EC2 Key Pair public key to disk on instance launch with cloud-init is vulnerable to this as well but only during instance launch.
EC2 Instance Connect
EC2 Instance Connect public keys are scoped to the user specified in the SendSSHPublicKey
API call.
Layout
Key:
š¤ = Generated
.
ā # Build outputs.
āāā build/ š¤
ā āāā ...
ā
ā # Go commands.
āāā cmd/
ā āāā ...
ā
ā # Go internal packages.
āāā internal/
ā ā # Go interfaces.
ā āāā interfaces/
ā ā ā # Go interface mocks.
ā ā āāā *_mock.go š¤
ā ā ā
ā ā āāā ...
ā ā
ā ā # Go implementations.
ā āāā implementations/
ā āāā ...
ā
ā # Reproducible shell configuration.
āāā flake.nix
āāā flake.lock š¤
ā
ā # Go path configuration.
āāā go.mod
āāā go.sum š¤
ā
ā # Mockery configuration.
āāā .mockery.yaml
ā
ā # Build recipes.
āāā justfile
Tools
- GNU Core Utilities
- GNU Find Utilities
- For deleting files.
- Git
- Just
- For build recipes.
- Go
- Mockery
- For creating mocks.
- golangci-lint
- Go linter.
A reproducible shell can be created with Nix (described by the flake.nix
+ flake.lock
files).
Nix can be installed with the Determinate Nix Installer (guide).
Afterwards, you can change into the project directory and create the reproducible shell with nix develop
.
You can also install the direnv shell extension to automatically load and unload the reproducible shell when you enter and leave the project directory.
Unlike nix develop
which drops you in a nested Bash shell, direnv extracts the environment variables from the nested Bash shell into your current shell (e.g. Bash, Zsh, Fish).
Developing
Common build recipes are provided as Just recipes. To list them, run:
just help
To build the project, run:
just release
To use a utility, run:
go run cmd/{utility}/main.go
Notes
Updating Flake Locks
The flake.lock
file locks the inputs (e.g. the Nixpkgs revision) used to evaluate flake.nix
files. To update the inputs (e.g. to get newer packages in a later Nixpkgs revision), you'll need to update your flake.lock
file.
# Update flake.lock.
nix flake update
To-Do
amazon-ec2-openssh-authorized-keys
- Review certificate + OCSP staple verification. Something's probably incorrect.
- Are the Amazon root CAs expected to be on systems already?
- Review certificate + OCSP staple verification. Something's probably incorrect.
- Documentation
- Have AWS add EC2 Instance Connect paths to IMDS documentation (and maybe aws/amazon-ec2-metadata-mock).
- Currently guessing these based on aws/aws-ec2-instance-connect-config.
- Have AWS add EC2 Instance Connect paths to IMDS documentation (and maybe aws/amazon-ec2-metadata-mock).
- Packaging
- Nix package
.deb
(Debian, Ubuntu).rpm
(Amazon Linux, RHEL, Fedora)- Homebrew formula (publish to the AWS Homebrew tap)
- Windows Package Manager
- Integration testing
- Use EC2 Image Builder.
- Make the image tests do a self-SSH.
- Use AWS CDK for infrastructure.
- Create an EC2 Key Pair (CloudFormation creates an SSM parameter).
- Create an EC2 launch template that uses the key pair.
- Create an EC2 Image Builder image resource (CloudFormation will trigger an image pipeline execution).
- Pending support for additional operating systems (macOS, Windows) for full coverage.
- Use EC2 Image Builder.
- CI/CD
- See commiterate/nix-images for a poor man's version of Amazon-internal Pipelines (video) with GitHub Actions.
- Dependabot (automatically update Nix, Go, and JavaScript dependencies).