Is it possible to get/set SSH host key programatically?

January 15, 2017 1.8k views
Security API FreeBSD

It seems FreeBSD images does not support user-data, so I cannot set ssh host keys there myself. Is there either another way to set the host key or alternatively read the one generated at first boot programmatically?

The only way to do this I am aware of is to open the console for the droplet via the web interface and read the key there which pretty much defeats the purpose of using the api to programmatically provision droplets in the first place. Not verifying host keys is a terrible idea and a complete showstopper.

Alternatively, can console output somehow be scraped?

Thanks
Troels

5 Answers

Not sure if I got what you are looking for, but I use Terraform and it is able to provision a new FreeBSD droplet with a chosen SSH host key.

If you need the "raw" API endpoint have a look at https://developers.digitalocean.com/documentation/v2/#ssh-keys

Regards,

Nicholas

@tkjacobsen

I'd recommend looking at doctl - GitHub Repository - Usage Guide & Overview.

There's a specific section that deals with SSH Keys here.

Using doctl isn't limited to your local environment. You could deploy it to a web server and call on its functionality from there as well.

You can also pull the data down using JSON if you prefer and then store the output to a file, which could then be called by your application to do whatever needs to be done.

DigitalOcean's web based control panel provides a convenient, point-and-click interface for managing Droplets. There are many times, however, when a command-line tool may be a preferable alternative. doctl, the official DigitalOcean command-line client, leverages the DigitalOcean API to provide access to most account and Droplet features.
  • Thanks for the reply. However, doctl doesn't solve the issue as I still blindly have to type "yes" to accept the SSH host key unless I manually go into the web console and confirm it:

    % doctl compute ssh XXXXXX
    The authenticity of host '[IP] ([IP])' can't be established.
    ECDSA key fingerprint is SHA256YYY.
    No matching host key fingerprint found in DNS.
    Are you sure you want to continue connecting (yes/no)?
    

    As such, I cannot automatically create and start using hosts without having to manually confirm the key.

    • @tkjacobsen

      One way around having to manually confirm each key would be to create a config file in your ~/.ssh directory (i.e. ~/.ssh/config). Within that file, add:

      Host *
          StrictHostKeyChecking no
      

      This won't work if, for instance, you create a Droplet and then re-image it. You would need to clear your known_hosts file first, but then afterwards, it'll work again, or;

      Host *
          StrictHostKeyChecking no
          UserKnownHostsFile=/dev/null
      

      ... and it won't check known_hosts.

      It's a slightly less secure method as you're blindly accepting the keys, but it is one way. I did test this both remotely (on a DigitalOcean Droplet connecting to another Droplet) as well as locally on my MacBook Pro and it worked on both.

      • Hi again.

        Thanks for your suggestion. This will definitely work for development and test purposes. Though, I'm not sure I'm comfortable with this on a production system.

        Would be nice to see a way to at least fetch the console output via the API so I could grep for the key.

        Best regards
        Troels

        • @tkjacobsen

          No problem and I agree. The above is suitable for local deployments, though I'd be on the fence about using it on a production server unless it was fully locked down and access was restricted to either a certain IP or IP range.

          That being said, what exactly are you trying to do? From your last comment, you're wanting to successfully login and grep the key, though beyond that, what are you trying to do afterwards?

          If you can provide more details, I'll see if there's anything I can come up.

          • I'm trying to establish an offsite backup setup where an always-on Raspberry Pi I have at home once a day will do the following:

            1. Spin up a new FreeBSD droplet the API
            2. Do do some initial setup via SSH (change username, reset passwords passwords, install packages, setup firewall, etc.)
            3. Mount a geli-encrypted ZFS volume on the droplet via SSH (I will pipe key-file via SSH so it is never stored on the droplet)
            4. Run a backup-script that backs up all my online services to the ZFS volume (google drive, google mail, evernote, etc.)
            5. Take a snapshot of the ZFS volumen via SSH
            6. Unmount the ZFS volumen via SSH
            7. Shutdown and destroy the droplet via the API

            This way, I will only pay for the block storage and about 30 minutes of droplet use per day. With some light scripting, I've managed to make the setup pretty much work (what nice and simple API!) except for the ssh key. (I have it working in AWS where I inject a ssh host key via user-data but that doesn't work for FreeBSD on DO, unfortunately).

          • tkjacobsen is asking for a way to validate the SSH host key of a new droplet, without having to perform a manual step of logging into the console with a password. I am trying to do the same thing and am a little shocked that this isn't possible with the DigitalOcean API.

            I just tried using Packer to create a snapshot (getting the key fingerprints in the process) and it took a while to find out the DigitalOcean just blows away the key when the snapshot is used to create a new droplet. While this does ensure keys are unique, I haven't figured out how to deterministically add my own keys yet.

            I have searched for a way to get this information using "doctl" and don't find any way to do this. I do see that there are log entries in my account under "Security History" that show events like "ssh_key.remove" and "ssh_key.add". This doesn't say what was created, just that keys were deleted and new ones created. That is less than helpful towards validating authenticity of the keys. (And as suggested above, turning off host key validation is not the right answer: facilitating validating the keys is the right answer.)

            Rather than just sticking the event into the security event history, could you please expose the key fingerprints that were created? That way "doctl compute action" could retrieve the fingerprints, or perhaps better yet stick the key fingerprints into the output of "doctl compute droplet get droplet_id --output json", allowing us a way to programmatically retrieve and add them to known_hosts files and/or validate them visually. Thanks.

Not sure If I got what you are asking, but I use Terraform and it is able to provision a new FreeBSD droplet with a pre-configured SSH key.

The API it uses is: https://developers.digitalocean.com/documentation/v2/#ssh-keys

Regards,

Nicholas

Have another answer? Share your knowledge.