Software Engineer

doing a dns lookup inside your puppet manifest

· by jsnby · Read in about 2 min · (240 Words)
Puppet

Update 2017-10-06:

It’s 2017. Don’t use the code below, but use the excellent dalen/dnsquery module instead. Leaving the original post below for historical reasons.


I use dynamic DNS at my residence so that I can always log into my server remotely without having to know the IP.

I run denyhosts on the server hosting my website at Rackspace to attempt to contain brute-force ssh attacks. If you enter the wrong password N times, your IP gets banned and you can’t connect to my server anymore via ssh.

The problem is that I can often times legitimately mistype my password. I want to ensure that I don’t accidentally lock myself out of my Rackspace VM. Luckily, denyhosts provides a way for you to whitelist IPs so that they will never be locked out…the allowed-hosts file.

Ok, but now my manifest needs to know what my dyndns name resolves to at manifest compilation time. To get around that, I added a function called dnsLookup. I put this in modules/custom/lib/puppet/parser/functions/dnsLookup.rb:

# dnsLookup.rb
# does a DNS lookup and returns an array of strings of the results

require 'resolv'

module Puppet::Parser::Functions
    newfunction(:dnsLookup, :type => :rvalue) do |args|
        result = []
        result = Resolv.new.getaddresses(args[0])
        return result
    end
end

So, now in my manifest, I can put something like this:

class denyhosts {
    # ...

    $allowed_ips = ['127.0.0.1', dnsLookup('dyndnsname.example.com')]

    file { "/var/lib/denyhosts/allowed-hosts":
        ensure  => present,
        owner   => root,
        group   => root,
        mode    => 0644,
        content => template('denyhosts/allowed-hosts.erb'),
        notify  => Service["denyhosts"],
    }

   # ...
}

The allowed-hosts.erb template looks like this:

<% allowed_ips.each do |ip| -%>
<%= ip %>
<% end -%>

I haven’t tested this with a name that has multiple records, so you might need to tweak or tune this if that is your particular use case.