SSH Keys...
Background: I am currently building a private IaaS cloud using the open source cloudstack software.
Did you know that cloudstack comes with the ability to offer cloud clients the ability to authenticate into their instance's using ssh keys? I didn't.
So, I'm reading the cloudstack api documentation and ... Before you say anything, yes, I was actually reading an api doc. So, I see an api method entitled createSSHKeyPair and I wondered if it did what I think it did. It did.
Unfortunately, I couldn't find any documentation on this, so I thought I'd help the community out and share what I learned.
I should also mention that Cloudstack also supports another form of user authentication. That is random root/admin password generation. A user is given a random password for use on their instance. I've tested this an it seems to work fine. This works on linux, unix, and windows. This is not covered in this article however.
A quick primer on SSH keys and why this would be useful:
If you know all about ssh keypairs, then please feel free to skip to the next section.
If you don't know, an ssh key pair can be used to login into a system with a 'ssh key file' versus using a known password. Please feel free to reference other material to learn about ssh keys.
Using ssh keys and infrastructure as a service (iaas) clouds is useful for a couple reasons. First, every cloud user would be using their own ssh key. This, in itself, offers some additional security to your cloud solution. This ensures that one cloud user can not access another cloud user's instances (unless they shared their ssh key files). Secondly, when people choose to use clouds, they often are doing it because they know the value of programmatically being able to access and modifuy thier infrastructure (instances). And, one way to do that is to use ssh keys. This would allow to easily manage many instances with a simple, secure method.
By the way, Amazon's EC2 uses SSH KeyPairs pretty heavily.
Now, what work is needed to make this happen on a cloudstack cloud?
First, some restrictions, notes and disclaimers. This should work on most unix/linux variants. I don't think this works with Windows atm (since I don't think is has a built in SSH server =]). I've personally tested it on CentOs linux. Also, SSH Key management is not available via the cloudstack GUI (currently). That means that the only way to create instances that use ssh keys is via the API (for now). My work was done on cloudstack 3.0.0. However, I think it also works on older versions as well.
The only thing a cloudstack administrator needs to do is:
- Create a instance template that supports SSH Keys
The process for the cloud user would be:
- Create an SSH Key in cloudstack
- Create an instance using the SSHKey enabled temaplate and specifying their personal ssh key
- Login to the instance using their ssh key (not their password)
Create a instance template that supports SSH Keys
The folks @ Cloudstack published a script that enables SSH Key support on a linux instance. What does this script do? Well, the script will run on instance startup. It will communicate to the instance's virtual router and ask cloudstack for the SSH key private key. The script will then download the ssh key and install it on the instance for the cloud user to authenticate against. What we, as the cloud admin, will need to do is install this script on an instance and save the instance as a template. This way, cloud users will be able to use this feature.
Here is what I did on a CentOs instance in order to get this to work:
- Create a new instance using the CentOs template provided by cloudstack.
- Download the cloudstack script from here to the centos instance: http://sourceforge.net/projects/cloudstack/files/SSH%20Key%20Gen%20Script/
- Copy the file to /etc/init.d and have it run on startup.
- Stop the instance (via the cloudstack GUI)
- Create a template (via the cloudstack GUI)
Here are the commands I ran on the CentOs host before I created a template.
# download the script
wget http://downloads.sourceforge.net/project/cloudstack/SSH%20Key%20Gen%20Script/cloud-set-guest-sshkey.in?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fcloudstack%2Ffiles%2FSSH%2520Key%2520Gen%2520Script%2F&ts=1331225219&use_mirror=iweb
# copy the script to the proper place
cp cloud-set-guest-sshkey.in /etc/init.d/
# set permissions on the script
chmod +x /etc/init.d/cloud-set-guest-sshkey.in
# tell the OS to start the script on start up
chkconfig --add cloud-set-guest-sshkey.in
The Cloud User work flow
1. Create an ssh key:
We will need to make a call to the createSSHKeyPair api method. I personally use the cloudstack python api library that jason hancock published. But, for a better example of how to do this via the api, I'll show example curl commands to the cloudstack api.
Note: I am making the below call from my cloudstack server itself. If you are making the api call from a different server, your URL/PORT will be different and you will need to use api keys.
Here, I am creating a ssh keypair called "keypair-test1" for the admin account in the root domain. (Please adjust these values to meet yoru needs)
My curl command:
curl --globoff "http://localhost:8096/?command=createSSHKeyPair&name=keypair-test1&account=admin&domainid=5163440e-c44b-42b5-9109-ad75cae8e8a2"
The output will look something like this:
<?xml version="1.0" encoding="ISO-8859-1"?><createsshkeypairresponse cloud-stack-version="3.0.0.20120228045507"><keypair><name>keypair-test1</name><fingerprint>f6:77:39:d5:5e:77:02:22:6a:d8:7f:ce:ab:cd:b3:56</fingerprint><privatekey>-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCSydmnQ67jP6lNoXdX3noZjQdrMAWNQZ7y5SrEu4wDxplvhYci
dXYBeZVwakDVsU2MLGl/K+wefwefwefwefwefJyKJaogMKn7BperPD6n1wIDAQAB
AoGAdXaJ7uyZKeRDoy6wA0UmF0kSPbMZCR+UTIHNkS/E0/4U+6lhMokmFSHtu
mfDZ1kGGDYhMsdytjDBztljawfawfeawefawfawfawQQDCjEsoRdgkduTy
QpbSGDIa11Jsc+XNDx2fgRinDsxXI/zJYXTKRhSl/LIPHBw/brW8vzxhOlSOrwm7
VvemkkgpAkEAwSeEw394LYZiEVv395ar9MLRVTVLwpo54jC4tsOxQCBlloocK
lYaocpk0yBqqOUSBawfIiDCuLXSdvBo1Xz5ICTM19vgvEp/+kMuECQBzm
nVo8b2Gvyagqt/KEQo8wzH2THghZ1qQ1QRhIeJG2aissEacF6bGB2oZ7Igim5L14
4KR7OeEToyCLC2k+02UCQQCrniSnWKtDVoVqeK/zbB32JhW3Wullv5p5zUEcd
KfEEuzcCUIxtJYTahJ1pvlFkQ8anpuxjSEDp8x/18bq3
-----END RSA PRIVATE KEY-----
</privatekey></keypair></createsshkeypairresponse>
What you will want to do, is copy the key data into a file so that file looks like this:
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCSydmnQ67jP6lNoXdX3noZjQdrMAWNQZ7y5SrEu4wDxplvhYci
dXYBeZVwakDVsU2MLGl/K+wefwefwefwefwefJyKJaogMKn7BperPD6n1wIDAQAB
AoGAdXaJ7uyZKeRDoy6wA0UmF0kSPbMZCR+UTIHNkS/E0/4U+6lhMokmFSHtu
mfDZ1kGGDYhMsdytjDBztljawfawfeawefawfawfawQQDCjEsoRdgkduTy
QpbSGDIa11Jsc+XNDx2fgRinDsxXI/zJYXTKRhSl/LIPHBw/brW8vzxhOlSOrwm7
VvemkkgpAkEAwSeEw394LYZiEVv395ar9MLRVTVLwpo54jC4tsOxQCBlloocK
lYaocpk0yBqqOUSBawfIiDCuLXSdvBo1Xz5ICTM19vgvEp/+kMuECQBzm
nVo8b2Gvyagqt/KEQo8wzH2THghZ1qQ1QRhIeJG2aissEacF6bGB2oZ7Igim5L14
4KR7OeEToyCLC2k+02UCQQCrniSnWKtDVoVqeK/zbB32JhW3Wullv5p5zUEcd
KfEEuzcCUIxtJYTahJ1pvlFkQ8anpuxjSEDp8x/18bq3
-----END RSA PRIVATE KEY-----
Save the file. I called my file keypair-test1
2. Create an instance
Now, we need to create a new instance in cloudstack. We have to use the template we created above. We also will have to use the ssh key name from above. Note: you can not create the instance via the gui at this time and associate the instance with the newly created ssh keypair. A sample curl command to create a new instance would be:
Note: Please substitute the template, service offering and security group IDs (you may not need to specify a security group if you are not using that feature) that are in your cloudstack environment:
curl --globoff http://localhost:8096/?command=deployVirtualMachine\&zoneId=1\&serviceOfferingId=18727021-7556-4110-9322-d625b52e0813\&templateId=e899c18a-ce13-4bbf-98a9-625c5026e0b5\&securitygroupids=ff03f02f-9e3b-48f8-834d-91b822da40c5\&account=admin\&domainid=1\&keypair=keypair-test1
3. Login using the ssh key
Assuming everything above went well, you should be able to login into you new instance without using a password, but instead using your keypair:
From a linux cli, I ran this:
ssh -i ~/.ssh/keypair-test1 192.168.1.100
The -i parameter tells the ssh client to use a ssh key found at ~/.ssh/keypair-test1.
Notice it just works and doesn't ask for a password:
[root@cloudstack1]# ssh -i ~/.ssh/keypair-test1 192.168.1.100
Last login: Mon Mar 26 19:58:30 2012 from 1.2.3.4
[root@faa9ccca-30fe-4e4b-9645-d878514f0966 ~]# hostname
faa9ccca-30fe-4e4b-9645-d878514f0966
[root@faa9ccca-30fe-4e4b-9645-d878514f0966 ~]# cat /etc/redhat-release
CentOS release 5.6 (Final)
[root@faa9ccca-30fe-4e4b-9645-d878514f0966 ~]# uname -a
Linux faa9ccca-30fe-4e4b-9645-d878514f0966 2.6.18-238.el5xen #1 SMP Thu Jan 13 16:41:45 EST 2011 x86_64 x86_64 x86_64 GNU/Linux
Good luck and happy hunting.
Chris