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 distros 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 useupdate-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 via 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 via two methods
-
an HTTP query
-
a file on the instance's ephemeral store (
/dev/sda2
). This file is namedopenssh_id.pub
and its format is compatible with the OpenSSHauthorized_keys
file.
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 | |
---|---|
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 |
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:
-
Always delete the shell history before bundling. If you attempt more than one bundle upload in the same image the shell history will contain your secret access key.
-
Bundling a running instance requires your private key and X509 certificate. Put these and other credentials in a location that will not be bundled (such as the ephemeral store).
-
Exclude the ssh authorized keys when bundling the image. The Amazon public images store the public key an instance was launched with in that instance's ssh authorized keys file.
It is not possible for this list to be exhaustive. Build your shared AMIs carefully and consider where you might be exposing sensitive data.