Set up SpamAssassin

Scan incoming and outgoing email for spam. Use a local Unbound for DNS,
so we don't run into blocks for RBL queries.
This commit is contained in:
Râu Cao
2023-12-06 12:12:00 +01:00
parent 05ccbcc58f
commit b3f2ca415e
40 changed files with 2145 additions and 4 deletions

View File

@@ -0,0 +1,93 @@
#
# Cookbook:: unbound
# Resource:: config_authority_zone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
provides :unbound_config_auth_zone
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/authority-zone-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :zone_name, String,
default: lazy { name }
property :primary, [String, Array],
coerce: proc { |p| Array(p) }
property :master, [String, Array],
coerce: proc { |p| Array(p) }
property :url, [String, Array],
coerce: proc { |p| Array(p) }
property :allow_notify, [String, Array],
coerce: proc { |p| Array(p) }
property :fallback_enabled, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :for_downstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :for_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :zonemd_check, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :zonemd_reject_absence, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :zonefile, String
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'name' => new_resource.zone_name,
'primary' => new_resource.primary.dup,
'master' => new_resource.master.dup,
'url' => new_resource.url.dup,
'allow-notify' => new_resource.allow_notify.dup,
'fallback-enabled' => new_resource.fallback_enabled,
'for-downstream' => new_resource.for_downstream,
'for-upstream' => new_resource.for_upstream,
'zonemd-check' => new_resource.zonemd_check,
'zonemd-reject-absence' => new_resource.zonemd_reject_absence,
'zonefile' => new_resource.zonefile,
}.compact
config = {
'auth-zone' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,67 @@
#
# Cookbook:: unbound
# Resource:: config_cachedb
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/cachedb.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :backend, String
property :secret_seed, String
property :redis_server_host, String
property :redis_server_port, Integer
property :redis_timeout, Integer
property :redis_expire_records, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
cachedb_config = {
'backend' => new_resource.backend,
'secret-seed' => new_resource.secret_seed,
'redis-server-host' => new_resource.redis_server_host,
'redis-server-port' => new_resource.redis_server_port,
'redis-timeout' => new_resource.redis_timeout,
'redis-expire-records' => new_resource.redis_expire_records,
}.compact
config = {
'cachedb' => cachedb_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,58 @@
#
# Cookbook:: unbound
# Resource:: config_dns64
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/dns64.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :dns64_prefix, String
property :dns64_synthall, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dns64_ignore_aaaa, String
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
dns64_config = {
'dns64-prefix' => new_resource.dns64_prefix,
'dns64-synthall' => new_resource.dns64_synthall,
'dns64-ignore-aaaa' => new_resource.dns64_ignore_aaaa,
}.compact
config = {
'server' => dns64_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,80 @@
#
# Cookbook:: unbound
# Resource:: config_dnscrypt
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/dnscrypt.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :dnscrypt_enable, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnscrypt_port, Integer
property :dnscrypt_provider, [String, Array],
coerce: proc { |p| Array(p) }
property :dnscrypt_secret_key, String
property :dnscrypt_provider_cert, String
property :dnscrypt_provider_cert_rotated, String
property :dnscrypt_shared_secret_cache_size, String
property :dnscrypt_shared_secret_cache_slabs, Integer
property :dnscrypt_nonce_cache_size, String
property :dnscrypt_nonce_cache_slabs, Integer
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
dnscrypt_config = {
'dnscrypt-enable' => new_resource.dnscrypt_enable,
'dnscrypt-port' => new_resource.dnscrypt_port,
'dnscrypt-provider' => new_resource.dnscrypt_provider.dup,
'dnscrypt-secret-key' => new_resource.dnscrypt_secret_key,
'dnscrypt-provider-cert' => new_resource.dnscrypt_provider_cert,
'dnscrypt-provider-cert-rotated' => new_resource.dnscrypt_provider_cert_rotated,
'dnscrypt-shared-secret-cache-size' => new_resource.dnscrypt_shared_secret_cache_size,
'dnscrypt-shared-secret-cache-slabs' => new_resource.dnscrypt_shared_secret_cache_slabs,
'dnscrypt-nonce-cache-size' => new_resource.dnscrypt_nonce_cache_size,
'dnscrypt-nonce-cache-slabs' => new_resource.dnscrypt_nonce_cache_slabs,
}.compact
config = {
'dnscrypt' => dnscrypt_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,116 @@
#
# Cookbook:: unbound
# Resource:: config_dnstap
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/dnstap.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :dnstap_enable, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_bidirectional, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_socket_path, String
property :dnstap_ip, String
property :dnstap_tls, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_tls_server_name, String
property :dnstap_tls_cert_bundle, String
property :dnstap_tls_client_key_file, String
property :dnstap_tls_client_cert_file, String
property :dnstap_send_identity, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_send_version, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_identity, String
property :dnstap_version, String
property :dnstap_log_resolver_query_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_log_resolver_response_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_log_client_query_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_log_client_response_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_log_forwarder_query_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :dnstap_log_forwarder_response_messages, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'dnstap-enable' => new_resource.dnstap_enable,
'dnstap-bidirectional' => new_resource.dnstap_bidirectional,
'dnstap-socket-path' => new_resource.dnstap_socket_path,
'dnstap-ip' => new_resource.dnstap_ip,
'dnstap-tls' => new_resource.dnstap_tls,
'dnstap-tls-server-name' => new_resource.dnstap_tls_server_name,
'dnstap-tls-cert-bundle' => new_resource.dnstap_tls_cert_bundle,
'dnstap-tls-client-key-file' => new_resource.dnstap_tls_client_key_file,
'dnstap-tls-client-cert-file' => new_resource.dnstap_tls_client_cert_file,
'dnstap-send-identity' => new_resource.dnstap_send_identity,
'dnstap-send-version' => new_resource.dnstap_send_version,
'dnstap-identity' => new_resource.dnstap_identity,
'dnstap-version' => new_resource.dnstap_version,
'dnstap-log-resolver-query-messages' => new_resource.dnstap_log_resolver_query_messages,
'dnstap-log-resolver-response-messages' => new_resource.dnstap_log_resolver_response_messages,
'dnstap-log-client-query-messages' => new_resource.dnstap_log_client_query_messages,
'dnstap-log-client-response-messages' => new_resource.dnstap_log_client_response_messages,
'dnstap-log-forwarder-query-messages' => new_resource.dnstap_log_forwarder_query_messages,
'dnstap-log-forwarder-response-messages' => new_resource.dnstap_log_forwarder_response_messages,
}.compact
config = {
'dnstap' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,48 @@
#
# Cookbook:: unbound
# Resource:: config_dynamic_library
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/dyn-lib-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :dynlib_file, [String, Array],
coerce: proc { |p| Array(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
config = {
'dynlib-file' => new_resource.dynlib_file.dup,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,80 @@
#
# Cookbook:: unbound
# Resource:: config_forward_zone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/forward-zone-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :zone_name, String,
default: lazy { name }
property :forward_host, [String, Array],
coerce: proc { |p| Array(p) }
property :forward_addr, [String, Array],
coerce: proc { |p| Array(p) }
property :forward_first, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :forward_tls_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :forward_ssl_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :forward_tcp_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :forward_no_cache, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'name' => new_resource.zone_name,
'forward-host' => new_resource.forward_host.dup,
'forward-addr' => new_resource.forward_addr.dup,
'forward-first' => new_resource.forward_first,
'forward-tls-upstream' => new_resource.forward_tls_upstream,
'forward-ssl-upstream' => new_resource.forward_ssl_upstream,
'forward-tcp-upstream' => new_resource.forward_tcp_upstream,
'forward-no-cache' => new_resource.forward_no_cache,
}.compact
config = {
'forward-zone' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,53 @@
#
# Cookbook:: unbound
# Resource:: config_python_script
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/python-script-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :python_script, [String, Array],
coerce: proc { |p| Array(p) },
required: true
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
declare_resource(:package, 'python3-unbound')
config = {
'python' => {
'python-script' => new_resource.python_script.dup,
},
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,77 @@
#
# Cookbook:: unbound
# Resource:: config_remote_control
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/remote-control.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :control_enable, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :control_interface, [String, Array],
coerce: proc { |p| Array(p) }
property :control_port, Integer
property :control_use_cert, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :control_key_file, String
property :control_cert_file, String
property :server, String
property :server_key_file, String
property :server_cert_file, String
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
remote_control = {
'control-enable' => new_resource.control_enable,
'control-interface' => new_resource.control_interface.dup,
'control-port' => new_resource.control_port,
'control-use-cert' => new_resource.control_use_cert,
'control-key-file' => new_resource.control_key_file,
'control-cert-file' => new_resource.control_cert_file,
'server-key-file' => new_resource.server_key_file,
'server-cert-file' => new_resource.server_cert_file,
}.compact
config = {
'remote-control' => remote_control,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,98 @@
#
# Cookbook:: unbound
# Resource:: config_rpz_zone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/rpz-zone-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :zone_name, String,
default: lazy { name }
property :primary, [String, Array],
coerce: proc { |p| Array(p) }
property :master, [String, Array],
coerce: proc { |p| Array(p) }
property :url, [String, Array],
coerce: proc { |p| Array(p) }
property :allow_notify, [String, Array],
coerce: proc { |p| Array(p) }
property :zonefile, String
property :rpz_action_override, [String, Symbol],
equal_to: %w(nxdomain nodata passthru drop disabled cname),
coerce: proc { |p| p.to_s }
property :rpz_cname_override, String
property :rpz_log, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :rpz_log_name, String
property :rpz_signal_nxdomain_ra, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :for_downstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :tags, [String, Array],
coerce: proc { |p| "\"#{p.to_a.join(' ')} \"" }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'name' => new_resource.zone_name,
'primary' => new_resource.primary.dup,
'master' => new_resource.master.dup,
'url' => new_resource.url.dup,
'allow-notify' => new_resource.allow_notify.dup,
'zonefile' => new_resource.zonefile,
'rpz-action-override' => new_resource.rpz_action_override,
'rpz-cname-override' => new_resource.rpz_cname_override,
'rpz-log' => new_resource.rpz_log,
'rpz-log-name' => new_resource.rpz_log_name,
'rpz-signal-nxfomain-ra' => new_resource.rpz_signal_nxdomain_ra,
'for-downstream' => new_resource.for_downstream,
'tags' => new_resource.tags.dup,
}.compact
config = {
'rpz' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,58 @@
#
# Cookbook:: unbound
# Resource:: config_server
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
provides :unbound_config_server
provides :unbound_configure
provides :unbound_config
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/unbound.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :include, [String, Array],
default: lazy { default_includes_dir },
coerce: proc { |p| Array(p) }
property :server, Hash,
default: {},
description: 'Server configuration as a Hash'
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
config = {
'include' => new_resource.include.dup,
'server' => new_resource.server.dup,
}.compact
perform_config_action(config)
end
end

View File

@@ -0,0 +1,84 @@
#
# Cookbook:: unbound
# Resource:: config_stub_zone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/stub-zone-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :zone_name, String,
default: lazy { name }
property :stub_host, [String, Array],
coerce: proc { |p| Array(p) }
property :stub_addr, [String, Array],
coerce: proc { |p| Array(p) }
property :stub_prime, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :stub_first, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :stub_tls_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :stub_ssl_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :stub_tcp_upstream, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
property :stub_no_cache, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'name' => new_resource.zone_name,
'stub-host' => new_resource.stub_host.dup,
'stub-addr' => new_resource.stub_addr.dup,
'stub-prime' => new_resource.stub_prime,
'stub-first' => new_resource.stub_first,
'stub-tls-upstream' => new_resource.stub_tls_upstream,
'stub-ssl-upstream' => new_resource.stub_ssl_upstream,
'stub-tcp-upstream' => new_resource.stub_tcp_upstream,
'stub-no-cache' => new_resource.stub_no_cache,
}.compact
config = {
'stub-zone' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,68 @@
#
# Cookbook:: unbound
# Resource:: config_view
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
use 'partials/_config_file'
property :config_file, String,
default: lazy { "#{config_dir}/view-#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :zone_name, String,
default: lazy { name }
property :local_zone, [String, Array],
coerce: proc { |p| Array(p) }
property :local_data, [String, Array],
coerce: proc { |p| Array(p) }
property :local_data_ptr, [String, Array],
coerce: proc { |p| Array(p) }
property :view_first, [String, true, false],
coerce: proc { |p| unbound_yes_no?(p) }
load_current_value do |new_resource|
current_value_does_not_exist! unless ::File.exist?(new_resource.config_file)
if ::File.exist?(new_resource.config_file)
owner ::Etc.getpwuid(::File.stat(new_resource.config_file).uid).name
group ::Etc.getgrgid(::File.stat(new_resource.config_file).gid).name
mode ::File.stat(new_resource.config_file).mode.to_s(8)[-4..-1]
end
end
action_class do
def do_template_action
zone_config = {
'name' => new_resource.zone_name,
'local-zone' => new_resource.local_zone.dup,
'local-data' => new_resource.local_data.dup,
'local-data-ptr' => new_resource.local_data_ptr.dup,
'view-first' => new_resource.view_first,
}.compact
config = {
'view' => zone_config,
}
perform_config_action(config)
end
end

View File

@@ -0,0 +1,36 @@
#
# Cookbook:: unbound
# Resource:: package
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
provides :unbound_install
property :packages, [String, Array],
coerce: proc { |p| p.is_a?(Array) ? p : [ p ] },
default: %w(unbound),
description: 'Unbound packages to install.'
action_class do
def do_package_action(action)
package 'unbound' do
package_name new_resource.packages
action action
end
end
end
%i(install upgrade remove).each { |pkg_action| action(pkg_action) { do_package_action(action) } }

View File

@@ -0,0 +1,122 @@
#
# Cookbook:: unbound
# Resource:: _config_file
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
include Unbound::Cookbook::Helpers
property :owner, String,
default: 'root',
description: 'Set to override config file owner. Defaults to root.'
property :group, String,
default: 'unbound',
description: 'Set to override config file group. Defaults to unbound.'
property :mode, String,
default: '0640',
description: 'Set to override config file mode. Defaults to 0640.'
property :directory_mode, String,
default: '0750',
description: 'Set to override config directory mode. Defaults to 0750.'
property :config_dir, String,
default: lazy { default_config_dir },
desired_state: false,
description: 'Set to override unbound configuration directory.'
property :config_file, String,
default: lazy { "#{config_dir}/#{name}.conf" },
desired_state: false,
description: 'Set to override unbound configuration file.'
property :cookbook, String,
default: 'unbound',
desired_state: false,
description: 'Template source cookbook for the unbound configuration file.'
property :template, String,
default: 'unbound.conf.erb',
desired_state: false,
description: 'Template source file for the unbound configuration file.'
property :sensitive, [true, false],
desired_state: false,
description: 'Ensure that sensitive resource data is not output by Chef Infra Client.'
property :sort, [true, false],
default: true
property :template_properties, Hash,
default: {}
property :extra_options, Hash,
default: {}
action_class do
def deepsort?
return if defined?(DeepSort)
begin
Gem::Specification.find_by_name('deepsort')
rescue Gem::MissingSpecError
declare_resource(:chef_gem, 'deepsort')
end
require 'deepsort'
true
end
def perform_config_action(config)
directory new_resource.config_dir do
owner new_resource.owner
group new_resource.group
mode new_resource.directory_mode
recursive true
action new_resource.action.eql?(:delete) ? :delete : :create
end
config.merge!(new_resource.extra_options.dup) unless new_resource.extra_options.empty?
if new_resource.sort
deepsort?
config.deep_sort!
end
template new_resource.config_file do
cookbook new_resource.cookbook
source new_resource.template
owner new_resource.owner
group new_resource.group
mode new_resource.mode
sensitive new_resource.sensitive
helpers(Unbound::Cookbook::TemplateHelpers)
variables(content: config)
action new_resource.action
end
end
end
%i(create create_if_missing delete).each { |action_type| action(action_type) { do_template_action } }

View File

@@ -0,0 +1,69 @@
#
# Cookbook:: unbound
# Resource:: service
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
unified_mode true
property :service_name, String,
default: 'unbound',
description: 'The service name to perform actions upon'
property :config_test, [true, false],
default: true,
description: 'Perform configuration file test before performing service action'
property :config_test_fail_action, Symbol,
equal_to: %i(raise log),
default: :raise,
description: 'Action to perform upon configuration test failure.'
action_class do
def perform_config_test
cmd = shell_out('/usr/sbin/unbound-checkconf')
cmd.error!
rescue Mixlib::ShellOut::ShellCommandFailed
if new_resource.config_test_fail_action.eql?(:log)
Chef::Log.error("Configuration test failed, #{new_resource.service_name} #{action} action aborted!\n\n"\
"Error\n-----\n#{cmd.stderr}")
else
raise "Configuration test failed, #{new_resource.service_name} #{action} action aborted!\n\n"\
"Error\n-----\nAction: #{action}\n#{cmd.stderr}"
end
end
def do_service_action(service_action)
with_run_context(:root) do
if %i(start restart reload).include?(service_action)
if new_resource.config_test
perform_config_test
Chef::Log.info("Configuration test passed, creating #{new_resource.service_name} #{new_resource.declared_type} resource with action #{service_action}")
else
Chef::Log.info("Configuration test disabled, creating #{new_resource.service_name} #{new_resource.declared_type} resource with action #{service_action}")
end
declare_resource(:service, new_resource.service_name) { delayed_action(service_action) }
else
declare_resource(:service, new_resource.service_name) { action(service_action) }
end
end
end
end
%i(start stop restart reload enable disable).each { |action_type| action(action_type) { do_service_action(action_type) } }
action :test do
converge_by('Performing configuration test') { perform_config_test }
end