Jan 9, 2015 - Ansible - First Impressions


I took some time to try out a few provisioning tools - Ansible, Chef, and Puppet in particular - and I like Ansible a lot, I like it most.

The main reason I’d go with Ansible is its simplicity.
Install is dead simple, just

yum install --enablerepo epel ansible

and you are done. Without any extra configuration, you can go ahead and test reachability to the node you want to provision by a ping.
Say the IP of the node you want to provision is

ansible -m ping 

The only requirement Ansible needs to provision with the node is:

  • Be able to SSH with the target user
  • The target user has the correct permission to perform commands in the node

If you need to specify a private key,

ansible --private-key /path/to/private-key -m ping 

It’s the type fo simplicity that I love. I don’t want to have to think about “What do I have to install in the node?” “Is the agent installed in the node running correctly/with the correct version?” . Especially when I am having some sort of trouble setting up a server, that is the last thing I want to think about.

“Can I perform these commands in the server? Can I SSH to that server?” is all I want to ask myself.

Playbooks are also simple; You just write YAMLs in a certain structure.

# webservers.yml
- hosts: webservers
  sudo: yes
    - name: Install apache
      yum: name=httpd state=installed

    - name: Ensure apache is started
      service: name=httpd state=started

Define your hosts group like this, inside /etc/ansible/hosts

# /etc/ansible/hosts

And just run

ansible-playbook webservers.yml

Just like that, and you got yourself an Ansible setup that’ll install Apache and ensure that it’s running. As you can see, you don’t need any extra effort to learn languages. (Of course you need to learn the specific parameters within writing a playbook, but that goes for any provisioning middleware, and pretty much any middleware with configurations).

I’m still playing around with this and haven’t introduced it into my production environment, but I would eventually want to write up some script that’ll take my existing EC2 instances and create a ansible hosts file based on their tags. I see there are a lot more I can do with Ansible.

Jan 8, 2015 - Amazon EC2 Classic - Security Group best practice


Here is an example for a descent Security Group set up, for those of you who use EC2 Classics.
It will provide you with a certain amount of security, but be aware of the risks.
And as I wrote in the previous port, since VPC public subnet+publicIP instances give you more freedom for configuration and are pretty much similar in terms of security, you can go ahead and choose VPC.

This example also can be used in that VPC setting too, so should be useful either way.

Disclaimer: This may still have some security holes. Please leave comments if you have anything to say about them.

Setting up a descent Security Group with EC2 Classic instances

Let’s say you are building a regular web application which gets accessed from HTTP(80) and HTTPS(443).
It’ll have multiple application instances behind a Load Balancer (ELB), and also a RDS database (MySQL) also.

First you want to setup your Gateway instance - the instance that’ll be able to SSH to the actual application instances.
It should only allow access from your IP, whether it is your Office network IP or your mobile Wifi. It’s also a good idea to modify the SSH port of this instance to something other than the default 22. So it can have a Security Group as such:

Port Range Source
62222 (Your IP)

(Remember to modify your sshd configuration so that it accepts 62222 as the SSH port)
We’ll call this sg-gw .

Next, configure your application instances’ Security Group. Your application instances should allow SSH from your Gateway instance, and allow HTTP/HTTPS access from your ELB. Nothing else.
Assume that your ELB has a Security Group called sg-elb (You can easily check your ELB’s Security Group by going to your management console and viewing the description of the Load Balancer).

Port Range Source
80 elb-sg
443 elb-sg
22 sg-gw

Notice that you can set the Source as a particular Security Group. This way, you can guarantee that ONLY instances with that Security Group is allowed to access that port. Pretty useful and easy, right?
This Security Group will be called sg-app .

The final piece is your Security Group for your RDS MySQL. It should only allow access from your application instances, so:

Port Range Source
3306 sg-app

That’s all you need.

Now finally write whatever app it is, have it connect to your RDS, and attach however many application instances you want with sg-app.

So what have we got.
We’ve got ourselves a production-ready application, with very tightly closed ports.
That’s not too bad for just setting some easy Security Groups, is it?

Some potential security risks of this architecture may be:

  • Exposing a public IP (All EC2 Classics automatically have a public IP) so can be discovered by anybody on the internet
  • All HTTP/HTTPS traffic comes in from the ELB, and can include malicious packets that take advantage of software vulnurabilities
  • The Gateway instance can be compromised

The attacker will be able to access any of your nodes once they get into the Gateway instance, so be careful there.
I would say that you should be ready to destroy & re-launch your Gateway instance at anytime, since it isn’t directly critical to your application.
If your Gateway instance seems to be compromised, immediately shut it down, and launch it again with a new SSH key.

I hope I’m not missing any important points. I’m not an expert on network security, and I’m not fully aware of, say, what you can do just by knowing the IP even if ports are closed.

Jan 8, 2015 - Amazon VPC or EC2 Classics?


I Originally started working with EC2 Classic (as most would), and started to fine-tune the Security Group settings in order to construct a robust network security, and now am working with VPCs.
I think VPCs are naturally a better choice due to the ease of configuration (being able to modify Security Groups on instances anytime) and the ability to be able to set private IPs in however fashion you want to.

I want to go over private and public subnets of VPCs, and what to think of them, compared to EC2 Classics.

VPC with private subnets

Private subnets are good; They are secure. They hide your internal instances from the rest of the world, in your own little network.

But most practical use-cases of a server requires some sort of outbound internet connection - whether it be rubygems or yum updates. This means that your VPC has to be equipped with a NAT instance that’ll handle the outbound traffic of your private subnet instances.

Frankly I think NAT instances are bad. It’s a SPoF, because once it goes down your application can’t perform outbound connections. It’s also a potential bottleneck for traffic, since all of your internet traffic goes through that one small instance that just sits there doing nothing. Having an extra EC2 instance to take care of which is a potential SPoF and a bottleneck is VERY stressful.

So, unless your application does not have ANY critical outbound traffic like third-party APIs or github repositories, NAT instances will always be a source of your worries. You can find several solutions to constructing a high-availability NAT instance architecture, like here or here, and even Amazon themselves came out with a pattern here, but for me, implementing these patterns is a hastle in itself unless you really, really want to hide your instances.

Luckily Amazon has been providing support for allocating public IPs on instances on public subnets, recently with Elastic Beanstalk too. So how about that?

VPC with public subnets

Since instances in public subnets can have public IPs, they are capable of outbound internect connection from the start.
It is a pretty convenient solution.

But that means that you have an instance which:

  • Has a public IP (= can be discovered from the internet)
  • Has all internet traffic going in&out with no filter, through a Internet Gateway

In my opinion, that sounds pretty similar to just having an EC2 Classic instance just sitting on the internet.

EC2 Classic

EC2 Classic instances have public IPs attached to them from when they are launched, and they just communicate with the internet on their own.
The Security Group configurations allow them to become a secure, closed node, or a node with all ports wide open.

I’ll go over a secure and clean configuration of EC2 Classics in another post.

So basically it becomes a trade-off of either

  1. Closing off your instances in a private subnet, and trying to maintian a high-availability NAT instance
  2. Using public subnets + public IPs, which are pretty much the same as EC2 Classics in terms of network security

You should think about this trade-off before naively choosing one or the other, or choosing to use EC2 Classics.
But if public subnets + public IP instances are similar to EC2 Classics, why not just go with the VPC?

I think that would be my position.