diff --git a/data/common.yaml b/data/common.yaml index b524673..2220e5c 100644 --- a/data/common.yaml +++ b/data/common.yaml @@ -1,6 +1,7 @@ --- bind::defaults::supported: false bind::defaults::chroot_supported: false +bind::defaults::chroot_class: '' bind::defaults::random_device: '/dev/random' bind::forwarders: '' diff --git a/data/osfamily/Debian-8.yaml b/data/osfamily/Debian-8.yaml new file mode 100644 index 0000000..7fbcef1 --- /dev/null +++ b/data/osfamily/Debian-8.yaml @@ -0,0 +1 @@ +bind::defaults::chroot_supported: true diff --git a/data/osfamily/Debian-9.yaml b/data/osfamily/Debian-9.yaml new file mode 100644 index 0000000..7fbcef1 --- /dev/null +++ b/data/osfamily/Debian-9.yaml @@ -0,0 +1 @@ +bind::defaults::chroot_supported: true diff --git a/data/osfamily/Debian.yaml b/data/osfamily/Debian.yaml index 1e2f348..3fe117b 100644 --- a/data/osfamily/Debian.yaml +++ b/data/osfamily/Debian.yaml @@ -12,5 +12,7 @@ bind::defaults::logdir: '/var/log/bind' bind::defaults::default_zones_include: '/etc/bind/named.conf.default-zones' bind::defaults::isc_bind_keys: '/etc/bind/bind.keys' +bind::defaults::chroot_dir: '/var/bind9/chroot' +bind::defaults::chroot_class: bind::chroot::manual + bind::updater::keydir: '/etc/bind/keys' -bind::defaults::bind_chroot_dir: '/var/lib/named/chroot' diff --git a/data/osfamily/RedHat.yaml b/data/osfamily/RedHat.yaml index df02b12..31aa4b4 100644 --- a/data/osfamily/RedHat.yaml +++ b/data/osfamily/RedHat.yaml @@ -14,8 +14,9 @@ bind::defaults::default_zones_include: '/etc/named.default-zones.conf' bind::defaults::default_zones_source: 'puppet:///modules/bind/RedHat/named.default-zones.conf' bind::defaults::isc_bind_keys: '/etc/named.iscdlv.key' -bind::defaults::bind_chroot_package: 'bind-chroot' -bind::defaults::bind_chroot_service: 'named-chroot' -bind::defaults::bind_chroot_dir: '/var/named/chroot' +# XXX bind::defaults::chroot_package: 'bind-chroot' +# XXX bind::defaults::chroot_service: 'named-chroot' +# XXX bind::defaults::chroot_dir: '/var/named/chroot' +bind::defaults::chroot_class: bind::chroot::package bind::updater::keydir: '/etc/named/keys' diff --git a/examples/chroot.pp b/examples/chroot.pp new file mode 100644 index 0000000..cf50fec --- /dev/null +++ b/examples/chroot.pp @@ -0,0 +1,13 @@ +class { 'bind': + chroot => true, + # Note: this file MUST be into the /etc/named directory so the + # RHEL7 specific setup-named-chroot.sh script will make it available into + # the chroot. + default_zones_include => '/etc/named/default-zones.conf', + forwarders => [ + '8.8.8.8', + '8.8.4.4', + ], + dnssec => true, + version => 'Controlled by Puppet', +} diff --git a/manifests/chroot/manual.pp b/manifests/chroot/manual.pp new file mode 100644 index 0000000..3e97d18 --- /dev/null +++ b/manifests/chroot/manual.pp @@ -0,0 +1,60 @@ +class bind::chroot::manual( + $chroot_dir = $::bind::defaults::chroot_dir, +) inherits bind::defaults { + exec { 'mkdir-p-$chroot_dir': + command => "mkdir -p ${::bind::defaults::chroot_dir}", + path => ['/bin', '/usr/bin'], + unless => "test -d ${::bind::defaults::chroot_dir}", + } + # Creating system dirs under chroot dir: + file { ["${::bind::defaults::chroot_dir}", + "${::bind::defaults::chroot_dir}/etc", + "${::bind::defaults::chroot_dir}/dev", + "${::bind::defaults::chroot_dir}/var", + "${::bind::defaults::chroot_dir}/var/cache", + "${::bind::defaults::chroot_dir}/var/run"]: + ensure => directory, + mode => '0660', + require => Exec['mkdir-p-$chroot_dir'], + } + + file { ["${::bind::defaults::chroot_dir}/var/cache/bind", + "${::bind::defaults::chroot_dir}/var/run/named"]: + ensure => directory, + mode => '0775', + group => $::bind::defaults::bind_group, + require => Exec['mkdir-p-$chroot_dir'], + } + + exec { 'mknod-dev-null': + command => "mknod ${::bind::defaults::chroot_dir}/dev/null c 1 3", + path => ['/bin', '/usr/bin'], + unless => "test -d ${::bind::defaults::chroot_dir}/dev/null", + } + exec { 'mknod-dev-random': + command => "mknod ${::bind::defaults::chroot_dir}/dev/random c 1 8", + path => ['/bin', '/usr/bin'], + unless => "test -d ${::bind::defaults::chroot_dir}/dev/random", + } + exec { 'mknod-dev-urandom': + command => "mknod ${::bind::defaults::chroot_dir}/dev/urandom c 1 9", + path => ['/bin', '/usr/bin'], + unless => "test -d ${::bind::defaults::chroot_dir}/dev/urandom", + } + file { [ "${::bind::defaults::chroot_dir}/dev/null", + "${::bind::defaults::chroot_dir}/dev/random", + "${::bind::defaults::chroot_dir}/dev/urandom"]: + mode => '0660', + require => [ Exec['mknod-dev-null'], Exec['mknod-dev-random'], Exec['mknod-dev-urandom'] ], + } + exec { 'mv-etc-bind-into-jailed-etc': + command => "mv ${::bind::defaults::confdir} ${::bind::defaults::chroot_dir}", + path => ['/bin', '/usr/bin'], + unless => "test -d ${::bind::defaults::chroot_dir}${::bind::defaults::confdir}", + require => [ File["${::bind::defaults::chroot_dir}/etc"] ] + } + #-> file { '/etc/bind': + # ensure => link, + # target => "${::bind::defaults::chroot_dir}/${::bind::defaults::confdir}", + #} +} diff --git a/manifests/chroot/package.pp b/manifests/chroot/package.pp new file mode 100644 index 0000000..fc3e38f --- /dev/null +++ b/manifests/chroot/package.pp @@ -0,0 +1,21 @@ +class bind::chroot::package( + $chroot_dir = $::bind::defaults::chroot_dir, +) inherits bind::defaults { + package { 'bind-chroot': + ensure => latest, + } + service { 'bind': + ensure => running, + name => 'named-chroot', + enable => true, + hasrestart => true, + hasstatus => true, + } + # On RHEL Family, there is a dedicated service named-chroot and we need + # to stop/disable 'named' service: + service { 'bind-without-chroot': + ensure => stopped, + name => $::bind::defaults::bind_service, + enable => false, + } +} diff --git a/manifests/defaults.pp b/manifests/defaults.pp index 8916d34..1001242 100644 --- a/manifests/defaults.pp +++ b/manifests/defaults.pp @@ -17,9 +17,13 @@ class bind::defaults ( $bind_chroot_dir = undef, $nsupdate_package = undef, $managed_keys_directory = undef, + # NOTE: we need to be able to override this parameter when declaring class, + # especially when not using hiera (i.e. when using Foreman as ENC): $default_zones_include = undef, $default_zones_source = undef, $isc_bind_keys = undef, + $chroot_class = undef, + $chroot_dir = undef, ) { unless is_bool($supported) { fail('Please ensure that the dependencies of the bind module are installed and working correctly') diff --git a/manifests/init.pp b/manifests/init.pp index b26091f..7681819 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,40 +1,27 @@ # ex: syntax=puppet si ts=4 sw=4 et class bind ( - $forwarders = undef, - $forward = undef, - $dnssec = undef, - $filter_ipv6 = undef, - $version = undef, - $statistics_port = undef, - $auth_nxdomain = undef, - $include_default_zones = true, - $include_local = false, - $tkey_gssapi_credential = undef, - $tkey_domain = undef, - $chroot = false, - $chroot_supported = $::bind::defaults::chroot_supported, - $chroot_dir = $::bind::defaults::bind_chroot_dir, + $forwarders = undef, + $forward = undef, + $dnssec = undef, + $filter_ipv6 = undef, + $version = undef, + $statistics_port = undef, + $auth_nxdomain = undef, + $include_default_zones = true, + $include_local = false, + $tkey_gssapi_credential = undef, + $tkey_domain = undef, + $chroot = false, + $chroot_class = $::bind::defaults::chroot_class, + $chroot_dir = $::bind::defaults::chroot_dir, # NOTE: we need to be able to override this parameter when declaring class, # especially when not using hiera (i.e. when using Foreman as ENC): - $default_zones_include = $::bind::defaults::default_zones_include, + $default_zones_include = $::bind::defaults::default_zones_include, ) inherits bind::defaults { if $chroot and !$chroot_supported { fail('Chroot for bind is not supported on your OS') } - - if $chroot { - if $::bind::defaults::bind_chroot_service { - $real_bind_service = $::bind::defaults::bind_chroot_service - } - if $::bind::defaults::bind_chroot_package { - $real_bind_package = $::bind::defaults::bind_chroot_package - } - } else { - $real_bind_service = $::bind::defaults::bind_service - $real_bind_package = $::bind::defaults::bind_package - } - File { ensure => present, owner => 'root', @@ -48,7 +35,7 @@ class bind ( package { 'bind': ensure => latest, - name => $real_bind_package, + name => $::bind::defaults::bind_package, } if $dnssec { @@ -126,23 +113,14 @@ class bind ( content => "};\n"; } - if $chroot and $::bind::defaults::bind_chroot_service { - service { 'bind': - ensure => running, - name => $::bind::defaults::bind_chroot_service, - enable => true, - hasrestart => true, - hasstatus => true, - } - # On RHEL Family, there is a dedicated service named-chroot and we need - # to stop/disable 'named' service: - service { 'bind-no-chroot': - ensure => stopped, - name => $::bind::defaults::bind_service, - enable => false, - } - - } else { + if $chroot and $::bind::defaults::chroot_class { + # When using a dedicated chroot class, service declaration is dedicated to this class + class { $::bind::defaults::chroot_class : } + } + # DO NOT declare a bind service when chrooting bind with bind::chroot::package class, + # because it needs another dedicated chrooted-bind service (i.e. named-chroot on RHEL) + # AND it also needs $::bind::defaults::bind_service being STOPPED and DISABLED. + if !$chroot or ($chroot and $::bind::defaults::chroot_class == 'bind::chroot::manual') { service { 'bind': ensure => running, name => $::bind::defaults::bind_service, diff --git a/metadata.json b/metadata.json index 3278a28..42c721d 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "inkblot-bind", - "version": "7.3.1", + "version": "7.3.1-chroot", "author": "inkblot", "license": "Apache-2.0", "summary": "ISC BIND name server", @@ -11,7 +11,7 @@ "operatingsystem_support": [ { "operatingsystem": "Debian", - "operatingsystemrelease": [ "7.7" ] + "operatingsystemrelease": [ "7", "8", "9"] }, { "operatingsystem": "Ubuntu", diff --git a/spec/classes/bind_spec.rb b/spec/classes/bind_spec.rb index 24a31ca..adf3450 100644 --- a/spec/classes/bind_spec.rb +++ b/spec/classes/bind_spec.rb @@ -9,16 +9,12 @@ describe 'bind' do when 'Debian' expected_bind_pkg = 'bind9' expected_bind_service = 'bind9' - expected_bind_chroot_pkg = nil - expected_bind_chroot_service = nil expected_named_conf = '/etc/bind/named.conf' expected_confdir = '/etc/bind' expected_default_zones_include= '/etc/bind/named.conf.default-zones' when 'RedHat' expected_bind_pkg = 'bind' expected_bind_service = 'named' - expected_bind_chroot_pkg = 'bind-chroot' - expected_bind_chroot_service = 'named-chroot' expected_named_conf = '/etc/named.conf' expected_confdir = '/etc/named' expected_default_zones_include= '/etc/named.default-zones.conf' @@ -96,21 +92,20 @@ describe 'bind' do default_zones_include: '/etc/named/default-zones.conf' } end - if not (facts[:os]['name'] == 'CentOS' && facts[:os]['release']['major'] == '7') + + + if not (facts[:os]['name'] == 'CentOS' && facts[:os]['release']['major'] == '7' or + facts[:os]['name'] == 'Debian' && facts[:os]['release']['major'].to_i >= 8) it { is_expected.to compile.and_raise_error(/Chroot for bind is not supported on your OS/) } else + # Generic chroot part: it { is_expected.to compile.with_all_deps } it { is_expected.to contain_class('bind::defaults') } it { is_expected.to contain_class('bind::keydir') } it { is_expected.to contain_class('bind::updater') } it { is_expected.to contain_class('bind') } it { is_expected.to compile.with_all_deps } - it do - is_expected.to contain_package('bind').with({ - ensure: 'latest', - name: expected_bind_chroot_pkg - }) - end + it { is_expected.to contain_package('bind').with({ ensure: 'latest', }) } it { is_expected.to contain_file('/usr/local/bin/dnssec-init') } it do is_expected.to contain_bind__key('rndc-key').with( @@ -153,19 +148,13 @@ describe 'bind' do end it { is_expected.to contain_file(expected_named_conf).that_requires('Package[bind]') } it { is_expected.to contain_file(expected_named_conf).that_notifies('Service[bind]') } - it do - is_expected.to contain_service('bind-no-chroot').with({ - ensure: 'stopped', - enable: false, - name: expected_bind_service - }) - end - it do - is_expected.to contain_service('bind').with({ - ensure: 'running', - enable: true, - name: expected_bind_chroot_service - }) + + + # OS family specific chroot setup: + if (facts[:os]['family'] == 'Debian') + it { is_expected.to contain_class('bind::chroot::manual') } + elsif (facts[:os]['family'] == 'RedHat') + it { is_expected.to contain_class('bind::chroot::package') } end end end diff --git a/spec/classes/chroot/manual_spec.rb b/spec/classes/chroot/manual_spec.rb new file mode 100644 index 0000000..379a424 --- /dev/null +++ b/spec/classes/chroot/manual_spec.rb @@ -0,0 +1,16 @@ +# ex: syntax=ruby ts=2 sw=2 si et +require 'spec_helper' + +describe 'bind::chroot::manual' do + on_supported_os.each do |os, facts| + context "on #{os}" do + # Only applies to Debian Family for now: + next unless facts[:os]['family'] == 'Debian' + let (:facts) {facts} + context "with defaults parameters" do + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('bind::defaults') } + end + end + end +end diff --git a/spec/classes/chroot/package_spec.rb b/spec/classes/chroot/package_spec.rb new file mode 100644 index 0000000..b2ed457 --- /dev/null +++ b/spec/classes/chroot/package_spec.rb @@ -0,0 +1,31 @@ +# ex: syntax=ruby ts=2 sw=2 si et +require 'spec_helper' + +describe 'bind::chroot::package' do + on_supported_os.each do |os, facts| + context "on #{os}" do + # Only applies to RedHat Family for now: + next unless facts[:os]['family'] == 'RedHat' + let (:facts) {facts} + context "with defaults parameters" do + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('bind::defaults') } + it { is_expected.to contain_package('bind-chroot').with({ ensure: 'latest', }) } + it do + is_expected.to contain_service('bind-without-chroot').with({ + ensure: 'stopped', + enable: false, + name: 'named' + }) + end + it do + is_expected.to contain_service('bind').with({ + ensure: 'running', + enable: true, + name: 'named-chroot' + }) + end + end + end + end +end