encryption

Decrypting AWS Windows passwords

With Linux instances, the public key of the key pair you specify when creating the instance is placed in the .ssh/authorized_keys directory. When you SSH in it encrypts the initial communication details with your public key so that only someone with the corresponding private key can decrypt the details and complete the connection.

Windows instances do not work in the same way. Instead when the instance is created a random password is created. This password is then encrypted with the public key.  You can request this encrypted password but you then need the private key to decrypt it. This can be done through the AWS console but if you are going to use boto to automate AWS then you really want a Python solution.

I have seen a couple of solutions using the PyCrypto module but I wanted a pure Python solution. Luckily there is an rsa module (pip install rsa) which is written in pure Python. With that and the boto module you can decrypt the password with the following code.

import rsa, boto, base64
instance_id = 'i-0123456789abcdef'
key_path = r'C:\path\to\private.pem'

ec2 = boto.connect_ec2() #access_key,secret_key
passwd = base64.b64decode(ec2.get_password_data(instance_id))
if (passwd):
    with open (key_path,'r') as privkeyfile:
        priv = rsa.PrivateKey.load_pkcs1(privkeyfile.read())
    key = rsa.decrypt(passwd,priv)
else:
    key = 'Wait at least 4 minutes after creation before the admin password is available'

print(key)

You just need to specify the instance_id and the private key file location (2nd and 3rd lines). The connect_ec2 method will use the credentials in the .aws file in your home directory if it exists. Alternatively you can specify the access key and secret key as parameters to the method. Assuming you haven’t jumped the gun this should print out the admin password.

SSH tunneling for security

Running your administration scripts and monitoring from a remote server can bring a lot of benefits. I’ve covered simple web servers and threading in previous posts. However this does create one big issue, securing it. Setting up HTTPS and storing user log ins adds a lot of complexity.

However if you are running this on a *nix server, or if you are prepared to install an SSH server on your Windows box, you can get encryption and authentication almost for free with SSH tunneling. This allows traffic to be sent down the encrypted SSH connection to other ports on the server – or even other servers. Authentication with your username and password/certificate comes at the start when you establish the SSH connection.

For example, you could make a simple web server in Python binded to port 8082 on the localhost. This would not be accessible to any other computer on the network, only someone directly connected to the server. Rather than run a text only browser from the SSH terminal, you could tunnel all traffic going to port 8081 (say) on your machine to port 8082 on the remote machine. Then while the SSH connection was open, point your browser at http://localhost:8082/ to view the web page on your local machine as if it was a regular server.

So how to configure this? I’ll assume you are using PuTTY. Enter the hostname or ip address of the server as usual. Then expand the Connection and SSH nodes to show the Tunnels page and make the tunnelfollowing changes

  • Remove the default tick against local ports accept connections from other hosts
  • In source port, put your local port you want to use. This can be anything you like – in our example above it was port 8081
  • In destination port server and port you want to access from the remote server – in our example above this would be 127.0.0.1:8082

And that is it. The settings should now look something like the image on the right.

Save this configuration for future use in the normal way and you are good to go.