Building Shared AMIs

This section describes best practices for building shared AMIs. Building safe, secure, useable AMIs for public consumption is a fairly straightforward process, if you stick to a few simple guidelines.

You're welcome to choose to ignore any, or all, of these guidelines. They're not requirements for publishing an AMI. However, we believe that following these guidelines will make for a far smoother user experience and help ensure your users' instances are secure.

These guidelines are generally written with Fedora distros in mind, but the principles hold for any AMI. You may need to tweak the examples we've provided to get them to work on other distributions.

Many of the steps below involve automating something during the boot sequence. We've made a few notes for some of the more common distributions below. For other distros check your local documentation or search the AWS forums in case someone else has done it already.

  • On Red Hat and Fedora systems you can add these steps to your /etc/rc.d/rc.local script.

  • On Gentoo systems you can add them to /etc/conf.d/local.local.

  • On Ubuntu systems you can add them to /etc/rc.local.

  • On Debian, you may need to create a start up script in /etc/init.d and use update-rc.d <scriptname> defaults 99 (where <scriptname> is the name of the script you created) and add the steps to this script.

We recommend that during the boot process your AMIs should fetch and upgrade the EC2 AMI creation tools. This ensures that new AMIs based on your shared AMIs contain the latest AMI creation tools.

On Fedora, adding the following to rclocal will update the AMI tools at boot.

# Update the EC2 AMI creation tools
echo " + Updating ec2-ami-tools"
wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm && \
rpm -Uvh ec2-ami-tools.noarch.rpm && \
echo " + Updated ec2-ami-tools"

You may wish to use this pattern to auto update other software on your image. It's up to you to decide which, if any, of the software components installed on your AMI should be updated at boot time. Two things to consider when making this decision are how much WAN traffic will the update generate (bearing in mind your users will be charged for it) and how much risk is there that the update will break other software on the AMI.

A fixed root password for a public AMI is a security risk. It won't be long before it becomes well known. It's not sufficient to rely on users changing the password after logging in for the first time, since this leaves a small window of "opportunity" for someone looking for a chance to do something bad (or cheap thrills).

The solution is to disable password based logins for the root user. In fact, we recommend you go one step further and randomize the root password at boot, just in case. Defense-in-depth is always a good strategy.

To disable password based logins for root, edit the /etc/ssh/sshd_config file and find and change the following line

#PermitRootLogin yes

to

PermitRootLogin without-password

The location of this configuration file may differ for your distribution, or if you're not running OpenSSH. Consult the relevant documentation if this is the case.

Randomizing the root password is also pretty simple. Add the following to your boot process.

if [ -f "/root/firstrun" ] ; then
  dd if=/dev/urandom count=50|md5sum|passwd --stdin root
  rm -f /root/firstrun
else
  echo "* Firstrun *" && touch /root/firstrun
fi

Once again, you may need to consult the relevant documentation if you're using a distro other than Fedora.

Now that we've done a pretty thorough job of ensuring that no one can log into instances of our AMI using a password, we need to make sure they can login using some other mechanism.

EC2 allows users to specify a public-private keypair name when launching an instance. When a valid keypair name is provided to the RunInstances API call (or through the command line API tools) the following happens behind the scenes:

The public key (the only portion of the keypair EC2 retains on the server after a call to CreateKeyPair) is made available to the instance through two methods

  1. an HTTP query

  2. a file on the instance's ephemeral store (/dev/sda2). This file is named openssh_id.pub and its format is compatible with the OpenSSH authorized_keys file.

[Note]Note

The HTTP request is the preferred method of retrieving the public key. The second method is deprecated and will be phased out in future versions of the service.

This means at boot, all your AMI need do is retrieve the key value and append it to /root/.ssh/authorized_keys (or the equivalent for any other user account on the AMI) and users will be able to launch instances of your AMI with a keypair and log in without requiring a root password.

if [ ! -d /root/.ssh ] ; then
        mkdir -p /root/.ssh
        chmod 700 /root/.ssh
fi
# Fetch public key using HTTP
curl http://169.254.169.254/2007-03-01//meta-data/public-keys/0/openssh-key > /tmp/my-key
if [ $? -eq 0 ] ; then
        cat /tmp/my-key >> /root/.ssh/authorized_keys
        chmod 600 /root/.ssh/authorized_keys
        rm /tmp/my-key
fi
# or fetch public key using the file in the ephemeral store:
if [ -e /mnt/openssh_id.pub ] ; then
        cat /mnt/openssh_id.pub >> /root/.ssh/authorized_keys
        chmod 600 /root/.ssh/authorized_keys
fi

This can be applied to any user account. There is no reason to restrict it to root.

[Note]Note

There's an implication of this step that you should be aware of: rebundling an instance based on this image will include the key it was launched with in the new image, unless you explicitly clear out (or delete) the authorized_keys file. You can also exclude this file from rebundling.

This is an optional step. It slightly weakens your sshd security (although not significantly), but ensures that should DNS resolution fail, ssh logins will still work. If you leave this setting at its default, DNS resolution failures will prevent logins altogether.

To disable password based logins for root, edit the /etc/ssh/sshd_config file and find and change the following line

#UseDNS yes

to this

UseDNS no

The location of this configuration file may differ for your distribution, or if you're not running OpenSSH. Consult the relevant documentation if this is the case.

Currently there is no easy way of knowing who provides a shared AMI. All you are presented with is a numeric user id. We suggest that you post a description of your ami, and the ami id, in the Amazon EC2 developer forum. This will provide users interested in trying new shared AMIs with a central location to find information about those AMIs.

We are working on making it easier to share and find new AMIs.

We have looked at making shared AMIs safe, secure and useable for the users who launch them, but if you publish a shared AMI you should also take steps to protect yourself against the users of you AMI This section looks at steps you can take to do this.

We recommend against storing sensitive data or software on any AMI that you share. Users who launch a shared AMI potentially have access to rebundle it and register it as their own. Follow these guidelines to help you to avoid some easily overlooked security risks:

It is not possible for this list to be exhaustive. Build your shared AMIs carefully and consider where you might be exposing sensitive data.