diff --git a/README.md b/README.md index c8601e0..6ec7381 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ Description This cookbook takes care of the installation and configuration of BIND9. At the moment you're able to define some global variables and to manage your zonefiles via data bags (json example below). It currently also supports automatic serial number generation and automatic resource records for chef nodes (see optional json in example below) -Besides that there's not much to see, e.g. no DNSSEC, no configurable logging, no rndc shell operations or other safety checks (named-checkconf, etc.). +Besides that there's not much to see, e.g. no configurable logging, no rndc shell operations or other safety checks (named-checkconf, etc.). It's my intention to round its edges over time. If you want to help feel free to contribute! -**DISCLAIMER**: +**DISCLAIMER**: Please keep in mind that this cookbook is far from finished and not adequately tested. It could break your setup. Use at **YOUR OWN RISK**! Requirements @@ -17,30 +17,46 @@ Platform: * Debian * Ubuntu -* Centos +* CentOS +* SmartOS Attributes ========== * **node[:bind9][:enable_ipv6]** - Enables BIND to listen on an IPv6 address. Default is: On -* **node[:bind9][:allow_query]** - Allow clients to query the nameserver. Default is: anyone -* **node[:bind9][:allow_recursion]** - Allow recursive name resolution. Default is: none (to prevent DNS cache poisoning) -* **node[:bind9][:allow_update]** - Allow dynamic DNS updates. Default is: none -* **node[:bind9][:allow_transfer]** - Allow zone transfers globally. Default is: none +* **node[:bind9][:allow_query]** - Array of clients allowed to query the nameserver. Default is: anyone +* **node[:bind9][:allow_recursion]** - Array of clients allowed to make recursive name resolution queries. Default is: none (to prevent DNS cache poisoning) +* **node[:bind9][:allow_update]** - Array of clients allowed to make dynamic DNS updates. Default is: none +* **node[:bind9][:allow_transfer]** - Array of clients allowed to make zone transfers. Default is: none * **node[:bind9][:enable_forwarding]** - Enables forwarding of requests. Default is: No forwarding -* **node[:bind9][:forwarders]** - Array for forwarding DNS. Default is: 4.4.4.4 and 8.8.8.8 (Google DNS) +* **node[:bind9][:forwarders]** - Array for forwarding DNS. Default is: 8.8.8.8 and 8.8.4.4 (Google DNS) + +* **node[:bind9][:enable_ddns]** - Allows Dynamic DNS (DDNS) to be enabled. Default is: false +* **node[:bind9][:ddns_algorithm]** - If DDNS is enabled, a algorithm can be specified. Default is: nil +* **node[:bind9][:ddns_secret]** - If DDNS is enabled, a key can be specified. Default is: nil Usage ===== Add "recipe[bind9]" directly to a node or a role. If you want to use BIND9 for serving domains you may add the appropriate data via data bags (example below). -Please note that the data bag's structure is mandatory except: +Please note that the data bag's structure is mandatory except: * TTL for DNS records (if you decide to leave it empty, the global TTL will take over) * autodomain for the zone (if you include this, automatic records will be added for chef nodes whose "domain" matches this) -Examples +Example attributes for a caching-only setup +===== + + default[:bind9][:allow_query] = ["localnets", "localhost"] + default[:bind9][:allow_recursion] = ["localnets", "localhost"] + default[:bind9][:allow_transfer] = ["none"] + default[:bind9][:allow_update] = nil + default[:bind9][:enable_forwarding] = true + default[:bind9][:forwarders] = ["8.8.8.8", "8.8.4.4"] + + +Example zone setup ===== $ knife data bag create zones diff --git a/attributes/default.rb b/attributes/default.rb index e80690e..cb66a78 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -1,28 +1,44 @@ default[:bind9][:enable_ipv6] = true -# Allow all clients to query the nameserver, no recursion -default[:bind9][:allow_query] = nil -default[:bind9][:allow_recursion] = "none" +# Allow only local clients to query the nameserver, with recursion +default[:bind9][:allow_query] = ["localnets", "localhost"] +default[:bind9][:allow_recursion] = ["localnets", "localhost"] # Don:t allow to mess with zone files by default -default[:bind9][:allow_transfer] = "none" +default[:bind9][:allow_transfer] = ["none"] default[:bind9][:allow_update] = nil -default[:bind9][:enable_forwarding] = false -default[:bind9][:forwarders] = [ "4.4.4.4", "8.8.8.8" ] +# default forwarders @ Google +default[:bind9][:enable_forwarding] = true +default[:bind9][:forwarders] = ["8.8.8.8", "8.8.4.4"] + +# Allow user to enable DDNS +default[:bind9][:enable_ddns] = false +default[:bind9][:ddns_algorithm] = nil +default[:bind9][:ddns_secret] = nil case platform -when "centos","redhat","fedora","scientific","amazon" - default[:bind9][:config_path] = "/etc/named" - default[:bind9][:config_file] = "/etc/named.conf" - default[:bind9][:options_file] = "/etc/named/named.conf.options" - default[:bind9][:local_file] = "/etc/named/named.conf.local" - default[:bind9][:data_path] = "/var/named" - default[:bind9][:user] = "named" +when "centos", "redhat", "fedora", "scientific", "amazon" + default[:bind9][:config_path] = "/etc/" + default[:bind9][:config_file] = "/etc/named.conf" + default[:bind9][:options_file] = "/etc/named.conf.options" + default[:bind9][:local_file] = "/etc/named.conf.local" + default[:bind9][:data_path] = "/var/named" + default[:bind9][:log_path] = "/var/log/bind" + default[:bind9][:user] = "named" +when "smartos" + default[:bind9][:config_path] = "/opt/local/etc" + default[:bind9][:config_file] = "/opt/local/etc/named.conf" + default[:bind9][:options_file] = "/opt/local/etc/named.conf.options" + default[:bind9][:local_file] = "/opt/local/etc/named.conf.local" + default[:bind9][:data_path] = "/var/named" + default[:bind9][:log_path] = "/var/log/named" + default[:bind9][:user] = "root" else - default[:bind9][:config_path] = "/etc/bind" - default[:bind9][:options_file] = "/etc/bind/named.conf.options" - default[:bind9][:local_file] = "/etc/bind/named.conf.local" - default[:bind9][:data_path] = "/var/cache/bind" - default[:bind9][:user] = "bind" + default[:bind9][:config_path] = "/etc/bind" + default[:bind9][:options_file] = "/etc/bind/named.conf.options" + default[:bind9][:local_file] = "/etc/bind/named.conf.local" + default[:bind9][:data_path] = "/var/cache/bind" + default[:bind9][:log_path] = "/var/log/named" + default[:bind9][:user] = "bind" end diff --git a/metadata.rb b/metadata.rb index 8ef079b..4128e67 100644 --- a/metadata.rb +++ b/metadata.rb @@ -5,6 +5,6 @@ long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version "0.1.9" -%w{ ubuntu debian centos }.each do |os| +%w{ ubuntu debian centos smartos }.each do |os| supports os end diff --git a/recipes/default.rb b/recipes/default.rb index 5c749ce..d367763 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -19,27 +19,52 @@ package "bind9" do case node[:platform] - when "centos", "redhat", "suse", "fedora" + when "centos", "redhat", "suse", "fedora", "smartos" package_name "bind" end action :install end -directory "/var/log/bind/" do +directory node[:bind9][:data_path] do + only_if { + node[:bind9][:enable_ddns] and + %w{centos redhat fedora scientific amazon}.member? node[:platform] + } owner node[:bind9][:user] group node[:bind9][:user] - mode 0755 + mode 0774 + recursive false + action :create +end + +directory node[:bind9][:log_path] do + owner node[:bind9][:user] + group node[:bind9][:user] + mode 0775 + recursive true + action :create end service "bind9" do case node[:platform] - when "centos", "redhat" + when "centos", "redhat", "fedora", "scientific", "amazon" service_name "named" + when "smartos" + service_name "dns/server:default" end supports :status => true, :reload => true, :restart => true action [ :enable ] end +template node[:bind9][:config_file] do + only_if { %w{centos redhat fedora scientific amazon smartos}.member? node[:platform] } + source "named.conf.erb" + owner "root" + group "root" + mode 0644 + notifies :restart, resources(:service => "bind9") +end + template node[:bind9][:options_file] do source "named.conf.options.erb" owner "root" @@ -59,12 +84,11 @@ notifies :restart, resources(:service => "bind9") end - search(:zones).each do |zone| unless zone['autodomain'].nil? || zone['autodomain'] == '' search(:node, "domain:#{zone['autodomain']}").each do |host| next if host['ipaddress'] == '' || host['ipaddress'].nil? - zone['zone_info']['records'].push( { + zone['zone_info']['records'].push({ "name" => host['hostname'], "type" => "A", "ip" => host['ipaddress'] @@ -72,8 +96,8 @@ end end - template "#{node[:bind9][:config_path]}/#{zone['domain']}" do - source "#{node[:bind9][:config_path]}/#{zone['domain']}.erb" + template "#{node[:bind9][:data_path]}/#{zone['domain']}" do + source "#{node[:bind9][:data_path]}/#{zone['domain']}.erb" local true owner "root" group "root" @@ -85,7 +109,7 @@ action :nothing end - template "#{node[:bind9][:config_path]}/#{zone['domain']}.erb" do + template "#{node[:bind9][:data_path]}/#{zone['domain']}.erb" do source "zonefile.erb" owner "root" group "root" @@ -99,10 +123,15 @@ :mail_exchange => zone['zone_info']['mail_exchange'], :records => zone['zone_info']['records'] }) - notifies :create, resources(:template => "#{node[:bind9][:config_path]}/#{zone['domain']}"), :immediately + notifies :create, resources(:template => "#{node[:bind9][:data_path]}/#{zone['domain']}"), :immediately end end service "bind9" do action [ :start ] end + +bash "selinux" do + only_if { %w{centos redhat fedora scientific amazon}.member? node[:platform] } + code "(sudo setsebool named_write_master_zones true) || true" +end diff --git a/templates/default/named.conf.erb b/templates/default/named.conf.erb new file mode 100644 index 0000000..a206141 --- /dev/null +++ b/templates/default/named.conf.erb @@ -0,0 +1,3 @@ +include "<%= node[:bind9][:options_file] %>"; +include "<%= node[:bind9][:local_file] %>"; +// include "<%= node[:bind9][:config_path] %>/named.conf.default-zones"; diff --git a/templates/default/named.conf.local.erb b/templates/default/named.conf.local.erb index c35456b..cfecb10 100644 --- a/templates/default/named.conf.local.erb +++ b/templates/default/named.conf.local.erb @@ -1,20 +1,31 @@ // -// Do any local configuration here +// MANAGED BY CHEF : Do any local configuration here // // Consider adding the 1918 zones here, if they are not used in your // organization //include "/etc/bind/zones.rfc1918"; +<% if node[:bind9][:enable_ddns] %> +key DDNS_UPDATE { + algorithm <%= node[:bind9][:ddns_algorithm] %>; + secret "<%= node[:bind9][:ddns_secret] %>"; +}; +<% end %> + <% @zonefiles.each do |conf| -%> zone "<%= conf["domain"] %>" IN { type <%= conf["type"] %>; - file "<%= node[:bind9][:config_path] %>/<%= conf["domain"] %>"; + file "<%= node[:bind9][:data_path] %>/<%= conf["domain"] %>"; + notify no; allow-transfer { <% conf["allow_transfer"].each do |ip| -%> <%= ip %>; <% end %> }; + <% if node[:bind9][:enable_ddns] %> + allow-update { key DDNS_UPDATE; }; + <% end %> }; <% end %> diff --git a/templates/default/named.conf.options.erb b/templates/default/named.conf.options.erb index 1d536a9..37b27bc 100644 --- a/templates/default/named.conf.options.erb +++ b/templates/default/named.conf.options.erb @@ -1,47 +1,59 @@ options { - directory "<%= node[:bind9][:data_path] %>"; - - // If there is a firewall between you and nameservers you want - // to talk to, you may need to fix the firewall to allow multiple - // ports to talk. See http://www.kb.cert.org/vuls/id/800113 - - <% if node[:bind9][:allow_query] %> - allow-query { - "<%= node[:bind9][:allow_query] %>"; - }; - - <% end %> - allow-recursion { - <%= node[:bind9][:allow_recursion] %>; - }; - - allow-transfer { - "<%= node[:bind9][:allow_transfer] %>"; - }; - - <% if node[:bind9][:allow_update] %> - allow-update { - "<%= node[:bind9][:allow_update] %>"; - }; - - <% end %> - <% if node[:bind9][:enable_forwarding] %> - forwarders { - <% node[:bind9][:forwarders].each do |forwarder| -%> - <%= forwarder %>; - <% end %> - }; - - <% end %> - auth-nxdomain no; # conform to RFC1035 - <% if node[:bind9][:enable_ipv6] %> - listen-on-v6 { any; }; - <% end %> + directory "<%= node[:bind9][:data_path] %>"; + + // If there is a firewall between you and nameservers you want + // to talk to, you may need to fix the firewall to allow multiple + // ports to talk. See http://www.kb.cert.org/vuls/id/800113 + + <% if node[:bind9][:allow_query] %> + allow-query { + <% node[:bind9][:allow_query].each do |allow_query| -%> + <%= allow_query %>; + <% end %> + }; + + <% end %> + <% if node[:bind9][:allow_recursion] %> + allow-recursion { + <% node[:bind9][:allow_recursion].each do |allow_recursion| -%> + <%= allow_recursion %>; + <% end %> + }; + + <% end %> + <% if node[:bind9][:allow_transfer] %> + allow-transfer { + <% node[:bind9][:allow_transfer].each do |allow_transfer| -%> + <%= allow_transfer %>; + <% end %> + }; + + <% end %> + <% if node[:bind9][:allow_update] %> + allow-update { + <% node[:bind9][:allow_update].each do |allow_update| -%> + <%= allow_update %>; + <% end %> + }; + + <% end %> + <% if node[:bind9][:enable_forwarding] %> + forwarders { + <% node[:bind9][:forwarders].each do |forwarder| -%> + <%= forwarder %>; + <% end %> + }; + + <% end %> + auth-nxdomain no; # conform to RFC1035 + <% if node[:bind9][:enable_ipv6] %> + listen-on-v6 { any; }; + <% end %> }; logging { channel default_log { - file "/var/log/bind/bind.log" versions 5 size 128M; + file "<%= node[:bind9][:log_path] %>/named.log" versions 5 size 128M; print-time yes; print-severity yes; print-category yes;