From a41f79817946ea2b0e5a5c0bd00773fb4cb47a5f Mon Sep 17 00:00:00 2001 From: jbond Date: Fri, 17 Jan 2025 16:36:01 +0100 Subject: [PATCH] dnstap: add new class to add dnstap configuration --- REFERENCE.md | 190 ++++++++++++++++++++++++++++++++++++ manifests/dnstap.pp | 104 ++++++++++++++++++++ spec/classes/dnstap_spec.rb | 123 +++++++++++++++++++++++ 3 files changed, 417 insertions(+) create mode 100644 manifests/dnstap.pp create mode 100644 spec/classes/dnstap_spec.rb diff --git a/REFERENCE.md b/REFERENCE.md index 369920a..48382bd 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -7,6 +7,7 @@ ### Classes * [`unbound`](#unbound): Installs and configures Unbound, the caching DNS resolver from NLnet Labs +* [`unbound::dnstap`](#unbound--dnstap) * [`unbound::remote`](#unbound--remote): Configure remote control of the unbound daemon process ### Defined types @@ -1920,6 +1921,195 @@ specifying reduces the number of puppet runs Default value: `$facts['unbound_version']` +### `unbound::dnstap` + +The unbound::dnstap class. + +#### Parameters + +The following parameters are available in the `unbound::dnstap` class: + +* [`enable`](#-unbound--dnstap--enable) +* [`bidirectional`](#-unbound--dnstap--bidirectional) +* [`socket_path`](#-unbound--dnstap--socket_path) +* [`ip`](#-unbound--dnstap--ip) +* [`tls`](#-unbound--dnstap--tls) +* [`tls_host`](#-unbound--dnstap--tls_host) +* [`tls_cert_bundle`](#-unbound--dnstap--tls_cert_bundle) +* [`tls_cert_key_file`](#-unbound--dnstap--tls_cert_key_file) +* [`tls_cert_cert_file`](#-unbound--dnstap--tls_cert_cert_file) +* [`send_identity`](#-unbound--dnstap--send_identity) +* [`send_version`](#-unbound--dnstap--send_version) +* [`identity`](#-unbound--dnstap--identity) +* [`version`](#-unbound--dnstap--version) +* [`sample_rate`](#-unbound--dnstap--sample_rate) +* [`log_resolver_query_messages`](#-unbound--dnstap--log_resolver_query_messages) +* [`log_resolver_response_messages`](#-unbound--dnstap--log_resolver_response_messages) +* [`log_client_query_messages`](#-unbound--dnstap--log_client_query_messages) +* [`log_client_response_messages`](#-unbound--dnstap--log_client_response_messages) +* [`log_forwarder_query_messages`](#-unbound--dnstap--log_forwarder_query_messages) +* [`log_forwarder_response_messages`](#-unbound--dnstap--log_forwarder_response_messages) + +##### `enable` + +Data type: `Boolean` + +Whether to enable dnstap. + +Default value: `true` + +##### `bidirectional` + +Data type: `Boolean` + +Whether to enable bidirectional dnstap. + +Default value: `true` + +##### `socket_path` + +Data type: `Optional[Stdlib::Absolutepath]` + +The path to the dnstap socket. + +Default value: `undef` + +##### `ip` + +Data type: `Optional[Unbound::Address]` + +The IP address for dnstap. + +Default value: `undef` + +##### `tls` + +Data type: `Boolean` + +Whether to enable TLS for dnstap. + +Default value: `true` + +##### `tls_host` + +Data type: `Optional[Stdlib::Host]` + +The TLS host for dnstap. + +Default value: `undef` + +##### `tls_cert_bundle` + +Data type: `Optional[Stdlib::Absolutepath]` + +The path to the TLS certificate bundle. + +Default value: `undef` + +##### `tls_cert_key_file` + +Data type: `Optional[Stdlib::Absolutepath]` + +The path to the TLS certificate key file. + +Default value: `undef` + +##### `tls_cert_cert_file` + +Data type: `Optional[Stdlib::Absolutepath]` + +The path to the TLS certificate file. + +Default value: `undef` + +##### `send_identity` + +Data type: `Boolean` + +Whether to send the identity in dnstap messages. + +Default value: `false` + +##### `send_version` + +Data type: `Boolean` + +Whether to send the version in dnstap messages. + +Default value: `false` + +##### `identity` + +Data type: `Optional[String[1]]` + +The identity to send in dnstap messages. + +Default value: `undef` + +##### `version` + +Data type: `Optional[String[1]]` + +The version to send in dnstap messages. + +Default value: `undef` + +##### `sample_rate` + +Data type: `Integer[0,1000]` + +The sample rate for dnstap messages. + +Default value: `0` + +##### `log_resolver_query_messages` + +Data type: `Boolean` + +Whether to log resolver query messages. + +Default value: `false` + +##### `log_resolver_response_messages` + +Data type: `Boolean` + +Whether to log resolver response messages. + +Default value: `false` + +##### `log_client_query_messages` + +Data type: `Boolean` + +Whether to log client query messages. + +Default value: `false` + +##### `log_client_response_messages` + +Data type: `Boolean` + +Whether to log client response messages. + +Default value: `false` + +##### `log_forwarder_query_messages` + +Data type: `Boolean` + +Whether to log forwarder query messages. + +Default value: `false` + +##### `log_forwarder_response_messages` + +Data type: `Boolean` + +Whether to log forwarder response messages. + +Default value: `false` + ### `unbound::remote` Configure remote control of the unbound daemon process diff --git a/manifests/dnstap.pp b/manifests/dnstap.pp new file mode 100644 index 0000000..5ec6da7 --- /dev/null +++ b/manifests/dnstap.pp @@ -0,0 +1,104 @@ +# @summary +# @param enable +# Whether to enable dnstap. +# @param bidirectional +# Whether to enable bidirectional dnstap. +# @param socket_path +# The path to the dnstap socket. +# @param ip +# The IP address for dnstap. +# @param tls +# Whether to enable TLS for dnstap. +# @param tls_host +# The TLS host for dnstap. +# @param tls_cert_bundle +# The path to the TLS certificate bundle. +# @param tls_cert_key_file +# The path to the TLS certificate key file. +# @param tls_cert_cert_file +# The path to the TLS certificate file. +# @param send_identity +# Whether to send the identity in dnstap messages. +# @param send_version +# Whether to send the version in dnstap messages. +# @param identity +# The identity to send in dnstap messages. +# @param version +# The version to send in dnstap messages. +# @param sample_rate +# The sample rate for dnstap messages. +# @param log_resolver_query_messages +# Whether to log resolver query messages. +# @param log_resolver_response_messages +# Whether to log resolver response messages. +# @param log_client_query_messages +# Whether to log client query messages. +# @param log_client_response_messages +# Whether to log client response messages. +# @param log_forwarder_query_messages +# Whether to log forwarder query messages. +# @param log_forwarder_response_messages +# Whether to log forwarder response messages. +class unbound::dnstap ( + Boolean $enable = true, # version 1.11 + Boolean $bidirectional = true, # version 1.11 + Optional[Stdlib::Absolutepath] $socket_path = undef, # version 1.11 + Optional[Unbound::Address] $ip = undef, # version 1.11 + Boolean $tls = true, # version 1.11 + Optional[Stdlib::Host] $tls_host = undef, # version 1.11 + Optional[Stdlib::Absolutepath] $tls_cert_bundle = undef, # version 1.11 + Optional[Stdlib::Absolutepath] $tls_cert_key_file = undef, # version 1.11 + Optional[Stdlib::Absolutepath] $tls_cert_cert_file = undef, # version 1.11 + Boolean $send_identity = false, # version 1.11 + Boolean $send_version = false, # version 1.11 + Optional[String[1]] $identity = undef, # version 1.11 + Optional[String[1]] $version = undef, # version 1.11 + Integer[0,1000] $sample_rate = 0, # version 1.21 + Boolean $log_resolver_query_messages = false, # version 1.11 + Boolean $log_resolver_response_messages = false, # version 1.11 + Boolean $log_client_query_messages = false, # version 1.11 + Boolean $log_client_response_messages = false, # version 1.11 + Boolean $log_forwarder_query_messages = false, # version 1.11 + Boolean $log_forwarder_response_messages = false, # version 1.11 + +) { + include unbound + if $enable and $socket_path == undef and $ip == undef { + fail('Either ip or socket_path is required when dnstap is enabled') + } + if $enable { + $ip_config = $ip.then |$v| { + @("CONFIG") + ${unbound::print_config('dnstap-ip', $v, '1.11')} + ${unbound::print_config('dnstap-tls', $tls, '1.11')} + ${unbound::print_config('dnstap-tls-host', $tls_host, '1.11')} + ${unbound::print_config('dnstap-tls-cert-bundle', $tls_cert_bundle, '1.11')} + ${unbound::print_config('dnstap-tls-cert-key-file', $tls_cert_key_file, '1.11')} + ${unbound::print_config('dnstap-tls-cert-cert-file', $tls_cert_cert_file, '1.11')} + | CONFIG + } + $config = @("CONFIG") + dnstap: + ${unbound::print_config('dnstap-enable', $enable, '1.11')} + ${unbound::print_config('dnstap-bidirectional', $bidirectional, '1.11')} + ${unbound::print_config('dnstap-socket-path', $socket_path, '1.11')} + ${$ip_config} + ${unbound::print_config('dnstap-send-identity', $send_identity, '1.11')} + ${unbound::print_config('dnstap-send-version', $send_version, '1.11')} + ${unbound::print_config('dnstap-identity', $identity, '1.11')} + ${unbound::print_config('dnstap-version', $version, '1.11')} + ${unbound::print_config('dnstap-sample-rate', $sample_rate, '1.21')} + ${unbound::print_config('dnstap-log-resolver-query-messages', $log_resolver_query_messages, '1.11')} + ${unbound::print_config('dnstap-log-resolver-response-messages', $log_resolver_response_messages, '1.11')} + ${unbound::print_config('dnstap-log-client-query-messages', $log_client_query_messages, '1.11')} + ${unbound::print_config('dnstap-log-client-response-messages', $log_client_response_messages, '1.11')} + ${unbound::print_config('dnstap-log-forwarder-query-messages', $log_forwarder_query_messages, '1.11')} + ${unbound::print_config('dnstap-log-forwarder-response-messages', $log_forwarder_response_messages, '1.11')} + | CONFIG + concat::fragment { 'unbound-dnstap': + order => '20', + target => $unbound::config_file, + content => $config.split("\n").filter |$x| { !$x.empty }.join("\n"), + } + } +} diff --git a/spec/classes/dnstap_spec.rb b/spec/classes/dnstap_spec.rb new file mode 100644 index 0000000..4bb7451 --- /dev/null +++ b/spec/classes/dnstap_spec.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'unbound::dnstap' do + on_supported_os.each do |os, facts| + context "on #{os}" do + let(:facts) { facts.merge(concat_basedir: '/dne', unbound_version: '1.21.0') } + + case facts[:os]['family'] + when 'FreeBSD' + let(:config_file) { '/usr/local/etc/unbound/unbound.conf' } + when 'OpenBSD' + let(:config_file) { '/var/unbound/etc/unbound.conf' } + else + let(:config_file) { '/etc/unbound/unbound.conf' } + end + + context 'with disabled params' do + let(:params) { { enable: false } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('unbound::dnstap') } + it { is_expected.not_to contain_concat__fragment('unbound-dnstap') } + end + + context 'with enable and socket' do + let(:params) { { socket_path: '/var/run/dnstap.sock' } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('unbound::dnstap') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{ + ^dnstap: + \s+dnstap-enable:\syes + \s+dnstap-bidirectional:\syes + \s+dnstap-socket-path:\s"/var/run/dnstap.sock" + \s+dnstap-send-identity:\sno + \s+dnstap-send-version:\sno + \s+dnstap-sample-rate:\s0 + \s+dnstap-log-resolver-query-messages:\sno + \s+dnstap-log-resolver-response-messages:\sno + \s+dnstap-log-client-query-messages:\sno + \s+dnstap-log-client-response-messages:\sno + \s+dnstap-log-forwarder-query-messages:\sno + \s+dnstap-log-forwarder-response-messages:\sno + }x + ) + end + end + + context 'with enable and ip' do + let(:params) { { ip: '192.0.2.1' } } + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('unbound::dnstap') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{ + ^dnstap: + \s+dnstap-enable:\syes + \s+dnstap-bidirectional:\syes + \s+dnstap-ip:\s"192\.0\.2\.1" + \s+dnstap-tls:\syes + \s+dnstap-send-identity:\sno + \s+dnstap-send-version:\sno + \s+dnstap-sample-rate:\s0 + \s+dnstap-log-resolver-query-messages:\sno + \s+dnstap-log-resolver-response-messages:\sno + \s+dnstap-log-client-query-messages:\sno + \s+dnstap-log-client-response-messages:\sno + \s+dnstap-log-forwarder-query-messages:\sno + \s+dnstap-log-forwarder-response-messages:\sno + }x + ) + end + + context 'with tls_host' do + let(:params) { super().merge(tls_host: 'dnstap.example.com') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{^ dnstap-tls-host:\s"dnstap.example.com"} + ) + end + end + + context 'with tls_cert_bundle' do + let(:params) { super().merge(tls_cert_bundle: '/etc/ssl/cert.pem') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{^ dnstap-tls-cert-bundle:\s"/etc/ssl/cert.pem"} + ) + end + end + + context 'with tls_cert_key_file' do + let(:params) { super().merge(tls_cert_key_file: '/etc/ssl/key.pem') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{^ dnstap-tls-cert-key-file:\s"/etc/ssl/key.pem"} + ) + end + end + + context 'with tls_cert_cert_file' do + let(:params) { super().merge(tls_cert_cert_file: '/etc/ssl/cert.pem') } + + it do + is_expected.to contain_concat__fragment('unbound-dnstap').with_content( + %r{^ dnstap-tls-cert-cert-file:\s"/etc/ssl/cert.pem"} + ) + end + end + end + end + end +end