From 29e46c42d0ed6cb4945912a313eab5f8cf85930f Mon Sep 17 00:00:00 2001 From: Armin Pech Date: Wed, 1 Jan 2020 15:01:56 +0100 Subject: [PATCH] Support DNSSEC single type signing scheme without ZSK --- Gemfile | 1 + README.md | 2 ++ files/dnssec-init | 12 +++++++++--- manifests/zone.pp | 3 ++- .../files/zones/example.com/example.com.zone | 9 +++++++++ spec/integration/dnssec-init_spec.rb | 16 ++++++++++++++++ spec/spec_helper.rb | 2 ++ templates/zone.conf.erb | 3 +++ 8 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 spec/fixtures/files/zones/example.com/example.com.zone create mode 100644 spec/integration/dnssec-init_spec.rb diff --git a/Gemfile b/Gemfile index b0ebba2..6f6be9a 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,7 @@ group :test do gem "rspec", '> 3.4.0' gem "rspec-puppet" gem "rspec-puppet-facts" + gem "rspec-command" gem 'rubocop', '> 0.47.0', '< 0.49.0' gem 'simplecov', '>= 0.11.0' gem 'simplecov-console' diff --git a/README.md b/README.md index ee505b2..4289b93 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,8 @@ bind::zone { 'example.com-external': } ``` +Set parameter `dnssec_ksk_only => true` if a DNSSEC zone should only be signed with a key signing key and no zone signing key should be created. + A master zone which is initialized with a pre-existing zone file (for example, to migrate an existing zone to a bind-module controlled server or to recover from a backup): diff --git a/files/dnssec-init b/files/dnssec-init index 73da6b1..e214ac1 100644 --- a/files/dnssec-init +++ b/files/dnssec-init @@ -7,13 +7,19 @@ KEY_DIRECTORY="${4:-${CACHEDIR}/${NAME}}" RANDOM_DEVICE="$5" NSEC3_SALT="$6" ZONE_FILE="$7" +DNSSEC_KSK_ONLY="$8" PATH=/bin:/sbin:/usr/bin:/usr/sbin -dnssec-keygen -a RSASHA256 -b 1024 -r "${RANDOM_DEVICE}" -K "${KEY_DIRECTORY}" "${DOMAIN}" +if [ "$DNSSEC_KSK_ONLY" != "true" ]; then + dnssec-keygen -a RSASHA256 -b 1024 -r "${RANDOM_DEVICE}" -K "${KEY_DIRECTORY}" "${DOMAIN}" +fi dnssec-keygen -a RSASHA256 -b 2048 -r "${RANDOM_DEVICE}" -f KSK -K "${KEY_DIRECTORY}" "${DOMAIN}" +if [ "$DNSSEC_KSK_ONLY" ]; then + DNSSEC_KSK_ONLY_SIGN_OPTIONS="-z" +fi if [ "$NSEC3_SALT" != '' ]; then - dnssec-signzone -S -u -3 "${NSEC3_SALT}" -d "${CACHEDIR}" -K "${KEY_DIRECTORY}" -o "${DOMAIN}" "${CACHEDIR}/${NAME}/${ZONE_FILE}" + dnssec-signzone -S ${DNSSEC_KSK_ONLY_SIGN_OPTIONS} -u -3 "${NSEC3_SALT}" -d "${CACHEDIR}" -K "${KEY_DIRECTORY}" -o "${DOMAIN}" "${CACHEDIR}/${NAME}/${ZONE_FILE}" else - dnssec-signzone -S -d "${CACHEDIR}" -K "${KEY_DIRECTORY}" -o "${DOMAIN}" "${CACHEDIR}/${NAME}/${ZONE_FILE}" + dnssec-signzone -S ${DNSSEC_KSK_ONLY_SIGN_OPTIONS} -d "${CACHEDIR}" -K "${KEY_DIRECTORY}" -o "${DOMAIN}" "${CACHEDIR}/${NAME}/${ZONE_FILE}" fi diff --git a/manifests/zone.pp b/manifests/zone.pp index dd51ecf..c3cadbd 100644 --- a/manifests/zone.pp +++ b/manifests/zone.pp @@ -11,6 +11,7 @@ $update_policies = '', $allow_transfers = '', $dnssec = false, + Boolean $dnssec_ksk_only = false, $nsec3_salt = '', $key_directory = '', $ns_notify = true, @@ -131,7 +132,7 @@ exec { "dnssec-keygen-${name}": command => "/usr/local/bin/dnssec-init '${cachedir}' '${name}'\ '${_domain}' '${key_directory}' '${random_device}' '${nsec3_salt}'\ - '${zone_file}'", + '${zone_file}' '${dnssec_ksk_only}'", cwd => $cachedir, user => $bind_user, creates => "${cachedir}/${name}/${zone_file}.signed", diff --git a/spec/fixtures/files/zones/example.com/example.com.zone b/spec/fixtures/files/zones/example.com/example.com.zone new file mode 100644 index 0000000..4c318fe --- /dev/null +++ b/spec/fixtures/files/zones/example.com/example.com.zone @@ -0,0 +1,9 @@ +$TTL 86400 +@ IN SOA localhost. root.localhost. ( + 1 ; Serial + 60 ; Refresh + 30 ; Retry + 300 ; Expire + 10 ) ; Negative Cache TTL +; +@ IN NS example.com. diff --git a/spec/integration/dnssec-init_spec.rb b/spec/integration/dnssec-init_spec.rb new file mode 100644 index 0000000..90fef16 --- /dev/null +++ b/spec/integration/dnssec-init_spec.rb @@ -0,0 +1,16 @@ +# ex: syntax=ruby ts=2 sw=2 si et +require 'spec_helper' + +describe 'dnssec-init should create RSASHA256 KSK and ZSK' do + fixture_file '../../files/dnssec-init' + fixture_file 'files/zones' + command '/bin/sh dnssec-init . example.com example.com . /dev/urandom 12345678 example.com.zone' + its(:stdout) { is_expected.to match(/^Kexample\.com\.\+008\+[0-9]+\nKexample\.com\.\+008\+[0-9]+\n\.\/example\.com\/example\.com\.zone\.signed$/m) } +end + +describe 'dnssec-init should create RSASHA256 KSK only' do + fixture_file '../../files/dnssec-init' + fixture_file 'files/zones' + command '/bin/sh dnssec-init . example.com example.com . /dev/urandom 12345678 example.com.zone true' + its(:stdout) { is_expected.to match(/^Kexample\.com\.\+008\+[0-9]+\n\.\/example\.com\/example\.com\.zone\.signed$/m) } +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 74dac10..b75ffce 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,10 +1,12 @@ require 'puppetlabs_spec_helper/module_spec_helper' require 'rspec-puppet-facts' require 'rspec-puppet' +require 'rspec_command' include RspecPuppetFacts RSpec.configure do |c| + c.include RSpecCommand c.hiera_config = File.expand_path(File.join(__FILE__, '../fixtures/hiera.yaml')) c.after(:suite) do RSpec::Puppet::Coverage.report! diff --git a/templates/zone.conf.erb b/templates/zone.conf.erb index 8a36dd7..f7c63d4 100644 --- a/templates/zone.conf.erb +++ b/templates/zone.conf.erb @@ -4,6 +4,9 @@ zone "<%= @_domain %>" { type <%= @zone_type %>; <%- if @dnssec -%> auto-dnssec maintain; +<%- if @dnssec_ksk_only -%> + update-check-ksk no; +<%- end -%> <%- if @key_directory and @key_directory != '' -%> key-directory "<%= @key_directory %>"; <%- else -%>