Making custom AMI and distributing it safely

There are many different ways of managing your infrastructure on aws right from bringing up stalk ec2 instances and customizing them using a configuration management system like puppet which take a reasonable amount of time to come online to customizing your AMI fully in a ready-to-go state and saving that as AMI for future use. Also depending on the kind of customization required you can also have the entire application stack pre-configured on a EBS snapshot and attach that your ec2 instance and with a little bit of tweaks you could have a fully functional box up and running. Whichever approach you take based on your needs you would still need to build your AMIs. As mentioned in my previous post, there is nothing special in this post other than notes for myself(and anyone else) on how to create an AMI from an per-exsistant image and sharing it safely.

Note: This post assumes you are working on an ubuntu instance but the same rules applies for any other unix variant as long as you have the right tools installed. The method of installing the tools might vary based on the distribution available

You need to have the following available before you start:

  • An EC2 public key (public part of the keypair) to access your instance
  • A X.509 cert and private key (see previous post for more details)
  • Your aws access id/key and secret key
  • Packages ec2-api-tools and ec2-ami-tools installed in the customized ami

In case you don’t have the ec2 installed, you need to enable the repos by uncommenting the following lines in /etc/apt/sources.list

#deb http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick multiverse
#deb http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse
#deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick-updates multiverse

On the ec2 instance, run the following command to ensure that its fully updated and have the required packages installed. This assumes that the required customization have been done at this stage.

ubuntu@ip-20-56-39-198:~$ sudo apt-get update && sudo apt-get install ec2-ami-tools ec2-api-tools

SCP you x.509 and private key to the ec2 instance at this stage and move it to /mnt/certs you would need to create the directory as its not already present.

rp@localhost$ scp -i ec2-keypair-key.pem aws-x509-cert.pem private-key.pem ubuntu@ec2-20-56-39-198.compute-1.amazonaws.com:~/

Just so that you know /mnt is a mounted block device which means that anything you put it in isn’t part of the AMI (unless of-course you explicitly ask for it). This is the reason why we would store the bundled image in the /mnt directory instead. You can also verify this by running $ sudo fdisk -l to see the list of all block devices and their partitions.

Before you start bundling your images there are a couple of things that would be worth looking into to ensure that your AMI is safe and you are not inadvertently giving anyone access to the ec2 instances that would be launched using the AMI.

  • Disable password based logins for root (or for accounts in the admin group if using ubuntu). Modify /etc/ssh/sshd_config.
    #PermitRootLogin yes
    PermitRootLogin without-password
    
  • Randomize the root password at boot time to ensure the password can’t be guessed (additional security following the previous point. A script in rc.local can do the trick
  • Remove ssh host key pairs to ensure new ones get generated for each instance of the AMI. Especially useful when using with puppet. Delete all ssh_host_* files in /etc/ssh/.
  • Disable sshd dns checks. This doesn’t make it any more safe, just ensures that even if the DNS isn’t working the ssh server can still let you connect. It would otherwise try and do a reverse lookup before establishing connection. Disabling it also speeds up the process of connecting.
    Modify /etc/ssh/sshd_config
    #UseDNS yes
    UseDNS no
    
  • Remove all entries in the ~/.ssh/authorized_keys and for other user accounts that were configured to work in that manner as well. This would ensure that the instances from the AMI don’t give access to users who had the orig. keypair when creating the customized AMI
  • Clear the following files .bash_history, .viminfo and any other files that store information about your current session of usage.
  • Remove passwords for all user accounts that are allowed login
     ssh passwd -l
    
  • Modify sshd to allow only public key authentication, modify /etc/ssh/sshd_config
    PubKeyAuthentication yes
    PasswordAuthentication no
    
  • Delete all shell history, system lot etc that might contain sensitive information

To bundle the AMI, run the following command

$sudo ec2-bundle-vol -k /mnt/certs/private-key.pem \
 -c /mnt/certs/aws-x509-cert.pem \
 -u  \
 -d /mnt/instance-store/ \
 -r i386

You need to create a s3 bucket to store this for future use. Lets say that bucket is called my-ami
Now upload the bundle to the s3 bucket

$ ec2-upload-bundle -b my-ami \
  -m instance-store/image.manifest.xml \
  -a your-account-access-key \
  -s your-account-secret-key
  --region us-west-1

The --region is optional and is sometimes required if your bucket is in a different region.

and then the last part is to register the AMI, this process will give you an AMI id which you can then use to launch instances that are a copy of the AMI.

$ ec2-register my-ami/my-prefix.manifest.xml \
  --name my-ami \
  --description 'Describe the type of server here'  \
  -K  /mnt/certs/private-key.pem\
  -C /mnt/certs/aws-x509-cert.pem \
  -a i386

This command would return back an AMI id.

Tags: ,

About rp

Architect for large, highly scalable LAMP applications and Technical Manager with special focus on metrics based continuous improvement of teams and products. Rajat has close to a decade of experience of a very wide range of skills related to infrastructure, middleware, app servers all the way to front-end technologies and software development methodologies including agile, iterative waterfall, waterfall as well as ah-hoc startup using the right approach in the right context to reduce time to market.