From 05477570e2be614ad7af06b49cb1aabd0300b4e2 Mon Sep 17 00:00:00 2001 From: Ryan Walder Date: Tue, 31 Jul 2018 16:50:19 +0100 Subject: [PATCH] Overhaul testing * Test package install * Test service * Test configs * Test zonefiles --- .kitchen.yml | 109 +++++++++++----- test/integration/default/config_spec.rb | 151 ++++++++++++++++++++++ test/integration/default/service_spec.rb | 1 - test/integration/default/zones_spec.rb | 156 +++++++++++++++++++++++ 4 files changed, 386 insertions(+), 31 deletions(-) create mode 100644 test/integration/default/config_spec.rb create mode 100644 test/integration/default/zones_spec.rb diff --git a/.kitchen.yml b/.kitchen.yml index ce5459d..3a340b4 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -39,64 +39,113 @@ provisioner: client2: - 10.30.0.0/8 configured_zones: - my.zone: + example.com: type: master notify: False update_policy: - "grant core_dhcp name dns_entry_allowed_to_update. ANY" - - example.com: + notify: False + example.net: + type: master + notify: False + example.org: + type: slave + notify: False + masters: + - 192.0.2.1 + - 192.0.2.2 + 113.0.203.in-addr.arpa: type: master notify: false + 100.51.198.in-addr.arpa: + type: master + notify: False available_zones: - my.zone: - file: my.zone.txt + example.net: + file: example.net soa: class: IN - ns: ns1.example.com - contact: hostmaster.example.com - serial: 2017041001 - retry: 600 - ttl: 8600 + ns: ns1.example.net + contact: hostmaster.example.net + serial: auto + retry: 300 + ttl: 300 records: - A: - ns1: 1.2.3.4 - mx1: - - 1.2.3.228 - - 1.2.3.229 NS: '@': - ns1 + A: + ns1: 198.51.100.1 + foo: 198.51.100.2 + bar: 198.51.100.3 + baz: 198.51.100.4 + mx1: + - 198.51.100.5 + - 198.51.100.6 + - 198.51.100.7 + CNAME: + mail: mx1.example.net. + smtp: mx1.example.net. example.com: - file: example.com.txt + file: example.com soa: class: IN ns: ns1.example.com contact: hostmaster.example.com - serial: 2017041001 + serial: 2018073100 retry: 600 - ttl: 8600 + ttl: 600 records: - A: - mx1: - - 1.2.3.228 - - 1.2.3.229 - - 2.3.4.186 - cat: 2.3.4.188 - rat: 1.2.3.231 - live: 1.2.3.236 NS: '@': - - rat - - cat + - ns1 + A: + ns1: 203.0.113.1 + foo: 203.0.113.2 + bar: 203.0.113.3 CNAME: - ftp: cat.example.com. - www: cat.example.com. + ftp: foo.example.com. + www: bar.example.com. mail: mx1.example.com. smtp: mx1.example.com. TXT: '@': - '"some_value"' + 113.0.203.in-addr.arpa: + file: 113.0.203.in-addr.arpa + soa: + class: IN + ns: ns1.example.com + contact: hostmaster.example.com + serial: 2018073100 + retry: 600 + ttl: 600 + records: + NS: + '@': + - ns1.example.com. + PTR: + 1.113.0.203.in-addr.arpa: ns1.example.com. + 2.113.0.203.in-addr.arpa: foo.example.com. + 3.113.0.203.in-addr.arpa: bar.example.com. + 100.51.198.in-addr.arpa: + file: 100.51.198.in-addr.arpa + soa: + class: IN + ns: ns1.example.net + contact: hostmaster.example.net + serial: auto + retry: 600 + ttl: 600 + records: + NS: + '@': + - ns1.example.net. + generate_reverse: + net: 198.51.100.0/24 + for_zones: + - example.net + verifier: name: inspec diff --git a/test/integration/default/config_spec.rb b/test/integration/default/config_spec.rb new file mode 100644 index 0000000..991e993 --- /dev/null +++ b/test/integration/default/config_spec.rb @@ -0,0 +1,151 @@ +# Set defaults, use debian as base + +conf_user = 'bind' +conf_group = 'bind' +keys_user = 'root' +keys_group = conf_group +logs_user = 'root' +logs_group = conf_group +named_directory = '/var/cache/bind' +zones_directory = '/var/cache/bind/zones' +keys_directory = '/etc/bind/keys' +log_directory = '/var/log/bind9' +keys_mode = '02755' +conf_mode = '0644' +config = '/etc/bind/named.conf' + +# Override by OS +case os[:name] +when 'arch','redhat', 'centos', 'fedora' + conf_user = 'named' + conf_group = 'named' + keys_group = 'root' + logs_group = conf_group + named_directory = '/var/named' + zones_directory = named_directory + keys_directory = '/etc/named.keys' + log_directory = '/var/log/named' + keys_mode = '0755' + conf_mode = '0640' + config = '/etc/named.conf' +when 'ubuntu' + log_directory = '/var/log/named' +end + +# Check main config dir +control 'Directory ' + named_directory do + title 'should exist' + describe directory(named_directory) do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0775' } + end +end + +# Check DNSSEC keys dir +control 'Directory ' + keys_directory do + title 'should exist' + describe directory(keys_directory) do + its('owner') { should eq keys_user } + its('group') { should eq keys_group } + its('mode') { should cmp keys_mode } + end +end + +# Check Logs dir +control 'Directory ' + log_directory do + title 'should exist' + describe directory(log_directory) do + its('owner') { should eq logs_user } + its('group') { should eq logs_group } + its('mode') { should cmp '0775' } + end +end + +# Check zones dir if on debian based OS +control 'Directory ' + zones_directory do + title 'should exist' + only_if do + os.debian? + end + describe directory(zones_directory) do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0775' } + end +end + +# Check main config +# RHEL: Doesn't use .options and has rfc1912.zones +# Debian: Uses .options +case os[:name] +when 'arch','redhat', 'centos', 'fedora' + control 'File ' + config do + title 'should exist' + describe file(config) do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp conf_mode } + its('content') { should match /^include\ "\/etc\/named\.rfc1912\.zones";/ } + its('content') { should match /^include\ "\/etc\/named\.conf\.local";/ } + end + end +when 'ubuntu', 'debian' + control 'File ' + config do + title 'should exist' + describe file(config) do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp conf_mode } + its('content') { should match /^include\ "\/etc\/bind\/named\.conf\.local";/ } + its('content') { should match /^include\ "\/etc\/bind\/named\.conf\.options";/ } + end + end +end + +# If debian check the .options file +control 'File ' + config + '.options' do + title 'should exist' + only_if do + os.debian? + end + describe file(config + '.options') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + its('content') { should match /\ {8}directory\ "#{named_directory}"/ } + its('content') { should match /\ {8}key-directory\ "#{keys_directory}"/ } + end +end + +# Check config.local +control 'File ' + config + '.local' do + title 'should exist' + describe file(config + '.local') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Multi line regex to match the various zones + # If you're here to update the pillar/tests I would highly reccommend + # using an online miltiline regex editor to do this: + # https://www.regextester.com/ + # the #{foo} is a ruby string expansion so we can use the variables + # defined above + # Match example.com zone from the pillar + its('content') { should match /^zone\ "example\.com"\ {\n\ \ type\ master;\n\ \ file\ "#{zones_directory}\/example\.com";\n\ \ \n\ \ update-policy\ {\n\ \ \ \ grant\ core_dhcp\ name\ dns_entry_allowed_to_update\.\ ANY;\n\ \ \};\n\ \ notify\ no;\n\};/ } + # Match example.net from pillar + its('content') { should match /^zone\ "example\.net"\ {\n\ \ type\ master;\n\ \ file\ "#{zones_directory}\/example\.net";\n\ \ \n\ \ notify\ no;\n\};/ } + # Match example.org from pillar + its('content') { should match /^zone\ "example\.org"\ {\n\ \ type\ slave;\n\ \ file\ "#{zones_directory}\/";\n\ \ \n\ \ notify\ no;\n\ \ masters\ \{\n\ \ \ \ 192\.0\.2\.1;\n\ \ \ \ 192\.0\.2\.2;\n\ \ \};\n\};/ } + # Match 113.0.203 reverse zone from pillar + its('content') { should match /^zone\ "113\.0\.203\.in-addr\.arpa"\ {\n\ \ type\ master;\n\ \ file\ "#{zones_directory}\/113\.0\.203\.in-addr\.arpa";\n\ \ \n\ \ notify\ no;\n\};/ } + # Match 100.51.198 reverse zone from pillar + its('content') { should match /^zone\ "100\.51\.198\.in-addr\.arpa"\ {\n\ \ type\ master;\n\ \ file\ "#{zones_directory}\/100\.51\.198\.in-addr\.arpa";\n\ \ \n\ \ notify\ no;\n\};/ } + # Match logging + its('content') { should match /^logging\ \{\n\ \ channel\ "querylog"\ {\n\ \ \ \ file\ "#{log_directory}\/query\.log";\n\ \ \ \ print-time\ yes;\n\ \ \};\n\ \ category\ queries\ \{\ querylog;\ \};\n\};/ } + # Match acl1 + its('content') { should match /acl\ client1\ \{\n\ \ 127\.0\.0\.0\/8;\n\ \ 10\.20\.0\.0\/16;\n\};/ } + # Match acl2 + its('content') { should match /^acl\ client2\ \{\n\ \ 10\.30\.0\.0\/8;\n\};/ } + end +end diff --git a/test/integration/default/service_spec.rb b/test/integration/default/service_spec.rb index e6e78fb..851b14b 100644 --- a/test/integration/default/service_spec.rb +++ b/test/integration/default/service_spec.rb @@ -14,4 +14,3 @@ control 'Bind9 service' do it { should be_running } end end - diff --git a/test/integration/default/zones_spec.rb b/test/integration/default/zones_spec.rb new file mode 100644 index 0000000..d5a3db0 --- /dev/null +++ b/test/integration/default/zones_spec.rb @@ -0,0 +1,156 @@ +# Set defaults, use debian as base + +conf_user = 'bind' +conf_group = 'bind' +keys_user = 'root' +keys_group = conf_group +logs_user = 'root' +logs_group = conf_group +named_directory = '/var/cache/bind' +zones_directory = '/var/cache/bind/zones' +keys_directory = '/etc/bind/keys' +log_directory = '/var/log/bind9' +keys_mode = '02755' +conf_mode = '0644' +config = '/etc/bind/named.conf' + +# Override by OS +case os[:name] +when 'arch','redhat', 'centos', 'fedora' + conf_user = 'named' + conf_group = 'named' + keys_group = 'root' + logs_group = conf_group + named_directory = '/var/named' + zones_directory = named_directory + keys_directory = '/etc/named.keys' + log_directory = '/var/log/named' + keys_mode = '0755' + conf_mode = '0640' + config = '/etc/named.conf' +when 'ubuntu' + log_directory = '/var/log/named' +end + +# Test example.com zonefile +control 'File ' + zones_directory + '/example.com' do + title 'should exist' + describe file(zones_directory + '/example.com') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Multi line regex to match the various zones + # If you're here to update the pillar/tests I would highly reccommend + # using an online miltiline regex editor to do this: + # https://www.regextester.com/ + # the #{foo} is a ruby string expansion so we can use the variables + # defined above + + # Match SOA + its('content') { should match /^@\ IN\ SOA\ ns1.example.com\ hostmaster.example.com\ \(\n 2018073100\ ;\ serial\n\ \ \ \ 12h\ ;\ refresh\n\ \ \ \ 600\ ;\ retry\n\ \ \ \ 2w\ ;\ expiry\n\ \ \ \ 1m\ ;\ nxdomain\ ttl\n\);/ } + + # Just match string for these as it's much easier to read + # Match NS + its('content') { should match '@ NS ns1' } + # Match A + its('content') { should match 'ns1 A 203.0.113.1' } + its('content') { should match 'foo A 203.0.113.2' } + its('content') { should match 'bar A 203.0.113.3' } + # Match CNAME + its('content') { should match 'ftp CNAME foo.example.com.' } + its('content') { should match 'www CNAME bar.example.com.' } + its('content') { should match 'mail CNAME mx1.example.com.' } + its('content') { should match 'smtp CNAME mx1.example.com.' } + # Match TXT + its('content') { should match '@ TXT "some_value"' } + end +end + +# Test example.net zonefile +control 'File ' + zones_directory + '/example.net' do + title 'should exist' + describe file(zones_directory + '/example.net') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Match SOA + its('content') { should match /^@\ IN\ SOA\ ns1.example.net\ hostmaster.example.net\ \(\n\ \ \ \ [0-9]{10}\ ;\ serial\n\ \ \ \ 12h\ ;\ refresh\n\ \ \ \ 300\ ;\ retry\n\ \ \ \ 2w\ ;\ expiry\n\ \ \ \ 1m\ ;\ nxdomain\ ttl\n\);/ } + # Match Include + its('content') { should match /^\$INCLUDE\ #{zones_directory}\/example\.net\.include$/ } + end +end + +# Test example.net.include zonefile +control 'File ' + zones_directory + '/example.net.include' do + title 'should exist' + describe file(zones_directory + '/example.net.include') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Just match string for these as it's much easier to read + # Match NS + its('content') { should match '@ NS ns1' } + # Match A + its('content') { should match 'ns1 A 198.51.100.1' } + its('content') { should match 'foo A 198.51.100.2' } + its('content') { should match 'bar A 198.51.100.3' } + its('content') { should match 'baz A 198.51.100.4' } + its('content') { should match 'mx1 A 198.51.100.5' } + its('content') { should match 'mx1 A 198.51.100.6' } + its('content') { should match 'mx1 A 198.51.100.7' } + # Match CNAME + its('content') { should match 'mail CNAME mx1.example.net.' } + its('content') { should match 'smtp CNAME mx1.example.net.' } + end +end + +# Test 113.0.203.in-addr.arpa zonefile +control 'File ' + zones_directory + '/113.0.203.in-addr.arpa' do + title 'should exist' + describe file(zones_directory + '/113.0.203.in-addr.arpa') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Match SOA + its('content') { should match /^@\ IN\ SOA\ ns1.example.com\ hostmaster.example.com\ \(\n\ \ \ \ 2018073100\ ;\ serial\n\ \ \ \ 12h\ ;\ refresh\n\ \ \ \ 600\ ;\ retry\n\ \ \ \ 2w\ ;\ expiry\n\ \ \ \ 1m\ ;\ nxdomain\ ttl\n\);/ } + + # Just match string for these as it's much easier to read + # Match Include + its('content') { should match '1.113.0.203.in-addr.arpa PTR ns1.example.com.' } + its('content') { should match '2.113.0.203.in-addr.arpa PTR foo.example.com.' } + its('content') { should match '3.113.0.203.in-addr.arpa PTR bar.example.com.' } + end +end + +# Test 100.51.198.in-addr.arpa zonefile +control 'File ' + zones_directory + '/100.51.198.in-addr.arpa' do + title 'should exist' + describe file(zones_directory + '/100.51.198.in-addr.arpa') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Match SOA + its('content') { should match /^@\ IN\ SOA\ ns1.example.net\ hostmaster.example.net\ \(\n\ \ \ \ [0-9]{10}\ ;\ serial\n\ \ \ \ 12h\ ;\ refresh\n\ \ \ \ 600\ ;\ retry\n\ \ \ \ 2w\ ;\ expiry\n\ \ \ \ 1m\ ;\ nxdomain\ ttl\n\);/ } + # Match Include + its('content') { should match /^\$INCLUDE\ #{zones_directory}\/100\.51\.198\.in-addr\.arpa\.include$/ } + end +end + +# Test 100.51.198.in-addr.arpa.include zonefile +control 'File ' + zones_directory + '/100.51.198.in-addr.arpa.include' do + title 'should exist' + describe file(zones_directory + '/100.51.198.in-addr.arpa.include') do + its('owner') { should eq conf_user } + its('group') { should eq conf_group } + its('mode') { should cmp '0644' } + # Match PTR + its('content') { should match '1.100.51.198.in-addr.arpa. PTR ns1.example.net.' } + its('content') { should match '2.100.51.198.in-addr.arpa. PTR foo.example.net.' } + its('content') { should match '3.100.51.198.in-addr.arpa. PTR bar.example.net.' } + its('content') { should match '4.100.51.198.in-addr.arpa. PTR baz.example.net.' } + its('content') { should match '5.100.51.198.in-addr.arpa. PTR mx1.example.net.' } + its('content') { should match '6.100.51.198.in-addr.arpa. PTR mx1.example.net.' } + its('content') { should match '7.100.51.198.in-addr.arpa. PTR mx1.example.net.' } + end +end +