2

A python script launches an instance. The script then needs to log in via SSH into it. But to pass the SSH host verification it has to get the host public keys that were generated on the instance during the launch.

These keys are usually printed in the console logs of the instance:

-----BEGIN SSH HOST KEY KEYS-----
...
-----END SSH HOST KEY KEYS-----

How to get this information via the boto3 API? One way I can think of is to write that info from the user cloud-init script of the instance into an s3 storage and then make python script read it. Is there a better way? Custom tags that can be added to an ec2 instance from within the instance?

2
  • Why are you wanting a program to use SSH? There's probably a better way to achieve your goal. What are you actually wanting to accomplish (as opposed to how)? Commented Jun 23, 2021 at 22:20
  • Using dockerpy. It's either HTTPS with client certificate or SSH. The HTTPS certificates are too annoying, it leaves SSH. I'm going with SSH and putting pub keys into the tags of the instance. Commented Jun 24, 2021 at 8:29

2 Answers 2

2

The OP is asking about the instance's SSH host public key, not the SSH client public key (which is what is tied to an EC2 "key pair" and what you specify when you launch the EC2 instance). Each EC2 instance generates a new host key the first time it boots. Then, when you connect from a client, SSH complains that the host key has changed, and you have to reset the entry in your client's ~/.ssh/known_hosts.

Unfortunately there is no secure and programmatic way to get a new EC2 instance's public host key. What everyone does is blindly connect to the EC2 instance the first time, ignoring warnings about unknown host keys, trusting that there is no man-in-the-middle, and cache the host key in ~/.aws/known_hosts for future use. This must be done every time an EC2 instance is reprovisioned.

One simple secure solution would be to add a script to the EC2 instance that runs on first boot and "publishes" the generated SSH host public key to a well-known and trusted location (e.g., An S3 object that is readable by anyone but can only be written by the EC2 instance's IAM role). Then, you can simply wait for the EC2 instance to boot for the first time, then download the SSH public host key from S3 and add it to your client's ~/.ssh/known_hosts file. After that, SSH will connect successfully with no host key warnings. Of course, every time you redeploy the EC2 instance, the host key will change and you will have to refresh the entry in ~/.ssh/known_hosts. But at least it is secure.

Another secure solution that would have the advantage of a stable host key that survives instance redeployments would be to generate a host key pair before the EC2 instance is launched, and pass it to the EC2 instance for use on first boot (either directly through user-data or indirectly with AWS secrets manager, S3, etc.). Then, you would add a script that runs on first boot that sets/replaces the SSH host key in the EC2 instance.

Then you can directly add the known and trusted host key to your client's ~/.ssh/known_hosts, and the key will remain stable across EC2 instance redeployments.

Managing all this, and protecting the secrecy of the sensitive host private key, is inconvenient and brings its own set of problems. Most people just accept that they have to take a leap of faith and refresh the host key over an insecure channel each time the EC2 instance is redeployed.

Sign up to request clarification or add additional context in comments.

1 Comment

"What everyone does is blindly connect to the EC2 instance the first time" - instead of connecting blindly, you can verify the fingerprint shown by the SSH client with the one printed in the instance's console log. This is what OP is probably doing, but wants to automate. While some "leaps of faith" cannot be avoided, this gap in the chain of trust can. It is a shame that there seems to be no easy solution at the moment.
1

Rather than generating new keys every time an instance is launched, you can simply specify an existing key when launching the EC2 instance. This way, it can always use the same keypair and your process is greatly simplified.

By the way, there should be very little need for a program to use an SSH connection into another computer. If you are wanting to run a script on another computer, you can do it via User Data (for initial launch), or use the AWS Systems Manager Run Command - AWS Systems Manager to run scripts on existing Amazon EC2 instances.

2 Comments

How to specify an existing key when launching the EC2 instance? Afaic, the AWS Console "Key pair" option refers to the client key, not to the server (host) key, which this question is about.
Here is one proposed solution using user_data property for cloudinit, which seems to be doable via AWS Console. But this solution is said to be unsecure and against best practice. (I keep bringing up AWS Console, while OP asked about boto3, and the linked answer is about Terraform - I don't think this makes any difference here)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.