Unfinished Development Web Development, Infrastructure & Testing

Route53 DNS updates with Foreman

I've been using Foreman within Amazon Web Services (AWS) for a while now on a number of different projects. The EC2 Compute resource is pretty solid in my experience. It has a couple of limitations but nothing that cannot be worked around with a little thought.

The biggest drawback for me was the lack of support for Route53 in the Smart Proxy. This meant choosing between no custom DNS names or rolling your own solution using the hooks plugin that Foreman provides. That is all about to change with Foreman Smart Proxy 1.10 as it will introduce DNS provider plugins and they have released a Route53 plugin already for use with it.

Not one to enjoy waiting, I wanted to have a play with this new functionaility, so I decided to run a 2nd smart proxy, built from source on a separate instance. This would allow me to follow the standard upgrade process when the 1.10 release is officially available on my current install.

Building the Smart Proxy

Building the smart proxy is pretty simple. I created a new instance and ensured the Foreman server was able to communicate with it over HTTPS, cloned the source, installed the required dependencies and certificates and I was good to go.

Note: the following steps were run against a CentOS 7 AMI from the marketplace

Getting the Smart Proxy Code

sudo yum -y install git
cd /usr/local
sudo git clone git://github.com/theforeman/smart-proxy.git foreman-proxy

sudo chown -R <user>:<group> foreman-proxy

Install the Route53 Plugin

The Route53 DNS provider is a plugin, so we need to tell the smart proxy to install it and add it to our load path. This is all accomplished through Bundler (in the released versions bundler_ext is used, so the process will be slightly different).

Whilst installing the gems is pretty simple, there are a few pre-requisites we will need first (note the install of bundler is not done as root):

sudo yum -y install gcc ruby-devel zlib-devel patch augeas-devel

gem install bundler

Now we add the plugin gem to our list of dependencies. We'll add it to the bundler.d/Gemfile.local.rb file so that subsequent updates won't overwrite it

echo "gem 'smart_proxy_dns_route53', '1.0.0'" >> /usr/local/foreman-proxy/bundler.d/Gemfile.local.rb

The last step in installing the plugin is actually installing all of the gems. As we are trying out the DNS provider functionality, we're skip installing the dependencies of other features

bundle install --without development test bmc krb5 puppet puppetca windows

SSL Certificates

In order for Foreman and the Smart Proxy to be able to communicate over HTTPS we'll need to generate some certificates for the smart proxy host and make it aware of the certificate authority Foreman is using.

On you Foreman host, generate the correct certificates for the smart proxy host:

sudo puppet cert --generate <proxy-FQDN>

You then need to copy the following files:

  • /var/lib/puppet/ssl/certs/ca.pem
  • /var/lib/puppet/ssl/certs/<proxy-FQDN>.pem
  • /var/lib/puppet/ssl/private_keys/<proxy-FQDN>.key

Copy them to the following locations on the smart proxy host (you may need to create the directory structure first):

  • /usr/local/foreman-proxy/ssl/certs/ca.pem
  • /usr/local/foreman-proxy/ssl/certs/<proxy-FQDN>.pem
  • /usr/local/foreman-proxy/ssl/private_keys/<proxy-FQDN>.key

Configure the Smart Proxy

Next up we need to create the settings file for the proxy. The Foreman team provide a nice example to copy:

cd /usr/local/foreman-proxy

cp config/settings.yml.example config/settings.yml
vi config/settings.yml
---

# SSL Setup
# If enabled, all communication would be verified via SSL
# NOTE that both certificates need to be signed by the same CA in order for this to work
# see http://theforeman.org/projects/smart-proxy/wiki/SSL for more information
:ssl_certificate: /usr/local/foreman-proxy/ssl/certs/proxy-FQDN.pem
:ssl_ca_file: /usr/local/foreman-proxy/ssl/certs/ca.pem
:ssl_private_key: /usr/local/foreman-proxy/ssl/private_keys/proxy-FQDN.key

# Hosts which the proxy accepts connections from
# commenting the following lines would mean every verified SSL connection allowed
# HTTPS: test the certificate CN
# HTTP: test the reverse DNS entry of the remote IP
:trusted_hosts:
  - "foreman-FQDN"

# verify a DNS reverse lookup against it's forward lookup
# 1.1.1.1 -> foreman.mycompany.com -> 1.1.1.1
# (default: true)
:forward_verify: true

:foreman_url: http://foreman-FQDN

# SSL settings for client authentication against Foreman. If undefined, the values
# from general SSL options are used instead. Mainly useful when Foreman uses
# different certificates for its web UI and for smart-proxy requests.
#:foreman_ssl_ca: ssl/certs/ca.pem
#:foreman_ssl_cert: ssl/certs/fqdn.pem
#:foreman_ssl_key: ssl/private_keys/fqdn.pem

# by default smart_proxy runs in the foreground. To enable running as a daemon, uncomment 'daemon' setting
:daemon: true
# Only used when 'daemon' is set to true.
# Uncomment and modify if you want to change the default pid file '/var/run/foreman-proxy/foreman-proxy.pid'
#:daemon_pid: /var/run/foreman-proxy/foreman-proxy.pid

# host and ports configuration
# host to bind ports to (possible values: *, localhost, 0.0.0.0)
:bind_host: '0.0.0.0'
# http is disabled by default. To enable, uncomment 'http_port' setting
#:http_port: 8000
# https is enabled if certificate, CA certificate, and private key are present in locations specifed by
# ssl_certificate, ssl_ca_file, and ssl_private_key correspondingly
# default values for https_port is 8443
:https_port: 8443

# Shared options for virsh DNS/DHCP provider
:virsh_network: default

# Log configuration
# Uncomment and modify if you want to change the location of the log file or use STDOUT or SYSLOG values
#:log_file: /var/log/foreman-proxy/proxy.log
# Uncomment and modify if you want to change the log level
# WARN, DEBUG, ERROR, FATAL, INFO, UNKNOWN
:log_level: ERROR

Now we need to configure the DNS feature to use our Route53 plugin

cp config/settings.d/dns.yml.example config/settings.d/dns.yml

vi config/settings.d/dns.yml
---
# Can be true, false, or http/https to enable just one of the protocols
:enabled: https 

:use_provider: dns_route53

The plugin connects via IAM credentials, so we need to tell it what credentials to use

vi config/settings.d/dns_route53.yml
---

# The plugin docs don't mention this, but I saw messages 
# in the log about it being disabled without it
:enabled: true

:aws_access_key: "<YOUR IAM ACCESS KEY>"
:aws_secret_key: "<YOUR IAM SECRET KEY>"

Running Service

In the configuration for the smart proxy above, we configured it to run as a background daemon. That means it will need write access to a couple of directories to create is pid file and log file

sudo mkdir -p /var/log/foreman-proxy && sudo chown <user>:<group> /var/log/foreman-proxy && sudo chmod 775 /var/log/foreman-proxy

sudo mkdir -p /var/run/foreman-proxy && sudo chown <user>:<group> /var/run/foreman-proxy && sudo chmod 775 /var/run/foreman-proxy

We can now start our smart proxy by simply executing bin/smart-proxy from the /usr/local/foreman-proxy directory

Add the Proxy to Foreman

Before you can use this smart proxy you will need to add it to Foreman. If you have used the about configuration you should be able to use https://<proxy-FQDN>:8443 as the URL. It should only respond with the DNS feature being available.

You will also need to configure your domains (in Infrastructure --> Domains) to use this proxy if the zones are hosted in Route53