Terraform é uma ferramenta da Hashicorp focada em Bootstrapping e inicialização de recursos, se fizermos uma comparação entre Puppet e Terraform por exemplo, o Puppet é responsável por gerenciar a configuração de uma infraestrutura que já existe, já o Terraform vai criar essa infraestrutura que será gerenciada pelo Puppet.
Nesse post vou mostrar como podemos gerenciar entradas de DNS através do Terraform usando o protocolo TSIG ( Transaction Signature ) que é documentando na RFC 2845 ( https://tools.ietf.org/html/rfc2845 ), isso permite que façamos atualizações dinâmicas no servidor de DNS de forma segura sem precisar logar no servidor.
Agora Hands On! O primeiro passo é subir uma máquina no Vagrant com o bind9 instalado:
# -*- mode: ruby -*- # vi: set ft=ruby : # All Vagrant configuration is done below. The "2" in Vagrant.configure # configures the configuration version (we support older styles for # backwards compatibility). Please don't change it unless you know what # you're doing. Vagrant.configure("2") do |config| config.vm.provider "virtualbox" do |vb| vb.memory = "1024" end config.vm.define "bind9" do |node| node.vm.box = "ubuntu/trusty64" node.vm.hostname = "dns-terraform" node.vm.network "public_network", bridge: "wlp4s0" node.vm.provision "shell", inline: <<-SHELL apt-get clean all apt-get update apt-get install -y bind9 dnsutils SHELL end end
Esse Vagrantfile irá subir um servidor Ubuntu 16.04 já com o bind9 instalado, que é o servidor de DNS geralmente utilizado nos servidores Linux.
Após a inicialização da máquina, acesse o diretório /etc/bind:
$ vagrant ssh bind9 vagrant@dns-terraform:~$ sudo su - root@dns-terraform:~# cd /etc/bind/
Veja os arquivos dentro do diretório:
root@dns-terraform:/etc/bind# ls bind.keys db.127 db.empty db.root named.conf.default-zones named.conf.options zones.rfc1918 db.0 db.255 db.local named.conf named.conf.local rndc.key
O bind quando instalado automaticamente já cria uma chave chamada rndc.key, vamos ver o conteúdo dela:
root@dns-terraform:/etc/bind# cat rndc.key key "rndc-key" { algorithm hmac-md5; secret "oP+1ph0UYnWnL/D8QXNYSQ=="; };
Copie esse conteúdo e cole dentro de /etc/bind/named.conf.local.
root@dns-terraform:/etc/bind# cat named.conf.local // // Do any local configuration here // // Consider adding the 1918 zones here, if they are not used in your // organization //include "/etc/bind/zones.rfc1918"; key "rndc-key" { algorithm hmac-md5; secret "oP+1ph0UYnWnL/D8QXNYSQ=="; };
Nesse passo criamos uma chave chamada rndc-key que vamos usar em breve. Agora precisamos criar uma zona de DNS.
root@dns-terraform:/etc/bind# cp /etc/bind/db.local /var/cache/bind/db.alissonmachado.com.br
Substitua o conteúdo localhost por alissonmachado.com.br.
root@dns-terraform:/etc/bind# sed -i "s/localhost/alissonmachado.com.br/g" /var/cache/bind/db.alissonmachado.com.br
A zona de DNS deve ficar da seguinte forma:
root@dns-terraform:/etc/bind# cat /var/cache/bind/db.alissonmachado.com.br ; ; BIND data file for local loopback interface ; $TTL 604800 @ IN SOA alissonmachado.com.br. root.alissonmachado.com.br. ( 2 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; @ IN NS alissonmachado.com.br. @ IN A 127.0.0.1 @ IN AAAA ::1
Agora vamos editar de novo o named.conf.local e deixar da seguinte forma:
root@dns-terraform:/etc/bind# cat /etc/bind/named.conf.local // // Do any local configuration here // // Consider adding the 1918 zones here, if they are not used in your // organization //include "/etc/bind/zones.rfc1918"; key "rndc-key" { algorithm hmac-md5; secret "oP+1ph0UYnWnL/D8QXNYSQ=="; }; zone "alissonmachado.com.br." { type master; file "/var/cache/bind/db.alissonmachado.com.br"; allow-update { key rndc-key; }; };
Agora reinicie o bind.
root@dns-terraform:/etc/bind# service bind9 restart * Stopping domain name service... bind9 waiting for pid 3291 to die [ OK ] * Starting domain name service... bind9 [ OK ] root@dns-terraform:/etc/bind#
Para validar se o DNS está funcionando utilize o comando host:
root@dns-terraform:/etc/bind# host alissonmachado.com.br localhost Using domain server: Name: localhost Address: 127.0.0.1#53 Aliases: alissonmachado.com.br has address 127.0.0.1
Está Ok! Agora vamos para o Terraform.
Para instalar o Terraform é só baixar o zip da documentação oficial. https://www.terraform.io/downloads.html Agora crie um arquivo chamado alisson_dns.tf com o seguinte conteúdo:
provider "dns" { update { server = "10.100.0.171" key_name = "rndc-key." key_algorithm = "hmac-md5" key_secret = "oP+1ph0UYnWnL/D8QXNYSQ==" } } resource "dns_a_record_set" "teste" { zone = "alissonmachado.com.br." name = "hector" addresses = [ "6.6.6.6" ] ttl = 300 } resource "dns_a_record_set" "jorge" { zone = "alissonmachado.com.br." name = "jorge" addresses = [ "10.10.10.10" ] ttl = 300 }
Com o arquivo criado, deixe o log do dns na tela para acompanhar a modificação:
root@dns-terraform:/etc/bind# tail -f /var/log/syslog
Dentro do Terraform, utilizamos o provider DNS, que deve ser baixado antes de executar o Terraform, para isso na pasta onde vc criou o alisson_dns.tf, digite o comando terraform init.
$ terraform init Initializing provider plugins... - Checking for available provider plugins on https://releases.hashicorp.com... - Downloading plugin for provider "dns" (1.0.0)... The following providers do not have any version constraints in configuration, so the latest version was installed. To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below. * provider.dns: version = "~> 1.0" Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If y
Agora o provider já foi instalado. Digite o comando terraform plan, ele irá mostrar o que será alterado no seu dns.
$ terraform plan Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + dns_a_record_set.jorge id: addresses.#: "1" addresses.3258735021: "10.10.10.10" name: "jorge" ttl: "300" zone: "alissonmachado.com.br." + dns_a_record_set.teste id: addresses.#: "1" addresses.3786324972: "6.6.6.6" name: "hector" ttl: "300" zone: "alissonmachado.com.br." Plan: 2 to add, 0 to change, 0 to destroy. ------------------------------------------------------------------------ a chamada Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
Veja que ele irá criar duas entradas de dns, uma chamada jorge apontando para o ip 10.10.10.10 e outra chamada hector apontando para o ip 6.6.6.6. Digite agora o comando terraform apply.
$ terraform apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: + dns_a_record_set.jorge id: addresses.#: "1" addresses.3258735021: "10.10.10.10" name: "jorge" ttl: "300" zone: "alissonmachado.com.br." + dns_a_record_set.teste id: addresses.#: "1" addresses.3786324972: "6.6.6.6" name: "hector" ttl: "300" zone: "alissonmachado.com.br." Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes dns_a_record_set.teste: Creating... addresses.#: "" => "1" addresses.3786324972: "" => "6.6.6.6" name: "" => "hector" ttl: "" => "300" zone: "" => "alissonmachado.com.br." dns_a_record_set.jorge: Creating... addresses.#: "" => "1" addresses.3258735021: "" => "10.10.10.10" name: "" => "jorge" ttl: "" => "300" zone: "" => "alissonmachado.com.br." dns_a_record_set.jorge: Creation complete after 0s (ID: jorge.alissonmachado.com.br.) dns_a_record_set.teste: Creation complete after 0s (ID: hector.alissonmachado.com.br.)
Veja que no final da execução do comando apareceu a mensagem Creation complete.
No log do bind apareceu a seguinte mensagem:
root@dns-terraform:/etc/bind# tail -f /var/log/syslog Apr 30 18:51:54 vagrant-ubuntu-trusty-64 named[3608]: client 10.100.0.185#53063/key rndc-key: updating zone 'alissonmachado.com.br/IN': adding an RR at 'jorge.alissonmachado.com.br' A Apr 30 18:51:54 vagrant-ubuntu-trusty-64 named[3608]: client 10.100.0.185#47174/key rndc-key: signer "rndc-key" approved Apr 30 18:51:54 vagrant-ubuntu-trusty-64 named[3608]: client 10.100.0.185#47174/key rndc-key: updating zone 'alissonmachado.com.br/IN': adding an RR at 'hector.alissonmachado.com.br' A
Agora se eu fizer uma consulta de DNS deve retornar os IPs cadastrados no terraform.
root@dns-terraform:/etc/bind# host jorge.alissonmachado.com.br localhost Using domain server: Name: localhost Address: 127.0.0.1#53 Aliases: jorge.alissonmachado.com.br has address 10.10.10.10 root@dns-terraform:/etc/bind# host hector.alissonmachado.com.br localhost Using domain server: Name: localhost Address: 127.0.0.1#53 Aliases: hector.alissonmachado.com.br has address 6.6.6.6
Dahora, é isso ae, valeuz!