From b7248fb81f0df7226bd0158872653d8c5dbeee8e Mon Sep 17 00:00:00 2001 From: fe80 Date: Thu, 30 Jun 2022 12:34:34 +0200 Subject: [PATCH 1/2] Bootstrap agent2 support * Add param binary_location for specify zabbix agent binary (only for systemd) * Remove some parameters in zabbix agent configuration if it's zabbix agent2 package * LogRemoteCommands * StartAgents * MaxLinesPerSecond * AllowRoot * User * LoadModulePath * Fix EnableRemoteCommands still use on zabbix agentd > 5 but remove on agent2 --- README.md | 16 +++++++++++++ REFERENCE.md | 31 +++++++++++++++++++++++++ manifests/agent.pp | 5 ++++ manifests/init.pp | 13 +++++++++++ manifests/params.pp | 4 ++++ manifests/startup.pp | 6 ++++- spec/classes/agent_spec.rb | 30 ++++++++++++++++++++++++ spec/classes/database_spec.rb | 4 +--- spec/defines/startup_spec.rb | 3 ++- templates/zabbix-agent-systemd.init.erb | 2 +- templates/zabbix_agentd.conf.erb | 22 ++++++++++-------- 11 files changed, 120 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ffe9dc3ba..4e751d32b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ 5. [Usage - Configuration options and additional functionality](#usage) * [zabbix-server](#usage-zabbix-server) * [zabbix-agent](#usage-zabbix-agent) + * [zabbix-agent2](#usage-zabbix-agent2) * [zabbix-proxy](#usage-zabbix-proxy) * [zabbix-javagateway](#usage-zabbix-javagateway) * [zabbix-sender](#usage-zabbix-sender) @@ -206,6 +207,21 @@ class { 'zabbix::agent': } ``` +### Usage zabbix-agent2 + +To use Zabbix agent2 you need to define some parameters + +```ruby + class { 'zabbix::agent': + package_name => 'zabbix-agent2', + agent_configfile_path => '/etc/zabbix/zabbix_agent2.d', + pidfile => '/var/run/zabbix/zabbix_agentd2.pid', + servicename => 'zabbix-agent2', + zabbix_package_agent => 'zabbix-agent2', + binary_location => '/usr/sbin/zabbix_agent2' + } +``` + ### Usage zabbix-proxy Like the zabbix-server, the zabbix-proxy can also be used in 2 ways: diff --git a/REFERENCE.md b/REFERENCE.md index e41d1806c..465552836 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -80,6 +80,19 @@ class { 'zabbix': } ``` +##### Using Zabbix Agent 2 + +```puppet +class { 'zabbix::agent': + package_name => 'zabbix-agent2', + agent_configfile_path => '/etc/zabbix/zabbix_agent2.d', + pidfile => '/var/run/zabbix/zabbix_agentd2.pid', + servicename => 'zabbix-agent2', + zabbix_package_agent => 'zabbix-agent2', + binary_location => '/usr/sbin/zabbix_agent2' +} +``` + #### Parameters The following parameters are available in the `zabbix` class: @@ -1418,6 +1431,7 @@ The following parameters are available in the `zabbix::agent` class: * [`userparameter`](#-zabbix--agent--userparameter) * [`loadmodulepath`](#-zabbix--agent--loadmodulepath) * [`loadmodule`](#-zabbix--agent--loadmodule) +* [`binary_location`](#-zabbix--agent--binary_location) * [`manage_startup_script`](#-zabbix--agent--manage_startup_script) ##### `zabbix_version` @@ -2098,6 +2112,14 @@ Module to load at agent startup. Default value: `$zabbix::params::agent_loadmodule` +##### `binary_location` + +Data type: `Optional[Stdlib::Absolutepath]` + +Location of th binary file, this feature is available only for systemd startup script + +Default value: `$zabbix::params::agent_binary_location` + ##### `manage_startup_script` Data type: `Boolean` @@ -5628,6 +5650,7 @@ The following parameters are available in the `zabbix::startup` defined type: * [`service_type`](#-zabbix--startup--service_type) * [`manage_database`](#-zabbix--startup--manage_database) * [`service_name`](#-zabbix--startup--service_name) +* [`binary_location`](#-zabbix--startup--binary_location) ##### `pidfile` @@ -5703,6 +5726,14 @@ Name of the service. Defaults to the resource name Default value: `$name` +##### `binary_location` + +Data type: `Optional[Stdlib::Absolutepath]` + +This params is use for define a specific binary location. This is actually only available for zabbix agent and systemd + +Default value: `undef` + ### `zabbix::template` This will upload an Zabbix Template (XML format) diff --git a/manifests/agent.pp b/manifests/agent.pp index db5b1ce14..c5a4f24a9 100644 --- a/manifests/agent.pp +++ b/manifests/agent.pp @@ -119,6 +119,7 @@ # @param userparameter User-defined parameter to monitor. # @param loadmodulepath Full path to location of agent modules. # @param loadmodule Module to load at agent startup. +# @param binary_location Location of th binary file, this feature is available only for systemd startup script # @param manage_startup_script # If the init script should be managed by this module. Attention: This might # cause problems with some config options of this module (e.g @@ -220,6 +221,7 @@ String $additional_service_params = $zabbix::params::additional_service_params, String $service_type = $zabbix::params::service_type, Boolean $manage_startup_script = $zabbix::params::manage_startup_script, + Optional[Stdlib::Absolutepath] $binary_location = $zabbix::params::agent_binary_location, ) inherits zabbix::params { if $facts['os']['family'] == 'Debian' and versioncmp($facts['os']['release']['major'], '11') == 0 { if versioncmp($zabbix_version, '5.2') == 0 { @@ -227,6 +229,8 @@ } } + $agent2 = $zabbix_package_agent == 'zabbix-agent2' + # Find if listenip is set. If not, we can set to specific ip or # to network name. If more than 1 interfaces are available, we # can find the ipaddress of this specific interface if listenip @@ -329,6 +333,7 @@ additional_service_params => $additional_service_params, service_type => $service_type, service_name => 'zabbix-agent', + binary_location => $binary_location, require => Package[$zabbix_package_agent], } } diff --git a/manifests/init.pp b/manifests/init.pp index 2cbd3a86e..e58b96d26 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -199,11 +199,13 @@ # @param saml_sp_cert The location of the SAML Service Provider Certificate. # @param saml_idp_cert The location of the SAML Identity Provider Certificate. # @param saml_settings A hash of additional SAML SSO settings. +# # @example Single host setup: # class { 'zabbix': # zabbix_url => 'zabbix.dj-wasabi.nl', # } # +# # @example This assumes that you want to use the postgresql database. If not and you want to supply your own database crendentials: # class { 'zabbix': # zabbix_url => 'zabbix.dj-wasabi.nl', @@ -211,6 +213,17 @@ # database_user => 'zabbix', # database_password => 'ThisIsVeryDifficult.nl', # } +# +# @example Using Zabbix Agent 2 +# class { 'zabbix::agent': +# package_name => 'zabbix-agent2', +# agent_configfile_path => '/etc/zabbix/zabbix_agent2.d', +# pidfile => '/var/run/zabbix/zabbix_agentd2.pid', +# servicename => 'zabbix-agent2', +# zabbix_package_agent => 'zabbix-agent2', +# binary_location => '/usr/sbin/zabbix_agent2' +# } +# # @author Werner Dijkerman ikben@werner-dijkerman.nl class zabbix ( $zabbix_url = '', diff --git a/manifests/params.pp b/manifests/params.pp index 4bd48efe8..dd75fc916 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -293,6 +293,10 @@ $server_socketdir = undef # Agent specific params + $agent_binary_location = $facts['kernel'] ? { + 'Linux' => '/usr/sbin/zabbix_agentd', + default => undef, + } $agent_allowroot = '0' $agent_buffersend = '5' $agent_buffersize = '100' diff --git a/manifests/startup.pp b/manifests/startup.pp index 8bd1c1ecf..7811852c8 100644 --- a/manifests/startup.pp +++ b/manifests/startup.pp @@ -11,6 +11,7 @@ # @param service_type Systemd service type # @param manage_database When true, it will configure the database and execute the sql scripts. # @param service_name Name of the service. Defaults to the resource name +# @param binary_location This params is use for define a specific binary location. This is actually only available for zabbix agent and systemd # @example # zabbix::startup { 'agent': } # @@ -27,6 +28,7 @@ String $service_type = 'simple', Optional[Boolean] $manage_database = undef, Optional[String] $service_name = $name, + Optional[Stdlib::Absolutepath] $binary_location = undef, ) { case $title.downcase { /agent/: { @@ -41,8 +43,10 @@ fail('we currently only support a title that contains agent or server') } } - # provided by camp2camp/systemd if $facts['systemd'] { + if $name =~ /^zabbix-agent2?$/ { + assert_type(Stdlib::Absolutepath, $binary_location) + } contain systemd systemd::unit_file { "${name}.service": content => template("zabbix/${service_name}-systemd.init.erb"), diff --git a/spec/classes/agent_spec.rb b/spec/classes/agent_spec.rb index 0f9b77c29..a95d089e3 100644 --- a/spec/classes/agent_spec.rb +++ b/spec/classes/agent_spec.rb @@ -88,6 +88,14 @@ end end + context 'when binary_location is define', if: facts[:kernel] == 'Linux' do + it do + is_expected.to contain_zabbix__startup(service_name).with( + binary_location: '/usr/sbin/zabbix_agentd' + ) + end + end + context 'when declaring manage_repo is true' do let :params do { @@ -427,6 +435,28 @@ end end end + + context 'when zabbix_package_agent is zabbix-agent2' do + let :params do + { + zabbix_package_agent: 'zabbix-agent2', startagents: 1, + maxlinespersecond: 1, allowroot: 1, zabbix_user: 'root', + loadmodulepath: '/tmp', allowkey: 'system.run[*]', + denykey: 'system.run[*]', enableremotecommands: 1, + logremotecommands: 1 + } + end + + it { is_expected.to contain_package('zabbix-agent2') } + + it do + is_expected.not_to contain_file(config_path).with_content( + %r{^(LogRemoteCommands|StartAgents|MaxLinesPerSecond + |AllowRoot|User|LoadModulePath|AllowKey|DenyKey| + EnableRemoteCommands|LogRemoteCommands)} + ) + end + end end end end diff --git a/spec/classes/database_spec.rb b/spec/classes/database_spec.rb index 25349fba7..76eeeb22f 100644 --- a/spec/classes/database_spec.rb +++ b/spec/classes/database_spec.rb @@ -11,9 +11,7 @@ next if facts[:os]['name'] == 'windows' context "on #{os}" do - let :facts do - facts - end + let(:facts) { facts } let :pre_condition do <<-EOS diff --git a/spec/defines/startup_spec.rb b/spec/defines/startup_spec.rb index 11e3d390f..3a83001a6 100644 --- a/spec/defines/startup_spec.rb +++ b/spec/defines/startup_spec.rb @@ -65,7 +65,8 @@ { agent_configfile_path: '/something', pidfile: '/somethingelse', - additional_service_params: '--foreground' + additional_service_params: '--foreground', + binary_location: '/usr/sbin/zabbix_agentd' } end diff --git a/templates/zabbix-agent-systemd.init.erb b/templates/zabbix-agent-systemd.init.erb index bfe6ceb02..ddc521877 100644 --- a/templates/zabbix-agent-systemd.init.erb +++ b/templates/zabbix-agent-systemd.init.erb @@ -8,7 +8,7 @@ After=network.target Restart=on-failure <% if @pidfile %>PIDFile=<%= @pidfile %><% end %> KillMode=control-group -ExecStart=/usr/sbin/zabbix_agentd <%= @additional_service_params %> -c <%= @agent_configfile_path %> +ExecStart=<%= @binary_location %> <%= @additional_service_params %> -c <%= @agent_configfile_path %> <% if @zabbix_user %>User=<%= @zabbix_user %><% end %> RestartSec=10s diff --git a/templates/zabbix_agentd.conf.erb b/templates/zabbix_agentd.conf.erb index 91334e985..d53987406 100644 --- a/templates/zabbix_agentd.conf.erb +++ b/templates/zabbix_agentd.conf.erb @@ -48,7 +48,8 @@ DebugLevel=<%= @debuglevel %> # <% if @sourceip %>SourceIP=<%= @sourceip %><% end %> -<% if @zabbix_version.to_f >= 5.0 %> +<% unless @agent2 %> +<% if @zabbix_version.to_f >= 5.0 %> ### Option: AllowKey # Allow execution of item keys matching pattern. # Multiple keys matching rules may be defined in combination with DenyKey. @@ -58,7 +59,7 @@ DebugLevel=<%= @debuglevel %> # If no AllowKey or DenyKey rules defined, all keys are allowed. # # Mandatory: no -<% if @allowkey %>AllowKey=<%= @allowkey -%><% end %> +<% if @allowkey %>AllowKey=<%= @allowkey -%><% end %> ### Option: DenyKey # Deny execution of items keys matching pattern. @@ -71,17 +72,15 @@ DebugLevel=<%= @debuglevel %> # # Mandatory: no # Default: -<% if @denykey %>DenyKey=<%= @denykey -%><% end %> -<% end %> +<% if @denykey %>DenyKey=<%= @denykey -%><% end %> +<% end %> -<% if @zabbix_version.to_f < 5.0 %> ### Option: EnableRemoteCommands # Whether remote commands from Zabbix server are allowed. # 0 - not allowed # 1 - allowed # EnableRemoteCommands=<%= @enableremotecommands %> -<% end %> ### Option: LogRemoteCommands # Enable logging of executed shell commands as warnings. @@ -89,6 +88,7 @@ EnableRemoteCommands=<%= @enableremotecommands %> # 1 - enabled # LogRemoteCommands=<%= @logremotecommands %> +<% end %> ##### Passive checks related @@ -111,11 +111,13 @@ ListenPort=<%= @listenport %> # <% if @listen_ip %>ListenIP=<%= @listen_ip %><% end %> +<% unless @agent2 %> ### Option: StartAgents # Number of pre-forked instances of zabbix_agentd that process passive checks. # If set to 0, disables passive checks and the agent will not listen on any TCP port. # StartAgents=<%= @startagents %> +<% end %> ##### Active checks related @@ -192,6 +194,7 @@ BufferSend=<%= @buffersend %> # BufferSize=<%= @buffersize %> +<% unless @agent2 %> ### Option: MaxLinesPerSecond # Maximum number of new lines the agent will send per second to Zabbix Server # or Proxy processing 'log' and 'logrt' active checks. @@ -199,6 +202,7 @@ BufferSize=<%= @buffersize %> # provided in 'log' or 'logrt' item keys. # MaxLinesPerSecond=<%= @maxlinespersecond %> +<% end %> ############ ADVANCED PARAMETERS ################# @@ -222,7 +226,7 @@ MaxLinesPerSecond=<%= @maxlinespersecond %> # Timeout=<%= @timeout %> -<% if @kernel != 'windows' %> +<% if @kernel != 'windows' and !@agent2 %> ### Option: AllowRoot # Allow the agent to run as 'root'. If disabled and the agent is started by 'root', the agent # will try to switch to the user specified by the User configuration option instead. @@ -231,9 +235,7 @@ Timeout=<%= @timeout %> # 1 - allow # AllowRoot=<%= @allowroot %> -<% end %> -<% if @kernel != 'windows' %> ### Option: User # Drop privileges to a specific, existing user on the system. # Only has effect if run as 'root' and AllowRoot is disabled. @@ -268,7 +270,7 @@ UnsafeUserParameters=<%= @unsafeuserparameters %> # Disabled. A configuration file should be placed on directory: <%= @include %> ####### LOADABLE MODULES ####### -<% if @kernel != 'windows' %> +<% if @kernel != 'windows' and !@agent2 %> ### Option: LoadModulePath # Full path to location of agent modules. # Default depends on compilation options. From b63ad190395744135d06dfdfd7af734627da235f Mon Sep 17 00:00:00 2001 From: Phil Friderici Date: Tue, 28 Mar 2023 13:08:48 +0000 Subject: [PATCH 2/2] Fix broken dependency to puppetlabs/apache module * Copy apache_version from puppetlabs/apache v8.x module. Puppetlabs removed apache_version with the v9 release of the apache module. apache_version was used to distiguish between the needed settings. --- lib/facter/apache_version.rb | 27 ++++++++++++++ manifests/web.pp | 9 +++++ spec/classes/web_spec.rb | 2 +- .../facter/util/fact_apache_version_spec.rb | 37 +++++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 lib/facter/apache_version.rb create mode 100644 spec/unit/facter/util/fact_apache_version_spec.rb diff --git a/lib/facter/apache_version.rb b/lib/facter/apache_version.rb new file mode 100644 index 000000000..b7bc60d57 --- /dev/null +++ b/lib/facter/apache_version.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +Facter.add(:apache_version) do + confine kernel: %w[FreeBSD Linux] + setcode do + apache_version = nil + + if Facter::Core::Execution.which('httpd') + apache_version = Facter::Core::Execution.execute('httpd -V 2>&1') + Facter.debug "Matching httpd '#{apache_version}'" + elsif Facter::Core::Execution.which('apache2') + apache_version = Facter::Core::Execution.execute('apache2 -V 2>&1') + Facter.debug "Matching apache2 '#{apache_version}'" + elsif Facter::Core::Execution.which('apachectl') + apache_version = Facter::Core::Execution.execute('apachectl -v 2>&1') + Facter.debug "Matching apachectl '#{apache_version}'" + elsif Facter::Core::Execution.which('apache2ctl') + apache_version = Facter::Core::Execution.execute('apache2ctl -v 2>&1') + Facter.debug "Matching apache2ctl '#{apache_version}'" + end + + unless apache_version.nil? + match = %r{^Server version: Apache/(\d+.\d+(.\d+)?)}.match(apache_version) + match[1] unless match.nil? + end + end +end diff --git a/manifests/web.pp b/manifests/web.pp index 7d7700145..1a15cda8b 100644 --- a/manifests/web.pp +++ b/manifests/web.pp @@ -398,6 +398,15 @@ default => $zabbix_api_access.map |$host| { "host ${host}" }, } + # Check which version of Apache we're using + if versioncmp($facts['apache_version'], '2.4') >= 0 { + $directory_allow = { 'require' => 'all granted', } + $directory_deny = { 'require' => 'all denied', } + } else { + $directory_allow = { 'allow' => 'from all', 'order' => 'Allow,Deny', } + $directory_deny = { 'deny' => 'from all', 'order' => 'Deny,Allow', } + } + apache::vhost { $zabbix_url: docroot => '/usr/share/zabbix', ip => $apache_listen_ip, diff --git a/spec/classes/web_spec.rb b/spec/classes/web_spec.rb index fca7b2ed2..3011b9863 100644 --- a/spec/classes/web_spec.rb +++ b/spec/classes/web_spec.rb @@ -24,7 +24,7 @@ context "on #{os}" do let :facts do - facts + facts.deep_merge({ apache_version: '2.4' }) end context 'with all defaults' do diff --git a/spec/unit/facter/util/fact_apache_version_spec.rb b/spec/unit/facter/util/fact_apache_version_spec.rb new file mode 100644 index 000000000..23a9f372a --- /dev/null +++ b/spec/unit/facter/util/fact_apache_version_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Facter::Util::Fact do + before do + Facter.clear + end + + describe 'apache_version' do + context 'with value' do + before do + Facter.fact(:kernel).stubs(:value).returns('Linux') + Facter::Core::Execution.stubs(:which).with('httpd').returns(true) + Facter::Core::Execution.stubs(:execute).with('httpd -V 2>&1').returns('Server version: Apache/2.4.16 (Unix)\nServer built: Jul 31 2015 15:53:26') + end + + it 'returns the correct version' do + expect(Facter.fact(:apache_version).value).to eq('2.4.16') + end + end + end + + describe 'apache_version with empty OS' do + context 'with value' do + before do + Facter.fact(:kernel).stubs(:value).returns('Linux') + Facter::Core::Execution.stubs(:which).with('httpd').returns(true) + Facter::Core::Execution.stubs(:execute).with('httpd -V 2>&1').returns('Server version: Apache/2.4.6 ()\nServer built: Nov 21 2015 05:34:59') + end + + it 'returns the correct version' do + expect(Facter.fact(:apache_version).value).to eq('2.4.6') + end + end + end +end