Created
January 14, 2015 16:33
-
-
Save peckpeck/b39e85efa5a237f1758f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Configure the reverse proxy entries used by Apache. | |
# | |
bundle edit_line insert_proxy_entries(entries) | |
{ | |
insert_lines: | |
"<IfModule mod_proxy.c> | |
${entries}</IfModule>"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent rudder_reverse_proxy_apache_installation(service_name, internal_name, params) { | |
vars: | |
redhat:: | |
"apache_package_name" string => "httpd"; | |
!redhat:: | |
"apache_package_name" string => "apache2"; | |
classes: | |
"rudder_reverse_proxy_apache_install_package" expression => strcmp("${${params}[package_install]}", "true"); | |
packages: | |
# Too bad SuSE 10 uses a different bundle, things would be so simple if it was not the case... | |
SuSE_10.rudder_reverse_proxy_apache_install_package:: | |
"${apache_package_name}" | |
package_policy => "add", | |
package_method => rudder_rug, | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_package"), | |
comment => "Installing apache using the rug interface"; | |
!SuSE_10.rudder_reverse_proxy_apache_install_package:: | |
"${apache_package_name}" | |
package_policy => "add", | |
package_method => generic, | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_package"), | |
comment => "Installing apache using generic interface"; | |
} | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
bundle agent rudder_reverse_proxy_apache_installation_reporting(service_name, internal_name, params) { | |
classes: | |
"rudder_reverse_proxy_apache_install_package" expression => strcmp("${${params}[package_install]}", "true"); | |
methods: | |
"any" usebundle => rudder_common_reports_generic("${internal_name}", "rudder_reverse_proxy_apache_package", "${${params}[tracking_key]}", "Installation parameters", "None", "The ${service_name} package installation"); | |
# Special case if no installation is needed | |
"any" | |
usebundle => rudder_common_report("${internal_name}", "result_success", "${${params}[tracking_key]}", "Installation parameters", "None", "${service_name} installation is not required. Skipping..."), | |
ifvarclass => "!rudder_reverse_proxy_apache_install_package"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
##################################################################################### | |
# This Technique installs and configures Apache HTTPd to act as a reverse proxy | |
# server.. See metadata.xml for more details. | |
##################################################################################### | |
bundle agent rudder_reverse_proxy_apache | |
{ | |
vars: | |
# Common declarations | |
"rudder_reverse_proxy_apache_service_name" | |
string => "Apache (as a reverse proxy)"; | |
"rudder_reverse_proxy_apache_internal_name" | |
string => "apacheReverseProxy"; | |
# Parameters | |
"rudder_reverse_proxy_params[package_install]" | |
string => "&APACHE_REVERSE_PROXY_INSTALL&"; | |
"rudder_reverse_proxy_params[proxies]" | |
string => "&APACHE_REVERSE_PROXY_URL_SRC,APACHE_REVERSE_PROXY_URL_DST,APACHE_REVERSE_PROXY_TIMEOUT:{src, dst, timeout|ProxyPass &src& &dst& connectiontimeout=5 timeout=&timeout&${const.n}ProxyPassReverse &src& &dst& | |
}&"; | |
"rudder_reverse_proxy_params[selinux]" | |
string => "&APACHE_REVERSE_PROXY_ADJUST_SELINUX&"; | |
"rudder_reverse_proxy_params[tracking_key]" | |
string => "&TRACKINGKEY&"; | |
methods: | |
# Note: | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
"any" usebundle => rudder_reverse_proxy_apache_installation("${rudder_reverse_proxy_apache_service_name}", "${rudder_reverse_proxy_apache_internal_name}", "rudder_reverse_proxy_apache.rudder_reverse_proxy_params"); | |
"any" usebundle => rudder_reverse_proxy_apache_installation_reporting("${rudder_reverse_proxy_apache_service_name}", "${rudder_reverse_proxy_apache_internal_name}", "rudder_reverse_proxy_apache.rudder_reverse_proxy_params"); | |
"any" usebundle => rudder_reverse_proxy_apache_configuration("${rudder_reverse_proxy_apache_service_name}", "${rudder_reverse_proxy_apache_internal_name}", "rudder_reverse_proxy_apache.rudder_reverse_proxy_params"); | |
"any" usebundle => rudder_reverse_proxy_apache_configuration_reporting("${rudder_reverse_proxy_apache_service_name}", "${rudder_reverse_proxy_apache_internal_name}", "rudder_reverse_proxy_apache.rudder_reverse_proxy_params"); | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent rudder_reverse_proxy_apache_configuration(service_name, internal_name, params) { | |
vars: | |
"rudder_reverse_proxy_apache_proxies" string => "${${params}[proxies]}"; | |
debian:: | |
"rudder_reverse_proxy_apache_debian_modules" slist => { "proxy", "proxy_http" }; | |
SuSE:: | |
"rudder_reverse_proxy_apache_binary_name" string => "/usr/sbin/httpd2-(prefork|worker)"; | |
redhat:: | |
"reverse_proxy_configuration_file" string => "/etc/httpd/conf.d/rudder-reverse-proxy.conf"; | |
"rudder_reverse_proxy_apache_binary_name" string => "/usr/sbin/httpd"; | |
"rudder_reverse_proxy_apache_restart_command" string => "/etc/init.d/httpd"; | |
!redhat:: | |
"reverse_proxy_configuration_file" string => "/etc/apache2/conf.d/rudder-reverse-proxy.conf"; | |
"rudder_reverse_proxy_apache_restart_command" string => "/etc/init.d/apache2"; | |
!SuSE.!redhat:: | |
"rudder_reverse_proxy_apache_binary_name" string => "/usr/sbin/apache2"; | |
classes: | |
# Adjust SELinux ? | |
"rudder_reverse_proxy_apache_selinux_adjust" expression => strcmp("${${params}[selinux]}","true"); | |
# What is the current SELinux http proxying policy ? | |
"rudder_reverse_proxy_apache_selinux_proxy_policy" expression => returnszero("/usr/sbin/getsebool httpd_can_network_relay | grep -q on", "useshell"); | |
"rudder_reverse_proxy_apache_mod_${rudder_reverse_proxy_apache_debian_modules}_loaded" expression => fileexists("/etc/apache2/mods-enabled/${rudder_reverse_proxy_apache_debian_modules}.load"); | |
files: | |
"${reverse_proxy_configuration_file}" | |
create => "true", | |
edit_defaults => empty_backup, | |
edit_line => insert_proxy_entries("${rudder_reverse_proxy_apache_proxies}"), | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_configuration"), | |
comment => "Edit the Apache reverse proxy file"; | |
# Class visibility forces us to use these bundles here. | |
methods: | |
# Modules edition | |
"any" | |
usebundle => rudder_common_report("${internal_name}", "result_success", "${${params}[tracking_key]}", "Module parameters", "None", "No ${service_name} modules edition needed"), | |
ifvarclass => "!debian|(rudder_reverse_proxy_apache_mod_proxy_loaded.rudder_reverse_proxy_apache_mod_proxy_http_loaded)"; | |
# SELinux edition | |
"any" | |
usebundle => rudder_common_report("${internal_name}", "result_success", "${${params}[tracking_key]}", "SELinux parameters", "None", "No ${service_name} SELinux modification needed"), | |
ifvarclass => "!rudder_reverse_proxy_apache_selinux_adjust|rudder_reverse_proxy_apache_selinux_proxy_policy"; | |
# Apache restart/reload | |
"any" | |
usebundle => rudder_common_report("${internal_name}", "log_info", "${${params}[tracking_key]}", "Daemon status", "None", "${service_name} has been restarted or reloaded"), | |
ifvarclass => "rudder_reverse_proxy_apache_restart_repaired|rudder_reverse_proxy_apache_reload_repaired"; | |
"any" | |
usebundle => rudder_common_report("${internal_name}", "result_error", "${${params}[tracking_key]}", "Daemon status", "None", "Unable to restart or reload ${service_name}"), | |
ifvarclass => "rudder_reverse_proxy_apache_restart_error|rudder_reverse_proxy_apache_reload_error"; | |
processes: | |
"${rudder_reverse_proxy_apache_binary_name}" | |
restart_class => "rudder_reverse_proxy_apache_process_down", | |
comment => "Ensuring apache is up"; | |
commands: | |
debian:: | |
"/usr/sbin/a2enmod ${rudder_reverse_proxy_apache_debian_modules}" | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_modules"), | |
ifvarclass => "!rudder_reverse_proxy_apache_mod_${rudder_reverse_proxy_apache_debian_modules}_loaded", | |
comment => "Enable Apache modules on Debian"; | |
rudder_reverse_proxy_apache_selinux_adjust.!rudder_reverse_proxy_apache_selinux_proxy_policy:: | |
"/usr/sbin/setsebool httpd_can_network_relay on" | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_selinux"), | |
comment => "Enable SELinux Apache entry to let Apache proxy entries"; | |
rudder_reverse_proxy_apache_configuration_repaired:: | |
"${rudder_reverse_proxy_apache_restart_command} reload" | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_reload"), | |
comment => "reloading apache"; | |
(rudder_reverse_proxy_apache_process_down|rudder_reverse_proxy_apache_modules_repaired):: | |
"${rudder_reverse_proxy_apache_restart_command} restart" | |
classes => rudder_common_classes("rudder_reverse_proxy_apache_restart"), | |
comment => "restarting apache"; | |
} | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
bundle agent rudder_reverse_proxy_apache_configuration_reporting(service_name, internal_name, params) | |
{ | |
methods: | |
# Modules edition | |
"any" usebundle => rudder_common_reports_generic("${internal_name}", "rudder_reverse_proxy_apache_modules", "${${params}[tracking_key]}", "Module parameters", "None", "The ${service_name} modules"); | |
# SELinux edition | |
"any" usebundle => rudder_common_reports_generic("${internal_name}", "rudder_reverse_proxy_apache_selinux", "${${params}[tracking_key]}", "SELinux parameters", "None", "The ${service_name} SELinux configuration"); | |
# Apache configuration | |
"any" usebundle => rudder_common_reports_generic("${internal_name}", "rudder_reverse_proxy_apache_configuration", "${${params}[tracking_key]}", "Reverse proxy parameters", "None", "The ${service_name} reverse proxy configuration"); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
#################### | |
# Installs Apache # | |
#################### | |
bundle agent check_apache_installation | |
{ | |
packages: | |
linux.!SuSE_10.!redhat:: | |
"apache2" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("apache_here", "apache_installed", "cant_install_apache"), | |
comment => "Installing apache using generic interface"; | |
SuSE_10:: | |
"apache2" | |
package_policy => "add", | |
package_method => rudder_rug, | |
classes => kept_if_else("apache_here", "apache_installed", "cant_install_apache"), | |
comment => "Installing apache using the rug interface"; | |
redhat:: | |
"httpd" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("apache_here", "apache_installed", "cant_install_apache"), | |
comment => "Installing apache using generic interface"; | |
reports: | |
apache_here.!apache_installed.!cant_install_apache:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Apache2 installation@@None@@${g.execRun}##${g.uuid}@#Apache already installed"; | |
apache_installed.!cant_install_apache:: | |
"@@apacheServerConfiguration@@result_repaired@@&TRACKINGKEY&@@Apache2 installation@@None@@${g.execRun}##${g.uuid}@#Apache installed"; | |
cant_install_apache:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Apache2 installation@@None@@${g.execRun}##${g.uuid}@#Can't install Apache"; | |
!linux:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Apache2 installation@@None@@${g.execRun}##${g.uuid}@#Support to check if Apache is installed not available on this platform"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent check_apache_configuration | |
{ | |
vars: | |
# Ports | |
"apache_ports" slist => {&APACHE_PORTS: { "&it&" };separator=", "&}; | |
# List of all the files to permit on the vhost directory | |
"vhosts_files" slist => { "ports.conf", "security.conf", &APACHE_VHOST_FQDN: { "vhost-&it&.conf" };separator=", "&}; | |
# Security config | |
"apache_security[ServerTokens]" string => "&APACHE_SERVERTOKENS&"; | |
"apache_security[ServerSignature]" string => "&APACHE_SERVERSIGNATURE&"; | |
"apache_security[TraceEnable]" string => "&APACHE_TRACEENABLE&"; | |
# Virtual Hosts | |
&APACHE_VHOST_FQDN:{fqdn |"apache_vhost_fqdn[&i&]" string => "&fqdn&"; | |
}& | |
&APACHE_VHOST_PORT:{port |"apache_vhost_port[&i&]" string => "&port&"; | |
}& | |
&APACHE_VHOST_ROOT:{root |"apache_vhost_root[&i&]" string => "&root&"; | |
}& | |
&APACHE_VHOST_EXPIRES:{expires |"apache_vhost_expires[&i&]" string => "&expires&"; | |
}& | |
&APACHE_VHOST_EXPIRES_TTL:{expires_ttl |"apache_vhost_expires_ttl[&i&]" string => "&expires_ttl&"; | |
}& | |
&APACHE_VHOST_ALIAS_ONE_SRC:{alias_one_src |"apache_vhost_alias_one_src[&i&]" string => "&alias_one_src&"; | |
}& | |
&APACHE_VHOST_ALIAS_ONE_DST:{alias_one_dst |"apache_vhost_alias_one_dst[&i&]" string => "&alias_one_dst&"; | |
}& | |
&APACHE_VHOST_ALIAS_TWO_SRC:{alias_two_src |"apache_vhost_alias_two_src[&i&]" string => "&alias_two_src&"; | |
}& | |
&APACHE_VHOST_ALIAS_TWO_DST:{alias_two_dst |"apache_vhost_alias_two_dst[&i&]" string => "&alias_two_dst&"; | |
}& | |
&APACHE_VHOST_ALIAS_THREE_SRC:{alias_three_src |"apache_vhost_alias_three_src[&i&]" string => "&alias_three_src&"; | |
}& | |
&APACHE_VHOST_ALIAS_THREE_DST:{alias_three_dst |"apache_vhost_alias_three_dst[&i&]" string => "&alias_three_dst&"; | |
}& | |
"apache_vhost_index" slist => getindices("apache_vhost_fqdn"); | |
# For reporting reason, we need to have the exact list of specified modules to check | |
"apache_modules_defined" slist => { &APACHE_MODULES: { "&it&" };separator=", "& }; | |
# Modules that are installed by default | |
"apache_modules" slist => { "expires", "alias", @{apache_modules_defined} }, | |
policy => "ifdefined"; | |
classes: | |
!redhat.!SuSE:: | |
# Security : if not there, Apache too, so don't bother anymore | |
"apache_bin_present" expression => fileexists("/usr/sbin/apache2"); | |
redhat:: | |
"apache_bin_present" expression => fileexists("/usr/sbin/httpd"); | |
SuSE:: | |
"apache_bin_worker" expression => fileexists("/usr/sbin/httpd2-worker"); | |
"apache_bin_prefork" expression => fileexists("/usr/sbin/httpd2-prefork"); | |
"apache_bin_present" expression => "apache_bin_prefork|apache_bin_worker"; | |
any:: | |
# Autostart ? | |
"apache_autostart" expression => strcmp("&APACHE_AUTOSTART&","true"); | |
# Adjust SELinux ? | |
"apache_selinux_adjust" expression => strcmp("&APACHE_SELINUX&","true"); | |
# Is the SELinux binary "chcon" present ? | |
"selinux_bin_present" expression => fileexists("/usr/bin/chcon"); | |
# Define if the list of module to verify has been specified by the user | |
"apache_modules_nok" expression => strcmp("&APACHE_MODULES&","none"); | |
"apache_modules_ok" not => strcmp("&APACHE_MODULES&","none"); | |
# Check if the variable apache_modules is defined so that they can be managed | |
"apache_module_list_defined" expression => isvariable("apache_modules"); | |
files: | |
debian:: | |
"/etc/rc2.d/S.*apache2.*" | |
create => "true", | |
#depth_search => recurse("0"), | |
#file_select => apache_startlink, | |
action => WarnOnly, | |
classes => if_else("apache_bootstarted", "apache_unbootstarted"); | |
"/etc/apache2/ports.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_apache_config_ports("@{check_apache_configuration.apache_ports}"), | |
classes => kept_if_else_hook("apache_ports_kept", "apache_ports_repaired", "apache_ports_failed", "apache_change"); | |
"/etc/apache2/conf.d/security" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => empty_backup, | |
edit_line => set_apache_config_security("check_apache_configuration.apache_security"), | |
classes => kept_if_else_hook("apache_security_kept", "apache_security_repaired", "apache_security_failed", "apache_change"); | |
"/etc/httpd/sites-enabled" | |
delete => tidy, | |
classes => if_repaired("apache_change"), | |
file_select => ex_list("@{vhosts_files}"), | |
depth_search => recurse("inf"); | |
"/etc/apache2/sites-enabled/vhost-${apache_vhost_fqdn[${apache_vhost_index}]}.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => empty_backup, | |
edit_line => set_apache_config_vhost("${apache_vhost_fqdn[${apache_vhost_index}]}", "${apache_vhost_port[${apache_vhost_index}]}", "${apache_vhost_root[${apache_vhost_index}]}", "${apache_vhost_expires[${apache_vhost_index}]}", "${apache_vhost_expires_ttl[${apache_vhost_index}]}", "${apache_vhost_alias_one_src[${apache_vhost_index}]}", "${apache_vhost_alias_one_dst[${apache_vhost_index}]}", "${apache_vhost_alias_two_src[${apache_vhost_index}]}", "${apache_vhost_alias_two_dst[${apache_vhost_index}]}", "${apache_vhost_alias_three_src[${apache_vhost_index}]}", "${apache_vhost_alias_three_dst[${apache_vhost_index}]}", "${g.rudder_tools}/apache-vhost.tpl"), | |
classes => kept_if_else_hook("apache_vhost_${apache_vhost_index}_kept", "apache_vhost_${apache_vhost_index}_repaired", "apache_vhost_${apache_vhost_index}_failed", "apache_change"); | |
redhat:: | |
"/etc/rc2.d/S.*httpd.*" | |
create => "true", | |
#depth_search => recurse("0"), | |
#file_select => apache_startlink, | |
action => WarnOnly, | |
classes => if_else("apache_bootstarted", "apache_unbootstarted"); | |
"/etc/httpd/rudder.conf.d" | |
delete => tidy, | |
classes => if_repaired("apache_change"), | |
file_select => ex_list("@{vhosts_files}"), | |
depth_search => recurse("inf"); | |
"/etc/httpd/conf.d/welcome.conf" | |
rename => disable, | |
comment => "Disable an annoying file"; | |
"/etc/httpd/conf/httpd.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => cleanup_redhat_apache("check_apache_configuration.apache_security"), | |
classes => kept_if_else_hook("apache_ports_kept", "apache_ports_repaired", "apache_ports_failed", "apache_change"); | |
"/etc/httpd/rudder.conf.d/." | |
perms => mog("755", "root", "root"), | |
create => "true", | |
comment => "Make sure the rudder configuration directory exists"; | |
"/etc/httpd/rudder.conf.d/ports.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_apache_config_ports("@{check_apache_configuration.apache_ports}"), | |
classes => kept_if_else_hook("apache_ports_kept", "apache_ports_repaired", "apache_ports_failed", "apache_change"); | |
"/etc/httpd/rudder.conf.d/security.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_apache_config_security("check_apache_configuration.apache_security"), | |
classes => kept_if_else_hook("apache_security_kept", "apache_security_repaired", "apache_security_failed", "apache_change"); | |
"/etc/httpd/rudder.conf.d/vhost-${apache_vhost_fqdn[${apache_vhost_index}]}.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => empty_backup, | |
edit_line => set_apache_config_vhost("${apache_vhost_fqdn[${apache_vhost_index}]}", "${apache_vhost_port[${apache_vhost_index}]}", "${apache_vhost_root[${apache_vhost_index}]}", "${apache_vhost_expires[${apache_vhost_index}]}", "${apache_vhost_expires_ttl[${apache_vhost_index}]}", "${apache_vhost_alias_one_src[${apache_vhost_index}]}", "${apache_vhost_alias_one_dst[${apache_vhost_index}]}", "${apache_vhost_alias_two_src[${apache_vhost_index}]}", "${apache_vhost_alias_two_dst[${apache_vhost_index}]}", "${apache_vhost_alias_three_src[${apache_vhost_index}]}", "${apache_vhost_alias_three_dst[${apache_vhost_index}]}", "${g.rudder_tools}/apache-vhost.tpl"), | |
classes => kept_if_else_hook("apache_vhost_${apache_vhost_index}_kept", "apache_vhost_${apache_vhost_index}_repaired", "apache_vhost_${apache_vhost_index}_failed", "apache_change"); | |
SuSE:: | |
"/etc/rc.d/rc3.d/S.*apache2.*" | |
create => "true", | |
#depth_search => recurse("0"), | |
#file_select => apache_startlink, | |
action => WarnOnly, | |
classes => if_else("apache_bootstarted", "apache_unbootstarted"); | |
"/etc/apache2/rudder.conf.d" | |
delete => tidy, | |
classes => if_repaired("apache_change"), | |
file_select => ex_list("@{vhosts_files}"), | |
depth_search => recurse("inf"); | |
"/etc/apache2/httpd.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => cleanup_redhat_apache("check_apache_configuration.apache_security"), | |
classes => kept_if_else_hook("apache_ports_kept", "apache_ports_repaired", "apache_ports_failed", "apache_change"); | |
"/etc/apache2/rudder.conf.d/." | |
perms => mog("755", "root", "root"), | |
create => "true", | |
comment => "Make sure the rudder configuration directory exists"; | |
"/etc/apache2/listen.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_apache_config_ports("@{check_apache_configuration.apache_ports}"), | |
classes => kept_if_else_hook("apache_ports_kept", "apache_ports_repaired", "apache_ports_failed", "apache_change"); | |
"/etc/apache2/rudder.conf.d/security.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_apache_config_security("check_apache_configuration.apache_security"), | |
classes => kept_if_else_hook("apache_security_kept", "apache_security_repaired", "apache_security_failed", "apache_change"); | |
"/etc/apache2/rudder.conf.d/vhost-${apache_vhost_fqdn[${apache_vhost_index}]}.conf" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => empty_backup, | |
edit_line => set_apache_config_vhost("${apache_vhost_fqdn[${apache_vhost_index}]}", "${apache_vhost_port[${apache_vhost_index}]}", "${apache_vhost_root[${apache_vhost_index}]}", "${apache_vhost_expires[${apache_vhost_index}]}", "${apache_vhost_expires_ttl[${apache_vhost_index}]}", "${apache_vhost_alias_one_src[${apache_vhost_index}]}", "${apache_vhost_alias_one_dst[${apache_vhost_index}]}", "${apache_vhost_alias_two_src[${apache_vhost_index}]}", "${apache_vhost_alias_two_dst[${apache_vhost_index}]}", "${apache_vhost_alias_three_src[${apache_vhost_index}]}", "${apache_vhost_alias_three_dst[${apache_vhost_index}]}", "${g.rudder_tools}/apache-vhost.tpl"), | |
classes => kept_if_else_hook("apache_vhost_${apache_vhost_index}_kept", "apache_vhost_${apache_vhost_index}_repaired", "apache_vhost_${apache_vhost_index}_failed", "apache_change"); | |
any:: | |
"${apache_vhost_root[${apache_vhost_index}]}/." | |
perms => mog("755", "root", "root"), | |
create => "true", | |
classes => if_repaired("root_${apache_vhost_root[${apache_vhost_index}]}_created"), | |
comment => "Make sure the root directory exists"; | |
processes: | |
!redhat.!SuSE.apache_autostart:: | |
"/usr/sbin/apache2" | |
restart_class => "apache_down", | |
comment => "Ensuring apache is up"; | |
redhat.apache_autostart:: | |
"/usr/sbin/httpd" | |
restart_class => "apache_down", | |
comment => "Ensuring apache is up"; | |
SuSE.apache_bin_prefork.apache_autostart:: | |
"/usr/sbin/httpd2-prefork" | |
restart_class => "apache_down", | |
comment => "Ensuring apache is up"; | |
SuSE.!apache_bin_prefork.apache_autostart:: | |
"/usr/sbin/httpd2-worker" | |
restart_class => "apache_down", | |
comment => "Ensuring apache is up"; | |
commands: | |
debian.apache_module_list_defined:: | |
"/usr/sbin/a2enmod" | |
args => "${apache_modules}", | |
classes => cf2_if_else("apache_module_${apache_modules}_enabled", "apache_module_${apache_vhost_index}_not_apache_modules"), | |
comment => "Enable Apache modules on Debian"; | |
apache_selinux_adjust.selinux_bin_present:: | |
"/usr/bin/chcon" | |
args => "-R --type=httpd_sys_content_t \"${apache_vhost_root[${apache_vhost_index}]}\"", | |
classes => cf2_if_else("apache_selinux_${apache_vhost_index}_adjusted", "apache_selinux_${apache_vhost_index}_not_adjusted"), | |
comment => "Set SELinux context for Apache VHosts"; | |
!redhat.(apache_down|apache_change):: | |
"/etc/init.d/apache2" | |
args => "restart", | |
classes => cf2_if_else("apache_restarted", "cant_restart_apache"), | |
comment => "restarting apache"; | |
redhat.(apache_down|apache_change):: | |
"/etc/init.d/httpd" | |
args => "restart", | |
classes => cf2_if_else("apache_restarted", "cant_restart_apache"), | |
comment => "restarting apache"; | |
(debian.apache_unbootstarted).apache_bin_present:: | |
"/usr/sbin/update-rc.d" | |
args => "apache2 defaults", | |
classes => cf2_if_else("apache_bootstarted_ok", "apache_still_unbootstarted"), | |
comment => "adding apache to the startup scripts"; | |
(redhat.apache_unbootstarted).apache_bin_present:: | |
"/sbin/chkconfig" | |
args => "--add httpd", | |
classes => cf2_if_else("apache_bootstarted_ok", "apache_still_unbootstarted"), | |
comment => "adding apache to the startup scripts"; | |
(SuSE.apache_unbootstarted).apache_bin_present:: | |
"/sbin/chkconfig" | |
args => "--add apache2", | |
classes => cf2_if_else("apache_bootstarted_ok", "apache_still_unbootstarted"), | |
comment => "adding apache to the startup scripts"; | |
reports: | |
# if the list is not defined, there is nothing to report ! | |
apache_modules_nok:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Module settings@@none@@${g.execRun}##${g.uuid}@#No Apache modules configured to be enabled, no changes made"; | |
# if the list if defined by the user, we report on each element of this list | |
debian.apache_module_list_defined.apache_modules_ok:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Module settings@@${apache_modules_defined}@@${g.execRun}##${g.uuid}@#The Apache module ${apache_modules_defined} was successfully enabled" | |
ifvarclass => canonify("apache_module_${apache_modules_defined}_enabled"); | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Module settings@@${apache_modules_defined}@@${g.execRun}##${g.uuid}@#Could not enable apache module ${apache_modules_defined} !" | |
ifvarclass => canonify("apache_module_${apache_modules_defined}_not_enabled"); | |
!debian.apache_modules_ok:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Module settings@@${apache_modules_defined}@@${g.execRun}##${g.uuid}@#The module verification only applies on Debian systems !"; | |
apache_selinux_adjust.selinux_bin_present:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@SELinux context@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#The SELinux context definition was successful for directory ${apache_vhost_root[${apache_vhost_index}]}" | |
ifvarclass => canonify("apache_selinux_${apache_vhost_index}_adjusted"); | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@SELinux context@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#The SELinux context definition for directory ${apache_vhost_root[${apache_vhost_index}]} has failed !" | |
ifvarclass => canonify("apache_selinux_${apache_vhost_index}_not_adjusted"); | |
apache_selinux_adjust.!selinux_bin_present:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@SELinux context@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#The automatic SELinux context definition was enabled but SELinux binaries"; | |
!apache_selinux_adjust:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@SELinux context@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#No SELinux context definition required for ${apache_vhost_root[${apache_vhost_index}]}"; | |
apache_ports_kept.!apache_ports_repaired.!apache_ports_failed:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Port settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD port settings OK"; | |
apache_ports_repaired.!apache_ports_failed:: | |
"@@apacheServerConfiguration@@result_repaired@@&TRACKINGKEY&@@Port settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD port settings reset"; | |
apache_ports_failed:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Port settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD port settings could not be set !"; | |
apache_security_kept.!apache_security_repaired.!apache_security_failed:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Security settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD security settings OK"; | |
apache_security_repaired.!apache_security_failed:: | |
"@@apacheServerConfiguration@@result_repaired@@&TRACKINGKEY&@@Security settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD security settings reset"; | |
apache_security_failed:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Security settings edition@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD security settings could not be set !"; | |
cfengine:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Virtual host settings@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#Apache HTTPD virtualhost ${apache_vhost_fqdn[${apache_vhost_index}]} already set" | |
ifvarclass => "apache_vhost_${apache_vhost_index}_kept.!apache_vhost_${apache_vhost_index}_repaired.!apache_vhost_${apache_vhost_index}_failed"; | |
"@@apacheServerConfiguration@@result_repaired@@&TRACKINGKEY&@@Virtual host settings@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#Apache HTTPD virtualhost ${apache_vhost_fqdn[${apache_vhost_index}]} reset" | |
ifvarclass => "apache_vhost_${apache_vhost_index}_repaired.!apache_vhost_${apache_vhost_index}_failed"; | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Virtual host settings@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#Apache HTTPD virtualhost ${apache_vhost_fqdn[${apache_vhost_index}]} could not be set !" | |
ifvarclass => "apache_vhost_${apache_vhost_index}_failed"; | |
"@@apacheServerConfiguration@@log_info@@&TRACKINGKEY&@@Virtual host settings@@${apache_vhost_fqdn[${apache_vhost_index}]}@@${g.execRun}##${g.uuid}@#The root directory ${apache_vhost_root[${apache_vhost_index}]} was created" | |
ifvarclass => canonify("root_${apache_vhost_root[${apache_vhost_index}]}_created"); | |
apache_autostart.apache_bootstarted.!apache_unboostarted:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Apache bootstart@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD is correctly set to start on boot"; | |
apache_autostart.apache_unboostarted.apache_bootstarted_ok.!apache_still_unbootstarted:: | |
"@@apacheServerConfiguration@@result_repaired@@&TRACKINGKEY&@@Apache bootstart@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD is now starting on boot"; | |
apache_autostart.apache_still_unbootstarted.apache_still_unbootstarted:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Apache bootstart@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD could not be set to start on boot"; | |
!apache_autostart:: | |
"@@apacheServerConfiguration@@result_success@@&TRACKINGKEY&@@Apache bootstart@@None@@${g.execRun}##${g.uuid}@#Don't have to check if Apache HTTPD should be started automatically"; | |
apache_restarted:: | |
"@@apacheServerConfiguration@@log_info@@&TRACKINGKEY&@@apacheServer@@None@@${g.execRun}##${g.uuid}@#Apache HTTPD restarted"; | |
cant_restart_apache:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@apacheServer@@None@@${g.execRun}##${g.uuid}@#Could not restart Apache HTTPD"; | |
!apache_bin_present:: | |
"@@apacheServerConfiguration@@result_error@@&TRACKINGKEY&@@Apache2 installation@@None@@${g.execRun}##${g.uuid}@#Apache binary is not present. Something is wrong (installation failure ?)"; | |
} | |
bundle edit_line cleanup_redhat_apache(tab) | |
# Sets the RHS of configuration items in the file of the form | |
# LHS RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing v[LHS]="rhs" | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use whitespace as separator, and to handle commented-out lines. | |
{ | |
vars: | |
"index" slist => getindices("${tab}"); | |
delete_lines: | |
"^.*${index}.*$"; | |
"^NameVirtualHost.*((?!443).)*$"; | |
"^Listen.*((?!443).)*$"; | |
insert_lines: | |
redhat:: | |
"Include /etc/httpd/rudder.conf.d/*.conf"; | |
(debian|SuSE):: | |
"Include /etc/apache2/rudder.conf.d/*.conf"; | |
} | |
bundle edit_line set_apache_config_ports(ports) | |
{ | |
delete_lines: | |
"^NameVirtualHost.*((?!443).)*$"; | |
"^Listen.*((?!443).)*$"; | |
insert_lines: | |
"NameVirtualHost *:${ports}"; | |
"Listen ${ports}"; | |
} | |
bundle edit_line set_apache_config_security(tab) | |
# Sets the RHS of configuration items in the file of the form | |
# LHS RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing v[LHS]="rhs" | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use whitespace as separator, and to handle commented-out lines. | |
{ | |
vars: | |
"index" slist => getindices("${tab}"); | |
# Be careful if the index string contains funny chars | |
"cindex[${index}]" string => canonify("${index}"); | |
delete_lines: | |
"^.*${index}.*$"; | |
field_edits: | |
# If the line is there, but commented out, first uncomment it | |
"#+${index}\s+.*" | |
edit_field => col("\s+","1","${index}","set"); | |
# match a line starting like the key something | |
"${index}\s+.*" | |
edit_field => col("\s+","2","${${tab}[${index}]}","set"), | |
classes => if_ok("not_${cindex[${index}]}"); | |
insert_lines: | |
"${index} ${${tab}[${index}]}" | |
ifvarclass => "!not_${cindex[${index}]}"; | |
} | |
bundle edit_line set_apache_config_vhost(fqdn, port, root, exp, exp_ttl, alias_one_src, alias_one_dst, alias_two_src, alias_two_dst, alias_three_src, alias_three_dst, template) | |
{ | |
vars: | |
mylock1:: | |
"mylock" string => "mylock", | |
policy => "overridable"; | |
set_expires:: | |
"finexpire" string => "On", | |
policy => "overridable"; | |
unset_expires:: | |
"finexpire" string => "Off", | |
policy => "overridable"; | |
set_alias_one:: | |
"finalias_one" string => "Alias ${alias_one_src} \"${alias_one_dst}\"", | |
policy => "overridable"; | |
set_alias_two:: | |
"finalias_two" string => "Alias ${alias_two_src} \"${alias_two_dst}\"", | |
policy => "overridable"; | |
set_alias_three:: | |
"finalias_three" string => "Alias ${alias_three_src} \"${alias_three_dst}\"", | |
policy => "overridable"; | |
unset_alias_one:: | |
"finalias_one" string => "# Alias 1 disabled", | |
policy => "overridable"; | |
unset_alias_two:: | |
"finalias_two" string => "# Alias 2 disabled", | |
policy => "overridable"; | |
unset_alias_three:: | |
"finalias_three" string => "# Alias 3 disabled", | |
policy => "overridable"; | |
classes: | |
"set_expires" expression => strcmp("${exp}","true"); | |
"unset_expires" expression => strcmp("${exp}","false"); | |
"set_alias_one" not => strcmp("${alias_one_src}","Disabled"); | |
"set_alias_two" not => strcmp("${alias_two_src}","Disabled"); | |
"set_alias_three" not => strcmp("${alias_three_src}","Disabled"); | |
"unset_alias_one" expression => strcmp("${alias_one_src}","Disabled"); | |
"unset_alias_two" expression => strcmp("${alias_two_src}","Disabled"); | |
"unset_alias_three" expression => strcmp("${alias_three_src}","Disabled"); | |
"mylock1" expression => "any"; | |
"mylock" expression => strcmp("mylock", "${mylock}"); | |
insert_lines: | |
mylock:: | |
"${template}" | |
insert_type => "file", | |
expand_scalars => "true"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Installs requested packages by OS # | |
# # | |
# - APT_PACKAGE_DEBLIST --> The OS dependant packages to install # | |
# # | |
# - APT_PACKAGE_DEBACTION --> The action to be made on these packages # | |
# # | |
########################################################################## | |
bundle agent check_apt_package_installation | |
{ | |
vars: | |
&APT_PACKAGE_DEBLIST:{name |"apt_package[&i&]" string => "&name&"; | |
}& | |
&APT_PACKAGE_DEBACTION:{action |"apt_action[&i&]" string => "&action&"; | |
}& | |
&APT_PACKAGE_ALLOW_UNTRUSTED:{untrusted |"apt_allow_untrusted[&i&]" string => "&untrusted&"; | |
}& | |
&APT_PACKAGE_VERSION_DEFINITION:{definition |"apt_version_definition[&i&]" string => "&definition&"; | |
}& | |
&APT_PACKAGE_VERSION_CRITERION:{version_criterion |"apt_version_criterion[&i&]" string => "&version_criterion&"; | |
}& | |
&APT_PACKAGE_VERSION:{version |"apt_version[&i&]" string => "&version&"; | |
}& | |
&TRACKINGKEY:{piuuid |"apt_policy_instance_uuid[&i&]" string => "&piuuid&"; | |
}& | |
# "debian_packagelist" slist => {&APT_PACKAGE_DEBLIST: { "&it&" };separator=", "&}; | |
"index_aptpkg" slist => getindices("apt_package"); | |
classes: | |
"${index_aptpkg}_package_version_defined" not => strcmp("${apt_version_definition[${index_aptpkg}]}", "default"); | |
packages: | |
debian:: | |
"${apt_package[${index_aptpkg}]}" | |
package_policy => "${apt_action[${index_aptpkg}]}", | |
package_method => apt_nobulk("30", "${apt_allow_untrusted[${index_aptpkg}]}"), | |
classes => kept_if_else("debian_install_kept_${apt_package[${index_aptpkg}]}", "debian_installed_${apt_package[${index_aptpkg}]}", "debian_install_failed_${apt_package[${index_aptpkg}]}"), | |
ifvarclass => "!${index_aptpkg}_package_version_defined", | |
comment => "Handling ${apt_package[${index_aptpkg}]} using apt_nobulk, policy : ${apt_action[${index_aptpkg}]}"; | |
"${apt_package[${index_aptpkg}]}" | |
package_policy => "${apt_action[${index_aptpkg}]}", | |
package_method => apt_nobulk("30", "${apt_allow_untrusted[${index_aptpkg}]}"), | |
package_select => "${apt_version_criterion[${index_aptpkg}]}", | |
package_version => "${apt_version[${index_aptpkg}]}", | |
classes => kept_if_else("debian_install_kept_${apt_package[${index_aptpkg}]}", "debian_installed_${apt_package[${index_aptpkg}]}", "debian_install_failed_${apt_package[${index_aptpkg}]}"), | |
ifvarclass => "${index_aptpkg}_package_version_defined", | |
comment => "Handling ${apt_package[${index_aptpkg}]} using apt_nobulk, policy : ${apt_action[${index_aptpkg}]}"; | |
reports: | |
debian:: | |
"@@packageInstallation@@result_repaired@@${apt_policy_instance_uuid[${index_aptpkg}]}@@Debian/Ubuntu packages@@${apt_package[${index_aptpkg}]}@@${g.execRun}##${g.uuid}@#Performed repair action for deb package ${apt_package[${index_aptpkg}]} with policy: ${apt_action[${index_aptpkg}]}" | |
ifvarclass => canonify("debian_installed_${apt_package[${index_aptpkg}]}"); | |
"@@packageInstallation@@result_error@@${apt_policy_instance_uuid[${index_aptpkg}]}@@Debian/Ubuntu packages@@${apt_package[${index_aptpkg}]}@@${g.execRun}##${g.uuid}@#Error taking action for deb package ${apt_package[${index_aptpkg}]} with policy: ${apt_action[${index_aptpkg}]}" | |
ifvarclass => canonify("debian_install_failed_${apt_package[${index_aptpkg}]}"); | |
"@@packageInstallation@@result_success@@${apt_policy_instance_uuid[${index_aptpkg}]}@@Debian/Ubuntu packages@@${apt_package[${index_aptpkg}]}@@${g.execRun}##${g.uuid}@#No action required for deb package ${apt_package[${index_aptpkg}]} with policy: ${apt_action[${index_aptpkg}]}" | |
ifvarclass => canonify("debian_install_kept_${apt_package[${index_aptpkg}]}"); | |
} | |
body package_method apt_nobulk(apt_pkg_timeout, allow_untrusted) | |
{ | |
any:: | |
# make correct version comparisons | |
package_version_less_command => "${rudder_debian_knowledge.dpkg_compare_less}"; | |
package_version_equal_command => "${rudder_debian_knowledge.dpkg_compare_equal}"; | |
debian:: | |
package_changes => "individual"; | |
package_list_update_ifelapsed => "${apt_pkg_timeout}"; | |
package_list_command => "/usr/bin/dpkg -l"; | |
package_list_name_regex => ".i\s+([^\s:]+).*"; | |
package_list_version_regex => ".i\s+[^\s]+\s+([^\s]+).*"; | |
package_installed_regex => ".i.*"; # packages that have been uninstalled may be listed | |
package_name_convention => "${name}"; | |
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false -o Apt::Get::AllowUnauthenticated=${allow_untrusted} --yes install"; | |
package_list_update_command => "/usr/bin/apt-get update"; | |
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -q remove"; | |
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false -o Apt::Get::AllowUnauthenticated=${allow_untrusted} --yes install"; | |
package_verify_command => "/usr/bin/dpkg -s"; | |
package_noverify_returncode => "1"; | |
} | |
##################################################################################### | |
# Copyright 2011-2012 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Configures the APT Package Manager # | |
###################################################### | |
bundle agent check_apt_settings | |
{ | |
vars: | |
debian_4:: | |
"apt_detected_distro" string => "etch"; | |
debian_5:: | |
"apt_detected_distro" string => "lenny"; | |
debian_6:: | |
"apt_detected_distro" string => "squeeze"; | |
debian_7:: | |
"apt_detected_distro" string => "wheezy"; | |
debian_8:: | |
"apt_detected_distro" string => "jessie"; | |
ubuntu_karmic:: | |
"apt_detected_distro" string => "karmic"; | |
ubuntu_lucid:: | |
"apt_detected_distro" string => "lucid"; | |
ubuntu_maverick:: | |
"apt_detected_distro" string => "maverick"; | |
ubuntu_natty:: | |
"apt_detected_distro" string => "natty"; | |
ubuntu_oneiric:: | |
"apt_detected_distro" string => "oneiric"; | |
ubuntu_precise:: | |
"apt_detected_distro" string => "precise"; | |
ubuntu_quantal:: | |
"apt_detected_distro" string => "quantal"; | |
ubuntu_raring:: | |
"apt_detected_distro" string => "raring"; | |
apt_installrecommends_edit:: | |
"aptconf[APT::Install-Recommends]" string => "&APT_INSTALLRECOMMENDS&"; | |
apt_installsuggests_edit:: | |
"aptconf[APT::Install-Suggests]" string => "&APT_INSTALLSUGGESTS&"; | |
any:: | |
&if (APT_HTTPPROXY_URL)& | |
"aptconf[Acquire::http::Proxy]" string => "\"&APT_HTTPPROXY_URL&\";"; | |
&endif& | |
&if (APT_FTPPROXY_URL)& | |
"aptconf[Acquire::ftp::Proxy]" string => "\"&APT_FTPPROXY_URL&\";"; | |
&endif& | |
&APT_URL:{apt_url |"apt_url[&i&]" string => "&apt_url&"; | |
}& | |
&APT_COMPONENT_MAIN, APT_COMPONENT_CONTRIB, APT_COMPONENT_NON_FREE, APT_COMPONENT_RESTRICTED, APT_COMPONENT_UNIVERSE, APT_COMPONENT_MULTIVERSE:{main, contrib, nonfree, restricted, universe, multiverse |"apt_components[&i&]" string => "&main& &contrib& &nonfree& &restricted& &universe& &multiverse&"; | |
}& | |
&APT_DISTRIBUTION, APT_DISTRO_AUTODETECT:{apt_distro, apt_autodetect |"apt_distro[&i&]" string => "&if (apt_autodetect)&${apt_detected_distro}&else&&apt_distro&&endif&"; | |
}& | |
classes: | |
# Repositories edition ? | |
"apt_repositories_edit" not => strcmp("&APT_ADDREPOSITORIES&","false"); | |
# Disable repositories ? | |
"apt_disablerepositories" not => strcmp("&APT_DISABLEREPOSITORIES&","false"); | |
# InstallRecommends edition ? | |
"apt_installrecommends_edit" not => strcmp("&APT_INSTALLRECOMMENDS&","dontchange"); | |
# InstallSuggests edition ? | |
"apt_installsuggests_edit" not => strcmp("&APT_INSTALLSUGGESTS&","dontchange"); | |
files: | |
debian.apt_repositories_edit:: | |
"/etc/apt/sources.list.d/rudder-apt.list" | |
create => "true", | |
perms => m("644"), | |
edit_line => set_apt_config_values_tier1("check_apt_settings.apt_url", "check_apt_settings.apt_distro", "check_apt_settings.apt_components"), | |
edit_defaults => empty_backup, | |
classes => kept_if_else("apt_tier1_kept", "apt_tier1_validated", "apt_tier1_failed"); | |
debian:: | |
"/etc/apt/apt.conf.d/99rudder" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => empty_backup, | |
edit_line => set_apt_config_values_tier2("check_apt_settings.aptconf"), | |
classes => kept_if_else("apt_tier2_kept", "apt_tier2_validated", "apt_tier2_failed"); | |
debian.apt_disablerepositories.(apt_tier1_validated|apt_tier1_kept):: | |
"/etc/apt/sources.list" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => comment_lines_matching("^[^#].*$","#"), | |
classes => kept_if_else("apt_disabled_kept", "apt_disabled_validated", "apt_disabled_failed"); | |
"/etc/apt/sources.list.d/.*" | |
edit_line => comment_lines_matching("^[^#].*$","#"), | |
edit_defaults => noempty_backup, | |
file_select => not_rudderaptlist, | |
classes => kept_if_else("apt_disabled_kept", "apt_disabled_validated", "apt_disabled_failed"); | |
reports: | |
# SUCCESS if: | |
## Do not need to edit repositories or repositories good = ((apt_tier1_kept|!apt_repositories_edit).!apt_tier1_validated) | |
## and | |
## APT Config good = (apt_tier2_kept.!apt_tier2_validated) | |
## and | |
## No need to disable other repositories (not require or already disabled) = ((!apt_disablerepositories|(apt_disabled_kept|!apt_repositories_edit)).!apt_disabled_validated) | |
## and | |
## No error = !(apt_tier1_failed|apt_tier2_failed|apt_disabled_failed) | |
((apt_tier1_kept|!apt_repositories_edit).!apt_tier1_validated).(apt_tier2_kept.!apt_tier2_validated).((!apt_disablerepositories|(apt_disabled_kept|!apt_repositories_edit)).!apt_disabled_validated).!(apt_tier1_failed|apt_tier2_failed|apt_disabled_failed):: | |
"@@aptPackageManagerSettings@@result_success@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT settings were all already correct"; | |
# REPAIRED if: | |
## Need to edit repositories and no error= apt_tier1_validated | |
## or | |
## Need to edit APT config and no error = apt_tier2_validated | |
## or | |
## Need to disable other repositories and no error= apt_disabled_validated | |
## and | |
## No error = !(apt_tier1_failed|apt_tier2_failed|apt_disabled_failed) | |
(apt_tier1_validated|apt_tier2_validated|apt_disabled_validated).(!apt_tier1_failed|!apt_tier2_failed|!apt_disabled_failed):: | |
"@@aptPackageManagerSettings@@result_repaired@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#Some APT settings were reset"; | |
apt_tier1_kept:: | |
"@@aptPackageManagerSettings@@log_info@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repositories already correct"; | |
apt_tier2_kept:: | |
"@@aptPackageManagerSettings@@log_info@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT configuration parameters already correct"; | |
apt_tier1_validated:: | |
"@@aptPackageManagerSettings@@log_repaired@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repositories have been reset"; | |
apt_tier2_validated:: | |
"@@aptPackageManagerSettings@@log_repaired@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT configuration parameters have been reset"; | |
apt_tier1_failed:: | |
"@@aptPackageManagerSettings@@result_error@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repositories could not be edited"; | |
apt_tier2_failed:: | |
"@@aptPackageManagerSettings@@result_error@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT configuration could not be set"; | |
apt_disablerepositories:: | |
"@@aptPackageManagerSettings@@log_info@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repository purge has been requested"; | |
apt_disabled_validated:: | |
"@@aptPackageManagerSettings@@log_repaired@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repositories deactivation is done"; | |
apt_disabled_failed:: | |
"@@aptPackageManagerSettings@@result_error@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT repositories deactivation is failed"; | |
!debian:: | |
"@@aptPackageManagerSettings@@result_error@@&TRACKINGKEY&@@aptPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#APT cannot be configured on non Debian OSes"; | |
} | |
bundle edit_line set_apt_config_values_tier1(apt_url, apt_distro, apt_components) | |
{ | |
vars: | |
"apt_index" slist => getindices("${apt_url}"); | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
"deb ${${apt_url}[${apt_index}]} ${${apt_distro}[${apt_index}]} ${${apt_components}[${apt_index}]}"; | |
} | |
bundle edit_line set_apt_config_values_tier2(tab) | |
# Sets the RHS of configuration items in the file of the form | |
# LHS RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing v[LHS]="rhs" | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use whitespace as separator, and to handle commented-out lines. | |
{ | |
vars: | |
"index" slist => getindices("${tab}"); | |
# Be careful if the index string contains funny chars | |
"cindex[${index}]" string => canonify("${index}"); | |
field_edits: | |
# If the line is there, but commented out, first uncomment it | |
"#+${index}\s+.*" | |
edit_field => col("\s+","1","${index}","set"); | |
# match a line starting like the key something | |
"${index}\s+.*" | |
edit_field => col("\s+","2","${${tab}[${index}]}","set"), | |
classes => if_ok("not_${cindex[${index}]}"); | |
insert_lines: | |
"// ### File managed by Rudder, edit with care ###" | |
location => start; | |
"${index} ${${tab}[${index}]}" | |
ifvarclass => "!not_${cindex[${index}]}"; | |
} | |
body file_select not_rudderaptlist | |
{ | |
leaf_name => { "^[^rudder.*?\.list].*" }; | |
file_result => "leaf_name"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
#################### | |
# Installs OpenVPN # | |
#################### | |
bundle agent check_openvpn_installation | |
{ | |
classes: | |
"openvpn_present" expression => fileexists("/etc/init.d/openvpn"); | |
packages: | |
linux.!SuSE:: | |
"openvpn" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("openvpn_here", "openvpn_installed", "cant_install_openvpn"), | |
comment => "Installing openvpn using generic interface"; | |
commands: | |
SuSE.!openvpn_present.64_bit:: | |
"/bin/rpm" | |
args => "-Uvh ${g.rudder_var}/tools/openvpn-2.2.1-1.x86_64.rpm", | |
classes => kept_if_else("openvpn_here", "openvpn_installed", "cant_install_openvpn"), | |
comment => "Installing openvpn using plain RPM"; | |
SuSE.!openvpn_present.32_bit:: | |
"/bin/rpm" | |
args => "-Uvh ${g.rudder_var}/tools/openvpn-2.2.1-1.i686.rpm", | |
classes => kept_if_else("openvpn_here", "openvpn_installed", "cant_install_openvpn"), | |
comment => "Installing openvpn using plain RPM"; | |
reports: | |
(openvpn_here|openvpn_present):: | |
"@@openvpnConfiguration@@result_success@@&TRACKINGKEY&@@OpenVPN install@@None@@${g.execRun}##${g.uuid}@#openvpn already installed"; | |
openvpn_installed:: | |
"@@openvpnConfiguration@@result_repaired@@&TRACKINGKEY&@@OpenVPN install@@None@@${g.execRun}##${g.uuid}@#openvpn installed"; | |
cant_install_openvpn:: | |
"@@openvpnConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN install@@None@@${g.execRun}##${g.uuid}@#Can't install openvpn"; | |
!linux:: | |
"@@openvpnConfiguration@@result_success@@&TRACKINGKEY&@@OpenVPN install@@None@@${g.execRun}##${g.uuid}@#Support to check if openvpn is installed not available on this platform"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent check_openvpn_client_configuration | |
{ | |
vars: | |
&OVPN_CLIENT_REMOTE_SERVER, OVPN_CLIENT_REMOTE_PORT:{server, port |"ovpn_client_remote[&i&]" string => "&server& &port&"; | |
}& | |
"ovpn_client[dev]" string => "&OVPN_CLIENT_TUNTAP&"; | |
"ovpn_client[proto]" string => "&OVPN_CLIENT_REMOTE_PROTOCOL&"; | |
"ovpn_client[script-security]" string => "2"; | |
"ovpn_client[verb]" string => "&OVPN_CLIENT_LOGGING_VERBOSITY&"; | |
ovpn_client_pskmode:: | |
"ovpn_client[secret]" string => "&OVPN_CLIENT_PSKFILE&"; | |
ovpn_client_randomize:: | |
"ovpn_client[remote-random]" string => ""; | |
ovpn_client_pwauth:: | |
"ovpn_client[auth-user-pass]" string => "/etc/openvpn/keyring.pwd"; | |
ovpn_client_keepretrying:: | |
"ovpn_client[resolv-retry]" string => "infinite"; | |
ovpn_client_logtofile.ovpn_client_appendfile:: | |
"ovpn_client[log-append]" string => "&OVPN_CLIENT_LOGGING_FILE&"; | |
ovpn_client_logtofile.!ovpn_client_appendfile:: | |
"ovpn_client[log]" string => "&OVPN_CLIENT_LOGGING_FILE&"; | |
classes: | |
# Security : if not there, OpenVPN too, so don't bother anymore | |
"openvpn_bin_present" expression => fileexists("/usr/sbin/openvpn"); | |
# Autostart ? | |
"ovpn_client_autostart" expression => strcmp("&OVPN_CLIENT_AUTOSTART&","true"); | |
# PSK mode ? | |
"ovpn_client_pskmode" expression => strcmp("&OVPN_CLIENT_KEYMODE&","psk"); | |
# Randomize remotes ? | |
"ovpn_client_randomize" expression => strcmp("&OVPN_CLIENT_REMOTE_RANDOMIZE&","true"); | |
# Use user/password ? | |
"ovpn_client_pwauth" expression => strcmp("&OVPN_CLIENT_REMOTE_AUTH&","true"); | |
# Do not use user/password ? | |
"ovpn_client_nopwauth" expression => strcmp("&OVPN_CLIENT_REMOTE_AUTH&","false"); | |
# Log to file ? | |
"ovpn_client_logtofile" expression => strcmp("&OVPN_CLIENT_LOGGING_TARGET&","file"); | |
# Append logs ? | |
"ovpn_client_appendfile" expression => strcmp("&OVPN_CLIENT_LOGGING_BEHAVIOR&","true"); | |
# Keep retrying connection ? | |
"ovpn_client_keepretrying" expression => strcmp("&OVPN_CLIENT_REMOTE_KEEPTRYING&","true"); | |
files: | |
(debian|redhat|SuSE):: | |
"/etc/rc2.d/S.*openvpn.*" | |
create => "true", | |
#depth_search => recurse("0"), | |
#file_select => openvpn_startlink, | |
action => WarnOnly, | |
classes => if_else("openvpn_bootstarted", "openvpn_unbootstarted"); | |
"/etc/openvpn/rudder.conf" | |
create => "true", | |
perms => m("644"), | |
edit_line => set_openvpn_config_values_tier1("check_openvpn_client_configuration.ovpn_client_remote"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("openvpn_tier1_kept", "openvpn_tier1_validated", "openvpn_tier1_failed"); | |
"/etc/openvpn/rudder.conf" | |
create => "true", | |
perms => m("644"), | |
edit_line => set_openvpn_config_values_tier2("check_openvpn_client_configuration.ovpn_client"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("openvpn_tier2_kept", "openvpn_tier2_validated", "openvpn_tier2_failed"); | |
ovpn_client_pwauth:: | |
"/etc/openvpn/keyring.pwd" | |
create => "true", | |
edit_defaults => noempty_backup, | |
perms => mog("600", "root", "root"), | |
edit_line => set_openvpn_config_values_keyring("&OVPN_CLIENT_REMOTE_USER&", "&OVPN_CLIENT_REMOTE_PASS&"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("openvpn_keyring_kept", "openvpn_keyring_validated", "openvpn_keyring_failed"); | |
processes: | |
ovpn_client_autostart:: | |
"/usr/sbin/openvpn" | |
restart_class => "openvpn_down", | |
comment => "Ensuring openvpn is up"; | |
commands: | |
(openvpn_tier1_validated|openvpn_tier2_validated|openvpn_keyring_validated|openvpn_down).ovpn_client_autostart:: | |
"/etc/init.d/openvpn" | |
args => "restart", | |
classes => cf2_if_else("openvpn_restarted", "cant_restart_openvpn"), | |
comment => "restarting openvpn"; | |
(debian.openvpn_unbootstarted).openvpn_bin_present:: | |
"/usr/sbin/update-rc.d" | |
args => "openvpn defaults", | |
classes => cf2_if_else("openvpn_bootstarted_ok", "openvpn_still_unbootstarted"), | |
comment => "adding openvpn to the startup scripts"; | |
(redhat.openvpn_unbootstarted).openvpn_bin_present:: | |
"/sbin/chkconfig" | |
args => "--add openvpn", | |
classes => cf2_if_else("openvpn_bootstarted_ok", "openvpn_still_unbootstarted"), | |
comment => "adding openvpn to the startup scripts"; | |
# YES I know this isn't DRY but CF3 does not support nested parenthesis yet | |
(SuSE.openvpn_unbootstarted).openvpn_bin_present:: | |
"/sbin/chkconfig" | |
args => "--add openvpn", | |
classes => cf2_if_else("openvpn_bootstarted_ok", "openvpn_still_unbootstarted"), | |
comment => "adding openvpn to the startup scripts"; | |
reports: | |
openvpn_tier1_kept:: | |
"@@openvpnClientConfiguration@@log_info@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN remotes list edition not needed"; | |
openvpn_tier2_kept:: | |
"@@openvpnClientConfiguration@@log_info@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN general configuration is OK"; | |
openvpn_keyring_kept:: | |
"@@openvpnClientConfiguration@@log_info@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN password keyring present"; | |
openvpn_tier1_validated:: | |
"@@openvpnClientConfiguration@@log_repaired@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN remotes list edition done"; | |
openvpn_tier2_validated:: | |
"@@openvpnClientConfiguration@@log_repaired@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN general configuration done"; | |
openvpn_keyring_validated:: | |
"@@openvpnClientConfiguration@@log_repaired@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN keyring written"; | |
openvpn_tier1_failed:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN remotes list edition failed"; | |
openvpn_tier2_failed:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN general configuration failed"; | |
openvpn_keyring_failed:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN keyring could not be written"; | |
ovpn_client_nopwauth.((openvpn_tier1_validated.openvpn_tier2_validated)|(openvpn_tier1_kept.openvpn_tier2_kept)):: | |
"@@openvpnClientConfiguration@@result_success@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN configuration is set correctly"; | |
ovpn_client_pwauth.((openvpn_tier1_validated.openvpn_tier2_validated.openvpn_keyring_validated)|(openvpn_tier1_kept.openvpn_tier2_kept.openvpn_keyring_kept)):: | |
"@@openvpnClientConfiguration@@result_success@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN configuration is set correctly"; | |
(openvpn_tier1_validated.openvpn_tier2_validated.openvpn_keyring_validated)|(openvpn_tier1_kept.openvpn_tier2_kept.openvpn_keyring_kept):: | |
"@@openvpnClientConfiguration@@result_success@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN configuration is set correctly" | |
ifvarclass => canonify("ovpn_client_pwauth"); | |
ovpn_client_autostart.openvpn_bootstarted_ok:: | |
"@@openvpnClientConfiguration@@result_repaired@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN is now starting on boot"; | |
ovpn_client_autostart.openvpn_still_unbootstarted:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN could not be set to start on boot"; | |
ovpn_client_autostart.openvpn_bootstarted:: | |
"@@openvpnClientConfiguration@@log_info@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN already set to start on boot"; | |
openvpn_restarted:: | |
"@@openvpnClientConfiguration@@log_repaired@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN restarted"; | |
cant_restart_openvpn:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#Could not restart OpenVPN"; | |
!openvpn_bin_present:: | |
"@@openvpnClientConfiguration@@result_error@@&TRACKINGKEY&@@OpenVPN configuration@@None@@${g.execRun}##${g.uuid}@#OpenVPN binary is not present. Something is wrong (installation failure?)"; | |
} | |
bundle edit_line set_openvpn_config_values_tier1(remotes) | |
{ | |
vars: | |
"remotes_index" slist => getindices("${remotes}"); | |
delete_lines: | |
"remote\ .*"; | |
insert_lines: | |
"remote ${${remotes}[${remotes_index}]}"; | |
} | |
bundle edit_line set_openvpn_config_values_tier2(tab) | |
# Sets the RHS of configuration items in the file of the form | |
# LHS RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing v[LHS]="rhs" | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use whitespace as separator, and to handle commented-out lines. | |
{ | |
vars: | |
"index" slist => getindices("${tab}"); | |
# Be careful if the index string contains funny chars | |
"cindex[${index}]" string => canonify("${index}"); | |
field_edits: | |
# If the line is there, but commented out, first uncomment it | |
"#+${index}\s+.*" | |
edit_field => col("\s+","1","${index}","set"); | |
# match a line starting like the key something | |
"${index}\s+.*" | |
edit_field => col("\s+","2","${${tab}[${index}]}","set"), | |
classes => if_ok("not_${cindex[${index}]}"); | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
"${index} ${${tab}[${index}]}" | |
ifvarclass => "!not_${cindex[${index}]}"; | |
} | |
bundle edit_line set_openvpn_config_values_keyring(user, pass) | |
{ | |
insert_lines: | |
"${user}"; | |
"${pass}"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# List of packages to manage | |
# Format of the file | |
# action:version_definition:version_comparaison:trackingkey | |
& RPM_PACKAGE_REDACTION, RPM_PACKAGE_VERSION_DEFINITION, RPM_PACKAGE_VERSION_CRITERION, TRACKINGKEY:{action, definition, version_criterion, trackingkey | &action&:&definition&:&version_criterion&:&trackingkey& | |
}& | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Installs requested packages by OS # | |
# # | |
# - RPM_PACKAGE_REDLIST --> The OS dependant packages to install # | |
# # | |
# - RPM_PACKAGE_REDACTION --> The action to be made on these packages # | |
# # | |
# - RPM_PACKAGE_VERSION --> The optionnal package version # | |
# # | |
########################################################################## | |
bundle agent check_rpm_package_installation { | |
vars: | |
&RPM_PACKAGE_CHECK_INTERVAL:{check_interval |"rpm_package_check_interval" string => "&check_interval&"; | |
}& | |
"package_number" int => readstringarrayidx("rpm_data","${sys.workdir}/inputs/rpmPackageInstallation/6.1/rpmPackageInstallationData", "#[^\n]*",":",9000,1600000); | |
&! We need to use the i0 notation to have indexes starting at 0, as in readstringarrayidx !& | |
&RPM_PACKAGE_REDLIST:{name |"rpm_package[&i0&]" string => "&name&"; | |
}& | |
&RPM_PACKAGE_VERSION:{version |"rpm_version[&i0&]" string => "&version&"; | |
}& | |
&RPM_PACKAGE_POST_HOOK_COMMAND:{command |"rpm_posthook[&i0&]" string => "&command&"; | |
}& | |
"index_rpmpkg" slist => getindices("rpm_package"); | |
# File containing the list of available packages to install | |
"available_updates_file" string => "${sys.workdir}/state/software_available_updates.csv"; | |
redhat:: | |
"available_updates_command" string => "/usr/bin/yum --quiet check-update | ${paths.path[sed]} 's%[0-9]\+:%%g' > ${available_updates_file}"; | |
zypper_version_ok:: | |
"available_updates_command" string => "/usr/bin/zypper list-updates -a | ${paths.path[grep]} '|' | ${paths.path[awk]} -F '|' '{print $3 $5}' | ${paths.path[sed]} 's%[0-9]\+:%%g' > ${available_updates_file}"; | |
# If the promises have been updated, we need to remove previously | |
# defined persistent classes (by setting there persistence to 1 minutes) | |
# and cancelling also the classes for this run | |
rudder_promises_generated_repaired:: | |
"zmd_classes_to_cancel_on_update" slist => { "zmd_kept", "zmd_restarted", "could_not_restart_zmd" }; | |
"unpersist_rpm_kept_classes_${index_rpmpkg}" | |
string => "undefine", | |
classes => rudder_always_classes_persist("rpm_package_install_kept_${index_rpmpkg}", "1"); | |
"rpm_kept_classes_purged_${index_rpmpkg}" | |
string => "undefine", | |
classes => cancel_all_classes("rpm_package_install_kept_${index_rpmpkg}"); | |
"unpersist_rpm_repaired_classes_${index_rpmpkg}" | |
string => "undefine", | |
classes => rudder_always_classes_persist("rpm_package_installed_${index_rpmpkg}", "1"); | |
"rpm_repaired_classes_purged_${index_rpmpkg}" | |
string => "undefine", | |
classes => cancel_all_classes("rpm_package_installed_${index_rpmpkg}"); | |
"unpersist_rpm_error_classes_${index_rpmpkg}" | |
string => "undefine", | |
classes => rudder_always_classes_persist("rpm_package_install_failed_${index_rpmpkg}", "1"); | |
"rpm_error_classes_purged_${index_rpmpkg}" | |
string => "undefine", | |
classes => cancel_all_classes("rpm_package_install_failed_${index_rpmpkg}"); | |
"unpersist_${zmd_classes_to_cancel_on_update}" | |
string => "undefine", | |
classes => rudder_always_classes_persist("${zmd_classes_to_cancel_on_update}", "1"); | |
"${zmd_classes_to_cancel_on_update}_purged" | |
string => "undefine", | |
classes => cancel_all_classes("${zmd_classes_to_cancel_on_update}"); | |
# Generate the list of avalable package if it has been done more than xx minutes ago, or if the file is not there | |
# Do it on redhat, or if the version of zypper is valid | |
(redhat|zypper_version_ok).first_pass:: | |
"get_update_list" string => execresult("${available_updates_command}", "useshell"), | |
classes => rudder_common_classes_persist("rpm_package_installation_updated_available_packages", "${rpm_package_check_interval}"), | |
ifvarclass => "!(rpm_package_installation_updated_available_packages_repaired|rpm_package_installation_updated_available_packages_kept)|!update_file_exists"; | |
# If the update file exist, then gather the version of the packages in it | |
update_file_exists:: | |
"${index_rpmpkg}_update_version" string => execresult("${paths.path[grep]} \"${rpm_package[${index_rpmpkg}]}.\" ${available_updates_file} | ${paths.path[awk]} 'END {print $2}'", "useshell"), | |
classes => rudder_common_classes("${index_rpmpkg}_update_version_fetched"), | |
ifvarclass => "!(${index_rpmpkg}_update_version_fetched_kept|${index_rpmpkg}_update_version_fetched_repaired|${index_rpmpkg}_update_version_fetched_failed)"; | |
classes: | |
&RPM_PACKAGE_POST_HOOK_RUN:{run |"execute_command_&i0&" expression => strcmp("&run&", "true"); | |
}& | |
# Check if update file exists | |
"update_file_exists" expression => fileexists("${available_updates_file}"); | |
# Detect if we want to update the package | |
"is_update_action_${index_rpmpkg}" expression => strcmp("${rpm_data[${index_rpmpkg}][0]}", "update"); | |
# Gather the version of the available package | |
"${index_rpmpkg}_update_version_valid" not => strcmp("", "${${index_rpmpkg}_update_version}"), | |
ifvarclass => "(${index_rpmpkg}_update_version_fetched_kept|${index_rpmpkg}_update_version_fetched_repaired)"; | |
"${index_rpmpkg}_package_version_defined" not => strcmp("${rpm_data[${index_rpmpkg}][1]}", "default"); | |
"first_pass" expression => "any"; | |
any:: | |
"pass3" expression => "pass2"; | |
"pass2" expression => "pass1"; | |
"pass1" expression => "any"; | |
packages: | |
redhat|SuSE:: | |
# Case 1: Not an update, or an update on SuSE without proper Zypper | |
"${rpm_package[${index_rpmpkg}]}" | |
package_policy => "${rpm_data[${index_rpmpkg}][0]}", | |
package_method => generic_nobulk("30"), | |
classes => rudder_common_classes_persist("rpm_package_installation_${index_rpmpkg}", "${rpm_package_check_interval}"), | |
ifvarclass => "(!is_update_action_${index_rpmpkg}|(SuSE.!zypper_version_ok)).!${index_rpmpkg}_package_version_defined.!(rpm_package_installation_${index_rpmpkg}_repaired|rpm_package_installation_${index_rpmpkg}_error|rpm_package_installation_${index_rpmpkg}_kept)", | |
comment => "Handling ${rpm_package[${index_rpmpkg}]} using yum_nobulk, policy : ${rpm_data[${index_rpmpkg}][0]}"; | |
# Case 2: It is an update, on RedHat or SuSE with Zypper, and we didn't give a version, but we could fetch it | |
"${rpm_package[${index_rpmpkg}]}" | |
package_policy => "${rpm_data[${index_rpmpkg}][0]}", | |
package_method => generic_nobulk("30"), | |
package_select => "==", | |
package_version => "${${index_rpmpkg}_update_version}", | |
classes => rudder_common_classes_persist("rpm_package_installation_${index_rpmpkg}", "${rpm_package_check_interval}"), | |
ifvarclass => "is_update_action_${index_rpmpkg}.${index_rpmpkg}_update_version_valid.!${index_rpmpkg}_package_version_defined.!(rpm_package_installation_${index_rpmpkg}_repaired|rpm_package_installation_${index_rpmpkg}_error|rpm_package_installation_${index_rpmpkg}_kept)", | |
comment => "Handling ${rpm_package[${index_rpmpkg}]} using yum_nobulk, policy : ${rpm_data[${index_rpmpkg}][0]}"; | |
# Case 3: We do have a version defined | |
"${rpm_package[${index_rpmpkg}]}" | |
package_policy => "${rpm_data[${index_rpmpkg}][0]}", | |
package_method => generic_nobulk("30"), | |
package_select => "${rpm_data[${index_rpmpkg}][2]}", | |
package_version => "${rpm_version[${index_rpmpkg}]}", | |
classes => rudder_common_classes_persist("rpm_package_installation_${index_rpmpkg}", "${rpm_package_check_interval}"), | |
ifvarclass => "${index_rpmpkg}_package_version_defined.!(rpm_package_installation_${index_rpmpkg}_repaired|rpm_package_installation_${index_rpmpkg}_error|rpm_package_installation_${index_rpmpkg}_kept)", | |
comment => "Handling ${rpm_package[${index_rpmpkg}]} using yum_nobulk, policy : ${rpm_data[${index_rpmpkg}][0]}"; | |
methods: | |
pass2.zmd_restart.!zypper_version_ok:: | |
"restart_zmd" usebundle => service_restart("novell-zmd"), | |
classes => kept_if_else_persist("zmd_kept", "zmd_restarted", "could_not_restart_zmd", "${rpm_package_check_interval}"), | |
ifvarclass => "!(zmd_kept|zmd_restarted|could_not_restart_zmd).!zypper_version_ok"; | |
pass3.(redhat|SuSE):: | |
"any" usebundle => rudder_common_report("packageInstallation", "result_repaired", "${rpm_data[${index_rpmpkg}][3]}", "RHEL/CentOS/SuSE packages", "${rpm_package[${index_rpmpkg}]}", "Performed repair action for RPM package ${rpm_package[${index_rpmpkg}]} to comply with policy: ${rpm_data[${index_rpmpkg}][0]}"), | |
ifvarclass => canonify("rpm_package_installation_${index_rpmpkg}_repaired"); | |
"any" usebundle => rudder_common_report("packageInstallation", "result_error", "${rpm_data[${index_rpmpkg}][3]}", "RHEL/CentOS/SuSE packages", "${rpm_package[${index_rpmpkg}]}", "Error taking action for RPM package ${rpm_package[${index_rpmpkg}]} with policy: ${rpm_data[${index_rpmpkg}][0]}"), | |
ifvarclass => canonify("rpm_package_installation_${index_rpmpkg}_error"); | |
"any" usebundle => rudder_common_report("packageInstallation", "result_success", "${rpm_data[${index_rpmpkg}][3]}", "RHEL/CentOS/SuSE packages", "${rpm_package[${index_rpmpkg}]}", "No action required for RPM package ${rpm_package[${index_rpmpkg}]} with policy: ${rpm_data[${index_rpmpkg}][0]}"), | |
ifvarclass => canonify("rpm_package_installation_${index_rpmpkg}_kept"); | |
"any" usebundle => rudder_common_report("packageInstallation", "result_error", "${rpm_data[${index_rpmpkg}][3]}", "RHEL/CentOS/SuSE packages", "${rpm_package[${index_rpmpkg}]}", "Error taking action for RPM package ${rpm_package[${index_rpmpkg}]} with policy: ${rpm_data[${index_rpmpkg}][0]} - could not fetch the version to update"), | |
ifvarclass => "is_update_action_${index_rpmpkg}.!${index_rpmpkg}_package_version_defined.rpm_package_installation_updated_available_packages_error"; | |
"any" usebundle => rudder_common_report("packageInstallation", "result_success", "${rpm_data[${index_rpmpkg}][3]}", "RHEL/CentOS/SuSE packages", "${rpm_package[${index_rpmpkg}]}", "No action required for RPM package ${rpm_package[${index_rpmpkg}]} with policy: ${rpm_data[${index_rpmpkg}][0]}"), | |
ifvarclass => "is_update_action_${index_rpmpkg}.!${index_rpmpkg}_package_version_defined.(rpm_package_installation_updated_available_packages_kept|rpm_package_installation_updated_available_packages_repaired).!${index_rpmpkg}_update_version_valid"; | |
# Post hooks reporting | |
"any" usebundle => rudder_common_report("packageInstallation", "result_repaired", "${rpm_data[${index_rpmpkg}][3]}", "Post-modification hook", "${rpm_package[${index_rpmpkg}]}", "Successfully executed post hook (${rpm_posthook[${index_rpmpkg}]}) for RPM package ${rpm_package[${index_rpmpkg}]}"), | |
ifvarclass => "rpm_posthook_${index_rpmpkg}_repaired"; | |
"any" usebundle => rudder_common_report("packageInstallation", "result_error", "${rpm_data[${index_rpmpkg}][3]}", "Post-modification hook", "${rpm_package[${index_rpmpkg}]}", "Error executing post hook (${rpm_posthook[${index_rpmpkg}]}) for RPM package ${rpm_package[${index_rpmpkg}]}"), | |
ifvarclass => "rpm_posthook_${index_rpmpkg}_error"; | |
"any" usebundle => rudder_common_report("packageInstallation", "result_error", "${rpm_data[${index_rpmpkg}][3]}", "Post-modification hook", "${rpm_package[${index_rpmpkg}]}", "Can't executing post hook (${rpm_posthook[${index_rpmpkg}]}) for RPM package ${rpm_package[${index_rpmpkg}]} as policy ${rpm_data[${index_rpmpkg}][0]} failed"), | |
ifvarclass => "rpm_package_installation_${index_rpmpkg}_error.execute_command_${index_rpmpkg}"; | |
"any" usebundle => rudder_common_report("packageInstallation", "result_success", "${rpm_data[${index_rpmpkg}][3]}", "Post-modification hook", "${rpm_package[${index_rpmpkg}]}", "No hook executed since package promise was kept"), | |
ifvarclass => "rpm_package_installation_${index_rpmpkg}_kept.execute_command_${index_rpmpkg}"; | |
"any" usebundle => rudder_common_report("packageInstallation", "result_na", "${rpm_data[${index_rpmpkg}][3]}", "Post-modification hook", "${rpm_package[${index_rpmpkg}]}", "No post hook execution set for RPM package ${rpm_package[${index_rpmpkg}]}"), | |
ifvarclass => "!execute_command_${index_rpmpkg}"; | |
# ZMD Process presence related reports | |
pass3.!(SuSE_10.!zypper_version_ok):: | |
"any" usebundle => rudder_common_report("packageInstallation", "result_na", "${rpm_data[${index_rpmpkg}][3]}", "ZMD process", "None", "ZMD process presence verification not necessary. Skipping ..."); | |
pass3.SuSE_10.!zmd_restart.zypper_version_ok:: | |
"any" usebundle => rudder_common_report("packageInstallation", "result_success", "${rpm_data[${index_rpmpkg}][3]}", "ZMD process", "None", "The ZMD process is present. Skipping ..."); | |
pass3.service_restart_novell_zmd_ok.zypper_version_ok:: | |
"any" usebundle => rudder_common_report("packageInstallation", "result_repaired", "${rpm_data[${index_rpmpkg}][3]}", "ZMD process", "None", "The ZMD daemon was successfully restarted"); | |
pass3.service_restart_novell_zmd_not_ok.zypper_version_ok:: | |
"any" usebundle => rudder_common_report("packageInstallation", "result_error", "${rpm_data[${index_rpmpkg}][3]}", "ZMD process", "None", "The ZMD daemon failed to restart"); | |
processes: | |
SuSE_10.!zypper_version_ok:: | |
"/usr/lib/zmd/zmd.exe" | |
restart_class => "zmd_restart"; | |
commands: | |
"${rpm_posthook[${index_rpmpkg}]}" | |
classes => rudder_common_classes("rpm_posthook_${index_rpmpkg}"), | |
contain => in_shell, | |
ifvarclass => "execute_command_${index_rpmpkg}.rpm_package_installation_${index_rpmpkg}_repaired.!rpm_package_installation_${index_rpmpkg}_error"; | |
} | |
body package_method generic_nobulk(rpm_pkg_timeout) { | |
package_version_less_command => "${rudder_rpm_knowledge.rpm_compare_less}"; | |
package_version_equal_command => "${rudder_rpm_knowledge.rpm_compare_equal}"; | |
package_changes => "individual"; | |
redhat:: | |
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; | |
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$"; | |
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$"; | |
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$"; | |
package_installed_regex => ".*"; | |
package_name_convention => "${name}-${version}"; | |
package_list_update_ifelapsed => "${rpm_pkg_timeout}"; | |
package_add_command => "/usr/bin/yum -y install"; | |
package_delete_command => "/bin/rpm -e"; | |
package_update_command => "/usr/bin/yum -y update"; | |
package_verify_command => "/bin/rpm -V"; | |
zypper_version_ok:: | |
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; | |
package_list_update_ifelapsed => "${rpm_pkg_timeout}"; | |
package_installed_regex => "i.*"; | |
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_name_convention => "${name}"; | |
package_add_command => "/usr/bin/zypper --non-interactive install"; | |
package_delete_command => "/usr/bin/zypper --non-interactive remove --force-resolution"; | |
package_update_command => "/usr/bin/zypper --non-interactive update"; | |
package_verify_command => "/usr/bin/zypper --non-interactive verify$"; | |
SuSE_10.!zypper_version_ok:: | |
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; | |
package_list_update_ifelapsed => "${rpm_pkg_timeout}"; | |
package_installed_regex => "i.*"; | |
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_name_convention => "${name}"; | |
package_add_command => "/usr/bin/rug install -y"; | |
package_delete_command => "/usr/bin/rug remove -y"; | |
package_update_command => "/usr/bin/rug update -y"; | |
package_verify_command => "/usr/bin/rug verify -y$"; # $ means no args | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Configures the RUG/YaST Package Managers using ZMD # | |
###################################################### | |
bundle agent check_zmd_settings | |
{ | |
vars: | |
&TRACKINGKEY:{policyInstanceId |"zmdconf_uuid[&i&]" string => "&policyInstanceId&"; | |
}& | |
proxy_edit:: | |
"zmdconf[Network][proxy-url]" string => "&ZMD_PROXY_URL&"; | |
proxy_edit_user:: | |
"zmdconf[Network][proxy-username]" string => "&ZMD_PROXY_USER&"; | |
proxy_edit_password:: | |
"zmdconf[Network][proxy-password]" string => "&ZMD_PROXY_PASSWORD&"; | |
class_ok:: | |
&ZMD_URL:{zmd_url |"zmd_url[&i&]" string => "&zmd_url&"; | |
}& | |
&ZMD_NAME:{zmd_name |"zmd_name[&i&]" string => "&zmd_name&"; | |
}& | |
"zmd_index" slist => getindices("zmd_url"); | |
&if(ZMD_SET_REFRESH_INTERVAL)& | |
"zmdconf[Server][refresh-interval]" string => "&ZMD_REFRESH_INTERVAL&"; | |
&endif& | |
"zmdconf[Advanced][security-level]" string => "&ZMD_SOURCEPOLICY&"; | |
"zmdconf[Server][remote-enabled]" string => "&ZMD_REMOTE_ENABLED&"; | |
"zmdconf[Debug][syslog-level]" string => "&ZMD_SYSLOG_LEVEL&"; | |
"zmd_sections" slist => getindices("zmdconf"); | |
classes: | |
# Repositories edition ? | |
"zmd_repositories_edit" not => strcmp("&ZMD_ADDREPOSITORIES&","false"); | |
# Disable repositories ? | |
"zmd_disablerepositories" not => strcmp("&ZMD_DISABLEREPOSITORIES&","false"); | |
# Is the checkzmd script present ? | |
"checkzmd_present" expression => fileexists("${g.rudder_tools}/checkzmd.pl"); | |
# Do we want to set the proxy ? | |
"proxy_edit" not => strcmp("&ZMD_PROXY_URL&", ""); | |
# Do we want to set the proxy username ? | |
"proxy_edit_user" not => strcmp("&ZMD_PROXY_USER&", ""); | |
# Do we want to set the proxy username ? | |
"proxy_edit_password" not => strcmp("&ZMD_PROXY_PASSWORD&", ""); | |
"class_ok" expression => strcmp("true", "true"); | |
"showtime" expression => isvariable("zmd_sections"); | |
files: | |
showtime.SuSE:: | |
"/etc/zmd/zmd.conf" | |
create => "true", | |
perms => mog("600", "root", "root"), | |
edit_defaults => noempty_backup, | |
edit_line => set_advanced_zmd_config_values("check_zmd_settings.zmdconf", "${zmd_sections}"), | |
classes => kept_if_else("zmd_conf_kept", "zmd_conf_validated", "zmd_conf_failed"); | |
processes: | |
"/usr/lib/zmd/zmd.exe" | |
restart_class => "zmd_restart"; | |
commands: | |
showtime.SuSE.checkzmd_present:: | |
"${g.rudder_tools}/checkzmd.pl \"${zmd_name[${zmd_index}]}\" \"${zmd_url[${zmd_index}]}\" ${zmd_index}" | |
contain => in_shell, | |
module => "true", | |
comment => "Analyzing ZMD's output"; | |
showtime.SuSE.zmd_repositories_edit:: | |
"/usr/bin/rug" | |
args => "sa --type=zypp \"${zmd_url[${zmd_index}]}\" \"${zmd_name[${zmd_index}]}\"", | |
ifvarclass => "index_${zmd_index}_not_matched", | |
classes => kept_if_else("source_${zmd_index}_kept", "source_${zmd_index}_added", "source_${zmd_index}_failed"), | |
comment => "Add the ${zmd_index} as a new source"; | |
"/usr/bin/rug" | |
args => "subscribe \"${zmd_name[${zmd_index}]}\"", | |
ifvarclass => "source_${zmd_index}_added", | |
classes => kept_if_else("source_${zmd_index}_subkept", "source_${zmd_index}_subscribed", "source_${zmd_index}_subfailed"), | |
comment => "Subscribe ${zmd_index} as a new source"; | |
showtime.SuSE.(zmd_restart|zmd_conf_validated):: | |
"/etc/init.d/novell-zmd" | |
args => "restart", | |
classes => kept_if_else("zmd_kept", "zmd_restarted", "could_not_restart_zmd"), | |
comment => "Restart the ZMD daemon"; | |
reports: | |
# ZMD settings edition | |
zmd_conf_kept:: | |
"@@zmdPackageManagerSettings@@result_success@@${zmdconf_uuid[${zmd_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#ZMD settings were all already correct"; | |
zmd_conf_validated:: | |
"@@zmdPackageManagerSettings@@result_repaired@@${zmdconf_uuid[${zmd_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#Some ZMD settings were reset"; | |
zmd_conf_failed:: | |
"@@zmdPackageManagerSettings@@result_error@@${zmdconf_uuid[${zmd_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#ZMD repositories could not be edited"; | |
"@@zmdPackageManagerSettings@@result_error@@&TRACKINGKEY&@@General settings@@None@@${g.execRun}##${g.uuid}@#ZMD repositories could not be edited"; | |
# Ignore non-SuSE OSes | |
!SuSE:: | |
"@@zmdPackageManagerSettings@@result_error@@${zmdconf_uuid[${zmd_index}]}@@zmdPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#ZMD cannot be configured on non SuSE OSes"; | |
SuSE:: | |
# Repositories | |
"@@zmdPackageManagerSettings@@result_success@@${zmdconf_uuid[${zmd_index}]}@@Repository@@${zmd_url[${zmd_index}]}@@${g.execRun}##${g.uuid}@#The ZMD source ${zmd_name[${zmd_index}]} is not here but no edition required. Skipping..." | |
ifvarclass => "index_${zmd_index}_not_matched.!zmd_repositories_edit"; | |
"@@zmdPackageManagerSettings@@result_success@@${zmdconf_uuid[${zmd_index}]}@@Repository@@${zmd_url[${zmd_index}]}@@${g.execRun}##${g.uuid}@#The ZMD source ${zmd_name[${zmd_index}]} was already here. Skipping..." | |
ifvarclass => "index_${zmd_index}_matched.!source_${zmd_index}_subscribed"; | |
"@@zmdPackageManagerSettings@@result_repaired@@${zmdconf_uuid[${zmd_index}]}@@Repository@@${zmd_url[${zmd_index}]}@@${g.execRun}##${g.uuid}@#The ZMD source ${zmd_name[${zmd_index}]} has been successfully added" | |
ifvarclass => "index_${zmd_index}_not_matched.source_${zmd_index}_subscribed"; | |
"@@zmdPackageManagerSettings@@result_error@@${zmdconf_uuid[${zmd_index}]}@@Repository@@${zmd_url[${zmd_index}]}@@${g.execRun}##${g.uuid}@#The ZMD source ${zmd_name[${zmd_index}]} was NOT added : Could not register the source !" | |
ifvarclass => "source_${zmd_index}_failed"; | |
"@@zmdPackageManagerSettings@@result_error@@${zmdconf_uuid[${zmd_index}]}@@Repository@@${zmd_url[${zmd_index}]}@@${g.execRun}##${g.uuid}@#The ZMD source ${zmd_name[${zmd_index}]} was NOT added : Could not subscribe to the source !" | |
ifvarclass => "source_${zmd_index}_subfailed"; | |
# ZMD Process presence related reports | |
SuSE.!zmd_restart:: | |
"@@zmdPackageManagerSettings@@result_success@@${zmdconf_uuid[${zmd_index}]}@@ZMD process@@None@@${g.execRun}##${g.uuid}@#The ZMD process is present. Skipping ..."; | |
SuSE.zmd_restarted:: | |
"@@zmdPackageManagerSettings@@result_repaired@@${zmdconf_uuid[${zmd_index}]}@@ZMD process@@None@@${g.execRun}##${g.uuid}@#The ZMD daemon was successfully restarted"; | |
SuSE.could_not_restart_zmd:: | |
"@@zmdPackageManagerSettings@@result_error@@${zmdconf_uuid[${zmd_index}]}@@ZMD process@@None@@${g.execRun}##${g.uuid}@#The ZMD daemon failed to restart"; | |
} | |
bundle edit_line set_advanced_zmd_config_values(tab, sectionName) | |
{ | |
# Sets the RHS of configuration items in the file of the form | |
# LHS=RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing tab[SectionName][LHS]="RHS" | |
# don't change value when the RHS is dontchange | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use section to define were to write, and to handle commented-out lines. | |
# CAUTION : for it to work nicely, you should use Cfengine with the commit n°3229 | |
# otherwise you may risk a segfault | |
vars: | |
"index" slist => getindices("${tab}[${sectionName}]"); | |
# Be careful if the index string contains funny chars | |
"cindex[${index}]" string => canonify("${index}"); | |
classes: | |
"edit_${cindex[${index}]}" not => strcmp("${${tab}[${sectionName}][${index}]}","dontchange"); | |
field_edits: | |
# If the line is there, but commented out, first uncomment it | |
"#+${index}=.*" | |
select_region => INI_section("${sectionName}"), | |
edit_field => col("=","1","${index}","set"), | |
ifvarclass => "edit_${cindex[${index}]}"; | |
# match a line starting like the key something | |
"${index}=.*" | |
edit_field => col("=","2","${${tab}[${sectionName}][${index}]}","set"), | |
select_region => INI_section("${sectionName}"), | |
classes => if_ok("not_${cindex[${index}]}"), | |
ifvarclass => "edit_${cindex[${index}]}"; | |
insert_lines: | |
"[${sectionName}]" | |
location => start; | |
"${index}=${${tab}[${sectionName}][${index}]}" | |
select_region => INI_section("${sectionName}"), | |
ifvarclass => "!not_${cindex[${index}]}.edit_${cindex[${index}]}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Configures the Zypper repositories # | |
###################################################### | |
bundle agent zypper_repositories_management | |
{ | |
vars: | |
&ZYPPER_REPO_NAME:{zypper_name |"zypper_name[&i&]" string => "&zypper_name&"; | |
}& | |
&ZYPPER_REPO_URL:{zypper_url |"zypper_url[&i&]" string => "&zypper_url&"; | |
}& | |
&ZYPPER_REPO_TYPE:{zypper_type |"zypper_type[&i&]" string => "&zypper_type&"; | |
}& | |
&ZYPPER_REPO_ENABLED:{zypper_enabled |"zypper_enabled[&i&]" string => "&zypper_enabled&"; | |
}& | |
&ZYPPER_REPO_AUTOREFRESH:{zypper_autorefresh |"zypper_autorefresh[&i&]" string => "&zypper_autorefresh&"; | |
}& | |
&TRACKINGKEY:{directiveId |"zypper_uuid[&i&]" string => "&directiveId&"; | |
}& | |
# List of all the files to permit deletion of others repos | |
"zypper_files" slist => { &ZYPPER_REPO_NAME: { "rudder-&it&.repo" };separator=", "&}; | |
"zypper_index" slist => getindices("zypper_name"); | |
"zypper_reports_value" slist => getvalues("zypper_uuid"); | |
classes: | |
# Disable repositories if the value of the variable start by true | |
# Since variable is unique, it can contain only one value, however, it is repeated | |
# as many time as there are instance of the directive, rendering the strcmp unusable in this case | |
"zypper_disable_other_repositories" expression => regcmp("true.*", "&ZYPPER_REPO_DISABLE_OTHER_REPOSITORIES&"); | |
files: | |
SuSE:: | |
"/etc/zypp/repos.d/rudder-${zypper_name[${zypper_index}]}.repo" | |
create => "true", | |
perms => m("644"), | |
edit_line => configure_zypper_repos("${zypper_name[${zypper_index}]}", "${zypper_url[${zypper_index}]}", "${zypper_enabled[${zypper_index}]}", "${zypper_type[${zypper_index}]}", "${zypper_autorefresh[${zypper_index}]}", "${sys.workdir}/inputs/zypperPackageManagerRepositories/zypper-repo.tml"), | |
edit_defaults => empty_backup, | |
classes => rudder_common_classes("zypper_repo_${zypper_index}"); | |
SuSE.zypper_disable_other_repositories:: | |
"/etc/zypp/repos.d/.*" | |
delete => tidy, | |
file_select => ex_list("@{zypper_files}"), | |
depth_search => recurse("inf"), | |
classes => rudder_common_classes("zypper_other_repos_disabled"), | |
comment => "Delete the unwanted repos as requested"; | |
methods: | |
SuSE:: | |
"repos_${zypper_index}" usebundle => rudder_common_reports_generic("Zypper Repositories Management", "zypper_repo_${zypper_index}", "${zypper_uuid[${zypper_index}]}", "Repositories", "${zypper_name[${zypper_index}]}", "Repository ${zypper_name[${zypper_index}]}"); | |
!SuSE:: | |
"repos_${zypper_index}" usebundle => rudder_common_report("Zypper Repositories Management", "result_na", "${zypper_uuid[${zypper_index}]}", "Repositories", "${zypper_name[${zypper_index}]}", "Repository ${zypper_name[${zypper_index}]} can only be added on SUSE/SLES systems"); | |
# we must report on the deletion of other reports for all instances of the directives | |
SuSE.zypper_disable_other_repositories:: | |
"deletion_${zypper_reports_value}" usebundle => rudder_common_reports_generic("Zypper Repositories Management", "zypper_other_repos_disabled", "${zypper_reports_value}", "Purge other repositories", "None", "Deletion of others repositories"); | |
# For deletion of others repos, if there is effectively no others files in the folders, then | |
# CFEngine will not define any classes at all: since there is nothing to promise on, there | |
# is no outcome. | |
# So, if disable_other_repositories is defined, but no any zypper_other_repos_disabled classes, | |
# we must consider the promise to be kept | |
"deletion_${zypper_reports_value}" | |
usebundle => rudder_common_report("Zypper Repositories Management", "result_success", "${zypper_reports_value}", "Purge other repositories", "None", "Every repository other than the defined ones were already disable"), | |
ifvarclass => "!zypper_other_repos_disabled_kept.!zypper_other_repos_disabled_repaired.!zypper_other_repos_disabled_error"; | |
SuSE.!zypper_disable_other_repositories:: | |
"deletion_${zypper_reports_value}" usebundle => rudder_common_report("Zypper Repositories Management", "result_na", "${zypper_reports_value}", "Purge other repositories", "None", "The repository desactivation has not been requested. Skipping..."); | |
!SuSE:: | |
"deletion_${zypper_reports_value}" usebundle => rudder_common_report("Zypper Repositories Management", "result_na", "${zypper_reports_value}", "Purge other repositories", "None", "Deletion of others repositories is available only on SUSE/SLES systems"); | |
} | |
bundle edit_line configure_zypper_repos(zypper_name, zypper_url, zypper_enabled, zypper_type, zypper_autorefresh, template) | |
{ | |
insert_lines: | |
"${template}" | |
insert_type => "file", | |
expand_scalars => "true"; | |
} | |
${rudder_parameters.rudder_file_edit_header} | |
[${configure_zypper_repos.zypper_name}] | |
name=${configure_zypper_repos.zypper_name} | |
enabled=${configure_zypper_repos.zypper_enabled} | |
autorefresh=${configure_zypper_repos.zypper_autorefresh} | |
baseurl=${configure_zypper_repos.zypper_url} | |
type=${configure_zypper_repos.zypper_type} | |
keeppackages=0 | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Configures the Zypper Package Manager # | |
###################################################### | |
bundle agent check_zypper_settings | |
{ | |
vars: | |
&ZYPPER_NAME:{zypper_name |"zypper_name[&i&]" string => "&zypper_name&"; | |
}& | |
&ZYPPER_URL:{zypper_url |"zypper_url[&i&]" string => "&zypper_url&"; | |
}& | |
&ZYPPER_TYPE:{zypper_type |"zypper_type[&i&]" string => "&zypper_type&"; | |
}& | |
&ZYPPER_ENABLED:{zypper_enabled |"zypper_enabled[&i&]" string => "&zypper_enabled&"; | |
}& | |
&TRACKINGKEY:{policyInstanceId |"zypper_uuid[&i&]" string => "&policyInstanceId&"; | |
}& | |
# List of all the files to permit on the vhost directory | |
"zypper_files" slist => { &ZYPPER_NAME: { "rudder-&it&.repo" };separator=", "&}; | |
"zypper_index" slist => getindices("zypper_name"); | |
"zmdconf[main][solver.onlyRequires]" string => "&ZYPPER_INSTALLRECOMMENDS&"; | |
"zypper_sections" slist => getindices("zmdconf"); | |
classes: | |
# Repositories edition ? | |
"zypper_repositories_edit" expression => strcmp("&ZYPPER_ADDREPOSITORIES&","true"); | |
# Disable repositories ? | |
"zypper_disablerepositories" not => strcmp("&ZYPPER_DISABLEREPOSITORIES&","false"); | |
files: | |
SuSE:: | |
"/etc/zypp/zypp.conf" | |
create => "true", | |
perms => mog("644", "root", "root"), | |
edit_defaults => noempty_backup, | |
edit_line => set_advanced_zypper_config_values("check_zypper_settings.zmdconf", "${zypper_sections}"), | |
classes => kept_if_else("zypper_conf_kept", "zypper_conf_validated", "zypper_conf_failed"); | |
SuSE.zypper_repositories_edit:: | |
#"/etc/zypp/repos.d/rudder-defined.repo" | |
# create => "true", | |
# perms => m("644"), | |
# edit_line => set_zypper_repos("check_zypper_settings.zypper_name", "check_zypper_settings.zypper_url", "check_zypper_settings.zypper_enabled", "check_zypper_settings.zypper_type"), | |
# edit_defaults => empty_backup, | |
# classes => kept_if_else("zypper_tier1_kept", "zypper_tier1_validated", "zypper_tier1_failed"); | |
"/etc/zypp/repos.d/rudder-${zypper_name[${zypper_index}]}.repo" | |
create => "true", | |
perms => m("644"), | |
edit_line => set_zypper_repos("${zypper_name[${zypper_index}]}", "${zypper_url[${zypper_index}]}", "${zypper_enabled[${zypper_index}]}", "${zypper_type[${zypper_index}]}", "${g.rudder_tools}/zypper-repo.tpl"), | |
edit_defaults => empty_backup, | |
classes => kept_if_else("zypper_${zypper_index}_kept", "zypper_${zypper_index}_validated", "zypper_${zypper_index}_failed"); | |
SuSE.zypper_disablerepositories:: | |
"/etc/zypp/repos.d/.*" | |
delete => tidy, | |
file_select => ex_list("@{zypper_files}"), | |
depth_search => recurse("inf"), | |
classes => kept_if_else("repos_disabled_kept", "repos_disabled_ok", "repos_disabled_fail"), | |
comment => "Delete the unwanted repos as requested"; | |
reports: | |
# ZYPPER settings edition | |
zypper_conf_kept.!zypper_conf_validated.!zypper_conf_failed:: | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#Zypper settings were all already correct"; | |
zypper_conf_validated:: | |
"@@zypperPackageManagerSettings@@result_repaired@@${zypper_uuid[${zypper_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#Some Zypper settings were reset"; | |
zypper_conf_failed:: | |
"@@zypperPackageManagerSettings@@result_error@@${zypper_uuid[${zypper_index}]}@@General settings@@None@@${g.execRun}##${g.uuid}@#Zypper repositories could not be edited"; | |
# Zypper repositories desactivation | |
zypper_disablerepositories.!repos_disabled_ok.!repos_disabled_fail:: | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@Repository deactivation@@None@@${g.execRun}##${g.uuid}@#Every repository other than the defined ones were already disabled"; | |
zypper_disablerepositories.repos_disabled_ok:: | |
"@@zypperPackageManagerSettings@@result_repaired@@${zypper_uuid[${zypper_index}]}@@Repository deactivation@@None@@${g.execRun}##${g.uuid}@#Every repository other than the defined ones were disabled"; | |
zypper_disablerepositories.repos_disabled_fail:: | |
"@@zypperPackageManagerSettings@@result_error@@${zypper_uuid[${zypper_index}]}@@Repository deactivation@@None@@${g.execRun}##${g.uuid}@#Could not disable the other repositories!"; | |
!zypper_disablerepositories:: | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@Repository deactivation@@None@@${g.execRun}##${g.uuid}@#The repository desactivation has not been requested. Skipping..."; | |
# Ignore non-SuSE OSes | |
!SuSE:: | |
"@@zypperPackageManagerSettings@@result_error@@${zypper_uuid[${zypper_index}]}@@zypperPackageManagerSettings@@None@@${g.execRun}##${g.uuid}@#ZYPPER cannot be configured on non SuSE OSes"; | |
!zypper_repositories_edit:: | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_name[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The source ${zypper_name[${zypper_index}]} will NOT be added as the repository addition parameter is off in the Policy Instance. Skipping..."; | |
SuSE:: | |
# Repositories | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_name[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The Zypper source ${zypper_name[${zypper_index}]} was already here. Skipping..." | |
ifvarclass => "zypper_${zypper_index}_kept.!zypper_${zypper_index}_validated"; | |
"@@zypperPackageManagerSettings@@result_repaired@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_name[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The Zypper source ${zypper_name[${zypper_index}]} has been successfully added" | |
ifvarclass => "zypper_${zypper_index}_validated"; | |
"@@zypperPackageManagerSettings@@result_error@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_name[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The Zypper source ${zypper_name[${zypper_index}]} was NOT added!" | |
ifvarclass => "zypper_${zypper_index}_error"; | |
} | |
bundle edit_line set_zypper_repos(zypper_name, zypper_url, zypper_enabled, zypper_type, template) | |
{ | |
insert_lines: | |
"${template}" | |
insert_type => "file", | |
expand_scalars => "true"; | |
} | |
bundle edit_line set_zypper_repos_BROKEN(zypper_name, zypper_url, zypper_enabled, zypper_type) | |
{ | |
vars: | |
"zypper_index" slist => getindices("${zypper_name}"); | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
"[${${zypper_name}[${zypper_index}]}]" | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"name=${${zypper_name}[${zypper_index}]}" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"enabled=${${zypper_enabled}[${zypper_index}]}" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"autorefresh=0" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"baseurl=${${zypper_url}[${zypper_index}]}" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"type=${${zypper_type}[${zypper_index}]}" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
"keeppackages=0" | |
select_region => INI_section("${${zypper_name}[${zypper_index}]}"), | |
classes => kept_if_else("source_${zypper_index}_kept", "source_${zypper_index}_ok", "source_${zypper_index}_failed"); | |
reports: | |
# Repositories | |
"@@zypperPackageManagerSettings@@result_success@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_url[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The ZYPPER source ${zypper_name[${zypper_index}]} was already here. Skipping..." | |
ifvarclass => "source_${zypper_index}_kept.!source_${zypper_index}_ok"; | |
"@@zypperPackageManagerSettings@@result_repaired@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_url[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The ZYPPER source ${zypper_name[${zypper_index}]} has been successfully added" | |
ifvarclass => "source_${zypper_index}_ok"; | |
"@@zypperPackageManagerSettings@@result_error@@${zypper_uuid[${zypper_index}]}@@Repository@@${zypper_url[${zypper_index}]}@@${g.execRun}##${g.uuid}@#The ZYPPER source ${zypper_name[${zypper_index}]} was NOT added!" | |
ifvarclass => "source_${zypper_index}_failed"; | |
} | |
bundle edit_line set_advanced_zypper_config_values(tab, sectionName) | |
{ | |
# Sets the RHS of configuration items in the file of the form | |
# LHS=RHS | |
# If the line is commented out with #, it gets uncommented first. | |
# Adds a new line if none exists. | |
# The argument is an associative array containing tab[SectionName][LHS]="RHS" | |
# don't change value when the RHS is dontchange | |
# Based on set_variable_values from cfengine_stdlib.cf, modified to | |
# use section to define were to write, and to handle commented-out lines. | |
# CAUTION : for it to work nicely, you should use Cfengine with the commit n°3229 | |
# otherwise you may risk a segfault | |
vars: | |
"index" slist => getindices("${tab}[${sectionName}]"); | |
# Be careful if the index string contains funny chars | |
"cindex[${index}]" string => canonify("${index}"); | |
classes: | |
"edit_${cindex[${index}]}" not => strcmp("${${tab}[${sectionName}][${index}]}","dontchange"); | |
field_edits: | |
# If the line is there, but commented out, first uncomment it | |
"#+${index}=.*" | |
select_region => INI_section("${sectionName}"), | |
edit_field => col("=","1","${index}","set"), | |
ifvarclass => "edit_${cindex[${index}]}"; | |
# match a line starting like the key something | |
"${index}=.*" | |
edit_field => col("=","2","${${tab}[${sectionName}][${index}]}","set"), | |
select_region => INI_section("${sectionName}"), | |
classes => if_ok("not_${cindex[${index}]}"), | |
ifvarclass => "edit_${cindex[${index}]}"; | |
insert_lines: | |
"${index}=${${tab}[${sectionName}][${index}]}" | |
select_region => INI_section("${sectionName}"), | |
ifvarclass => "!not_${cindex[${index}]}.edit_${cindex[${index}]}"; | |
} | |
body file_select not_rudderzypperrepo | |
{ | |
leaf_name => { "^[^rudder-defined.*?\.repo].*" }; | |
file_result => "leaf_name"; | |
} | |
##################################################################################### | |
# Copyright 2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Setups the Zypper Package Manager # | |
###################################################### | |
bundle agent zypper_package_manager_setup | |
{ | |
vars: | |
"directive_id" string => "&TRACKINGKEY&"; | |
"zmdconf[main][solver.onlyRequires]" string => "&ZYPPER_INSTALLRECOMMENDS&"; | |
"zypper_sections" slist => getindices("zmdconf"); | |
"class_prefix" string => "zypper_package_manager_setup"; | |
classes: | |
files: | |
SuSE:: | |
"/etc/zypp/zypp.conf" | |
create => "true", | |
perms => mog("644", "root", "root"), | |
edit_defaults => noempty_backup, | |
edit_line => set_variable_values_ini("zypper_package_manager_setup.zmdconf", "${zypper_sections}"), | |
classes => rudder_common_classes("${class_prefix}"); | |
methods: | |
SuSE:: | |
"suse" usebundle => rudder_common_reports_generic("Zypper package manager setup", "${class_prefix}", "${directive_id}", "General settings", "None", "The Zypper package manager setup"); | |
!SuSE:: | |
"not applicable" usebundle => rudder_common_report("Zypper package manager setup", "result_na", "${directive_id}", "General settings", "None", "The Zypper package manager setup is not applicable on this system"); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
################################################################# | |
# Manage files and folders, enforcing their existence # | |
################################################################# | |
bundle agent manageFilesAndFolders { | |
vars: | |
&FILE_AND_FOLDER_MANAGEMENT_PATH:{path |"file[&i&][path]" string => "&path&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_PERM:{perm |"file[&i&][mode]" string => "&perm&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_OWNER:{owner |"file[&i&][owner]" string => "&owner&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_GROUP:{group |"file[&i&][group]" string => "&group&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_POST_HOOK_COMMAND:{cmd |"file[&i&][post_hook_command]" string => "&cmd&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_SYMLINK_SOURCE:{src |"file[&i&][source]" string => "&src&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_SYMLINK_ENFORCE:{symlink_enforced | "file[&i&][symlink_enforced]" string => "&symlink_enforced&"; | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_RECURSIVE:{recursive |"file[&i&][recursive]" string => "&recursive&"; | |
}& | |
&FILE_AND_FOLDER_DELETION_DAYS:{ttl |"file[&i&][ttl]" string => "&ttl&"; | |
}& | |
&FILE_AND_FOLDER_DELETION_PATTERN:{pattern |"file[&i&][pattern]" string => "&pattern&"; | |
}& | |
&TRACKINGKEY:{directiveId |"file[&i&][uuid]" string => "&directiveId&"; | |
}& | |
"index" slist => getindices("file"); | |
iteration_1:: | |
"extended_modes_${index}" | |
string => "4", | |
ifvarclass => "enable_suid_${index}.!enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "2", | |
ifvarclass => "!enable_suid_${index}.enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "6", | |
ifvarclass => "enable_suid_${index}.enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "0", | |
ifvarclass => "!enable_suid_${index}.!enable_sgid_${index}"; | |
classes: | |
# Set a class to define when we need to run the post-modification hook | |
&FILE_AND_FOLDER_MANAGEMENT_POST_HOOK_RUN:{run |"manageFilesAndFolders_post_hook_run_&i&" expression => strcmp("&run&", "true"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_CHECK_PERMISSIONS:{perms |"manageFilesAndFolders_check_permissions_&i&" expression => strcmp("&perms&", "true"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{nocreate | "manageFilesAndFolders_nocreate_&i&" expression => strcmp("&nocreate&", "none"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{createfile | "manageFilesAndFolders_createfile_&i&" expression => strcmp("&createfile&", "file"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{createdir | "manageFilesAndFolders_createdir_&i&" expression => strcmp("&createdir&", "dir"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{copy | "manageFilesAndFolders_local_cp_&i&" expression => strcmp("©&", "copy"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{createsymlink | "manageFilesAndFolders_createsymlink_&i&" expression => strcmp("&createsymlink&", "symlink"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_ACTION:{clean | "manageFilesAndFolders_clean_&i&" expression => strcmp("&clean&", "clean"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_RECURSIVE:{isrecursive | "manageFilesAndFolders_isrecursive_&i&" expression => strcmp("&isrecursive&", "inf"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_OWNER:{userset | "manageFilesAndFolders_userset_&i&" expression => strcmp("&userset&", "${file[&i&][owner]}"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_GROUP:{groupset | "manageFilesAndFolders_groupset_&i&" expression => strcmp("&groupset&", "${file[&i&][group]}"); | |
}& | |
&FILE_AND_FOLDER_DELETION_OPTION:{delopt | "manageFilesAndFolders_deletion_simple_&i&" expression => strcmp("&delopt&", "none"); | |
}& | |
&FILE_AND_FOLDER_DELETION_OPTION:{delopt | "manageFilesAndFolders_deletion_single_recursive_&i&" expression => strcmp("&delopt&", "single"); | |
}& | |
&FILE_AND_FOLDER_DELETION_OPTION:{delopt | "manageFilesAndFolders_deletion_full_recursive_&i&" expression => strcmp("&delopt&", "full"); | |
}& | |
&FILE_AND_FOLDER_DELETION_OPTION:{delopt | "manageFilesAndFolders_deletion_exterminate_&i&" expression => strcmp("&delopt&", "exterminate"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_SUID:{suid |"enable_suid_&i&" expression => strcmp("&suid&", "true"); | |
}& | |
&FILE_AND_FOLDER_MANAGEMENT_SGID:{sgid |"enable_sgid_&i&" expression => strcmp("&sgid&", "true"); | |
}& | |
"manageFilesAndFolders_isdir_${index}" expression => isdir("${file[${index}][path]}"); | |
"manageFilesAndFolders_isfile_${index}" expression => isplain("${file[${index}][path]}"); | |
"manageFilesAndFolders_islink_${index}" expression => islink("${file[${index}][path]}"); | |
"iteration_2" expression => "iteration_1"; | |
"iteration_1" expression => "any"; | |
files: | |
iteration_2:: | |
# Directory | |
"${file[${index}][path]}/." | |
create => "true", | |
classes => kept_if_else("manageFolders_${index}_kept", "manageFolders_${index}_modified", "manageFolders_${index}_failed"), | |
comment => "Enforcing the existance of folder ${file[${index}][path]}", | |
ifvarclass => "(!manageFilesAndFolders_nocreate_${index}.!manageFilesAndFolders_createfile_${index}.manageFilesAndFolders_createdir_${index}).!manageFilesAndFolders_local_cp_${index}.!manageFilesAndFolders_createsymlink_${index}"; | |
# File | |
"${file[${index}][path]}" | |
create => "true", | |
classes => kept_if_else("manageFiles_${index}_kept", "manageFiles_${index}_modified", "manageFiles_${index}_failed"), | |
comment => "Enforcing the existance of file ${file[${index}][path]}", | |
ifvarclass => "(!manageFilesAndFolders_nocreate_${index}.!manageFilesAndFolders_createdir_${index}.manageFilesAndFolders_createfile_${index}).!manageFilesAndFolders_local_cp_${index}.!manageFilesAndFolders_createsymlink_${index}"; | |
# Local copy | |
"${file[${index}][path]}" | |
copy_from => backup_local_cp("${file[${index}][source]}"), | |
classes => kept_if_else("manageCp_${index}_kept", "manageCp_${index}_modified", "manageCp_${index}_failed"), | |
ifvarclass => "(!manageFilesAndFolders_nocreate_${index}.!manageFilesAndFolders_createdir_${index}.!manageFilesAndFolders_createfile_${index}).manageFilesAndFolders_local_cp_${index}.!manageFilesAndFolders_createsymlink_${index}", | |
comment => "Create ${file[${index}][path]} file as copy of ${file[${index}][source]}"; | |
# Symlink | |
"${file[${index}][path]}" | |
# create => "true", | |
link_from => ln_s("${file[${index}][source]}"), | |
move_obstructions => "${file[${index}][symlink_enforced]}", | |
classes => kept_if_else("manageSyms_${index}_kept", "manageSyms_${index}_modified", "manageSyms_${index}_failed"), | |
ifvarclass => "(!manageFilesAndFolders_nocreate_${index}.!manageFilesAndFolders_createdir_${index}.!manageFilesAndFolders_createfile_${index}).!manageFilesAndFolders_local_cp_${index}.manageFilesAndFolders_createsymlink_${index}", | |
comment => "Create the ${file[${index}][path]} symlink pointing to ${file[${index}][source]}"; | |
# Check the permissions none recursively | |
## With user and group | |
"${file[${index}][path]}" | |
perms => mog("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][owner]}", "${file[${index}][group]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.!manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_userset_${index}.manageFilesAndFolders_groupset_${index}"; | |
## With user | |
"${file[${index}][path]}" | |
perms => mo("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][owner]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.!manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_userset_${index}.!manageFilesAndFolders_groupset_${index}"; | |
## With group | |
"${file[${index}][path]}" | |
perms => mg("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][group]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.!manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_groupset_${index}.!manageFilesAndFolders_userset_${index}"; | |
# Check the permissions recursively | |
## With user and group | |
"${file[${index}][path]}" | |
depth_search => recurse_withroot("${file[${index}][recursive]}"), | |
perms => mog("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][owner]}", "${file[${index}][group]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_userset_${index}.manageFilesAndFolders_groupset_${index}"; | |
## With user | |
"${file[${index}][path]}" | |
depth_search => recurse_withroot("${file[${index}][recursive]}"), | |
perms => mo("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][owner]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_userset_${index}.!manageFilesAndFolders_groupset_${index}"; | |
## With group | |
"${file[${index}][path]}" | |
depth_search => recurse_withroot("${file[${index}][recursive]}"), | |
perms => mg("${extended_modes_${index}}${file[${index}][mode]}", "${file[${index}][group]}"), | |
classes => kept_if_else("manageFilesAndFolders_perms_${index}_kept", "manageFilesAndFolders_perms_${index}_modified", "manageFilesAndFolders_perms_${index}_failed"), | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.manageFilesAndFolders_isrecursive_${index}.manageFilesAndFolders_groupset_${index}.!manageFilesAndFolders_userset_${index}"; | |
# This will not delete the parent | |
"${file[${index}][path]}" | |
delete => tidy, | |
file_select => date_pattern("${file[${index}][ttl]}", "${file[${index}][pattern]}"), | |
ifvarclass => "manageFilesAndFolders_clean_${index}.manageFilesAndFolders_deletion_single_recursive_${index}", | |
depth_search => recurse("0"), | |
classes => kept_if_else("manageFilesAndFolders_delete_${index}_kept", "manageFilesAndFolders_delete_${index}_modified", "manageFilesAndFolders_delete_${index}_failed"); | |
# This will not delete the parent | |
"${file[${index}][path]}" | |
delete => tidy, | |
file_select => date_pattern("${file[${index}][ttl]}", "${file[${index}][pattern]}"), | |
depth_search => recurse("inf"), | |
ifvarclass => "manageFilesAndFolders_clean_${index}.(manageFilesAndFolders_deletion_full_recursive_${index}|manageFilesAndFolders_deletion_exterminate_${index})", | |
classes => kept_if_else("manageFilesAndFolders_delete_${index}_kept", "manageFilesAndFolders_delete_${index}_modified", "manageFilesAndFolders_delete_${index}_failed"); | |
# This WILL delete the parent | |
"${file[${index}][path]}" | |
delete => tidy, | |
file_select => date_pattern("${file[${index}][ttl]}", "${file[${index}][pattern]}"), | |
ifvarclass => "manageFilesAndFolders_clean_${index}.(manageFilesAndFolders_deletion_simple_${index}|manageFilesAndFolders_deletion_exterminate_${index})", | |
classes => kept_if_else("manageFilesAndFolders_delete_${index}_kept", "manageFilesAndFolders_delete_${index}_modified", "manageFilesAndFolders_delete_${index}_failed"); | |
commands: | |
"${file[${index}][post_hook_command]}" | |
classes => if_else("manageFilesAndFolders_${index}_command_run_ok", "manageFilesAndFolders_${index}_command_run_failed"), | |
contain => in_shell, | |
ifvarclass => "manageFilesAndFolders_post_hook_run_${index}.(manageFiles_${index}_modified|manageFolders_${index}_modified|manageCp_${index}_modified|manageSyms_${index}_modified|manageFilesAndFolders_perms_${index}_modified)"; | |
reports: | |
(linux|windows):: | |
# Reporting for creation | |
## Reporting for directory creation | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The folder ${file[${index}][path]} already exists" | |
ifvarclass => "manageFolders_${index}_kept.!manageFolders_${index}_modified.manageFilesAndFolders_isdir_${index}.!manageFilesAndFolders_isfile_${index}.!manageFilesAndFolders_islink_${index}"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The folder ${file[${index}][path]} was successfully created" | |
ifvarclass => "manageFolders_${index}_modified"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The folder ${file[${index}][path]} could not be created" | |
ifvarclass => "manageFolders_${index}_failed|manageFolders_${index}_kept.(manageFilesAndFolders_isfile_${index}|manageFilesAndFolders_islink_${index})"; | |
## Reporting for file creation | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} already exists" | |
ifvarclass => "manageFiles_${index}_kept.!manageFiles_${index}_modified.manageFilesAndFolders_isfile_${index}.!manageFilesAndFolders_isdir_${index}.!manageFilesAndFolders_islink_${index}"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} was successfully created" | |
ifvarclass => "manageFiles_${index}_modified"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} could not be created" | |
ifvarclass => "manageFiles_${index}_failed|manageFiles_${index}_kept.(manageFilesAndFolders_isdir_${index}|manageFilesAndFolders_islink_${index})"; | |
## Reporting for local cp | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} already exists and is up to date" | |
ifvarclass => "manageCp_${index}_kept.!manageCp_${index}_modified.manageFilesAndFolders_isfile_${index}.!manageFilesAndFolders_isdir_${index}.!manageFilesAndFolders_islink_${index}"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} was successfully copied from ${file[${index}][source]}" | |
ifvarclass => "manageCp_${index}_modified"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The file ${file[${index}][path]} could not be created" | |
ifvarclass => "manageCp_${index}_failed|manageCp_${index}_kept.(manageFilesAndFolders_isdir_${index}|manageFilesAndFolders_islink_${index})"; | |
## Reporting for symlink creation | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The symlink ${file[${index}][path]} already exists" | |
ifvarclass => "manageSyms_${index}_kept.!manageSyms_${index}_modified"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The symlink ${file[${index}][path]} was successfully created" | |
ifvarclass => "manageSyms_${index}_modified"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The symlink ${file[${index}][path]} could not be created" | |
ifvarclass => "manageSyms_${index}_failed"; | |
## Reporting for no change | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#No file creation action specified for ${file[${index}][path]}" | |
ifvarclass => "manageFilesAndFolders_nocreate_${index}"; | |
# Reporting for the permissions | |
## Success if not set | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} was not requested to have its permission enforced" | |
ifvarclass => "!manageFilesAndFolders_check_permissions_${index}"; | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The permission of the item ${file[${index}][path]} were correct" | |
ifvarclass => "manageFilesAndFolders_perms_${index}_kept.!manageFilesAndFolders_perms_${index}_modified"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The permissions of the item ${file[${index}][path]} have been corrected" | |
ifvarclass => "manageFilesAndFolders_perms_${index}_modified.!manageFilesAndFolders_perms_${index}_failed"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The permissions of the item ${file[${index}][path]} could not be set" | |
ifvarclass => "manageFilesAndFolders_perms_${index}_failed"; | |
"@@manageFilesAndFolders@@log_info@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} will be handled recursively" | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.manageFilesAndFolders_createdir_${index}.manageFilesAndFolders_recursive_${index}"; | |
"@@manageFilesAndFolders@@log_warn@@${file[${index}][uuid]}@@Permissions@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} will NOT be handled recursively, because it is either a file or a symlink" | |
ifvarclass => "manageFilesAndFolders_check_permissions_${index}.!manageFilesAndFolders_createdir_${index}.manageFilesAndFolders_recursive_${index}"; | |
# Reporting for the deletion | |
## Report in the general component of the file | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#File cleaning was requested for ${file[${index}][path]}. Check specific reporting in the 'File cleaning options' component." | |
ifvarclass => "manageFilesAndFolders_clean_${index}"; | |
## Success if not set | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File cleaning options@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} was not requested to be deleted" | |
ifvarclass => "!manageFilesAndFolders_clean_${index}"; | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@File cleaning options@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} was in conformity with the deletion policy" | |
ifvarclass => "manageFilesAndFolders_clean_${index}.!manageFilesAndFolders_delete_${index}_modified.!manageFilesAndFolders_delete_${index}_failed"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@File cleaning options@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} has been put in conformity with the deletion policy" | |
ifvarclass => "manageFilesAndFolders_delete_${index}_modified"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@File cleaning options@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#The item ${file[${index}][path]} deletion policy could not be enforced" | |
ifvarclass => "manageFilesAndFolders_delete_${index}_failed"; | |
# Reporting for post-command execution | |
"@@manageFilesAndFolders@@result_success@@${file[${index}][uuid]}@@Post-modification hook@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#Post-execution hook did not need running" | |
ifvarclass => "!manageFilesAndFolders_post_hook_run_${index}|((manageFiles_${index}_kept|manageFolders_${index}_kept|manageSyms_${index}_kept|manageFilesAndFolders_perms_${index}_kept).!(manageFiles_${index}_modified|manageFolders_${index}_modified|manageSyms_${index}_modified|manageFilesAndFolders_perms_${index}_modified))"; | |
"@@manageFilesAndFolders@@result_repaired@@${file[${index}][uuid]}@@Post-modification hook@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#Post-execution hook successfully run" | |
ifvarclass => "manageFilesAndFolders_${index}_command_run_ok"; | |
"@@manageFilesAndFolders@@result_error@@${file[${index}][uuid]}@@Post-modification hook@@${file[${index}][path]}@@${g.execRun}##${g.uuid}@#An error occured when running the post-execution hook" | |
ifvarclass => "manageFilesAndFolders_${index}_command_run_failed"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Adjust file permissions # | |
# ####################### # | |
# # | |
# This PT adjusts file or directory permissions # | |
# according to user set parameters. # | |
###################################################### | |
bundle agent files_permissions | |
{ | |
vars: | |
"dim_array" int => readstringarrayidx("file","${sys.workdir}/inputs/filesPermissions/permlist","#[^\n]*",":",1024,102400); | |
"filePerms" slist => getindices("file"); | |
methods: | |
"any" usebundle => check_permissions("${file[${filePerms}][0]}", | |
"${file[${filePerms}][1]}", | |
"${file[${filePerms}][2]}"); | |
} | |
bundle agent check_permissions(directiveId, fileName, action_parameters) | |
{ | |
vars: | |
"identifier" string => canonify("${directiveId}${fileName}"); | |
# Splitting the action parameters | |
# we need to do the split in two pass, as we cannot reliably use array with more than 10 column in CFEngine 3.6 | |
# See https://dev.cfengine.com/issues/6674 | |
"dim_array" int => parsestringarrayidx("permission_parameters", "${action_parameters}", "\s*#[^\n]*", ";;", 10, 4096); | |
# directly get the content of the value for ease of use in the technique | |
"user" string => "${permission_parameters[0][0]}"; | |
"group" string => "${permission_parameters[0][1]}"; | |
"mode" string => "${permission_parameters[0][2]}"; | |
"edit_user" string => "${permission_parameters[0][3]}"; | |
"edit_group" string => "${permission_parameters[0][4]}"; | |
"edit_mode" string => "${permission_parameters[0][5]}"; | |
"suid" string => "${permission_parameters[0][6]}"; | |
"sgid" string => "${permission_parameters[0][7]}"; | |
"recursion" string => "${permission_parameters[0][8]}"; | |
# See the explication below, before the "classes_defined" class definition | |
classes_defined.enable_suid.!enable_sgid:: | |
"extended_modes" | |
string => "4"; | |
classes_defined.!enable_suid.enable_sgid:: | |
"extended_modes" | |
string => "2"; | |
classes_defined.enable_suid.enable_sgid:: | |
"extended_modes" | |
string => "6"; | |
classes_defined.!enable_suid.!enable_sgid:: | |
"extended_modes" | |
string => "0"; | |
classes: | |
"file_exists" expression => fileexists(${fileName}); | |
"user_absent" not => userexists("${user}"); | |
"group_absent" not => groupexists("${group}"); | |
"edit_owner" not => strcmp("${edit_user}","false"); | |
"edit_group" not => strcmp("${edit_group}","false"); | |
"edit_mode" not => strcmp("${edit_mode}","false"); | |
"edit_recurse" not => strcmp("${recursion}","false"); | |
"enable_suid" not => strcmp("${suid}","false"); | |
"enable_sgid" not => strcmp("${sgid}","false"); | |
"is_symlink" expression => islink("${fileName}"); | |
# Again, normal ordering must be altered for this to work. | |
# This class will block variable definition as long as the other | |
# classes are not defined properly | |
"classes_defined" expression => "any"; | |
# When ${suid_definition} exists, it means that we can now set SUID | |
# and SGID bits. | |
"can_edit_suid_sgid" expression => isvariable("extended_modes"); | |
files: | |
file_exists.edit_owner.!user_absent.!edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => owner("${user}"), | |
comment => "Setting the file owner", | |
classes => kept_if_else("${identifier}_owner_ok", "${identifier}_owner_repaired", "${identifier}_owner_not_repaired"); | |
file_exists.edit_group.!group_absent.!edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => group("${group}"), | |
comment => "Setting the file group", | |
classes => kept_if_else("${identifier}_group_ok", "${identifier}_group_repaired", "${identifier}_group_not_repaired"); | |
can_edit_suid_sgid.file_exists.edit_mode.!edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => m("${extended_modes}${mode}"), | |
comment => "Setting the file mode", | |
classes => kept_if_else("${identifier}_mode_ok", "${identifier}_mode_repaired", "${identifier}_mode_not_repaired"); | |
file_exists.edit_owner.!user_absent.edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => owner("${user}"), | |
depth_search => recurse_with_current("inf"), | |
comment => "Setting the file owner", | |
classes => kept_if_else("${identifier}_owner_ok", "${identifier}_owner_repaired", "${identifier}_owner_not_repaired"); | |
file_exists.edit_group.!group_absent.edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => group("${group}"), | |
depth_search => recurse_with_current("inf"), | |
comment => "Setting the file group", | |
classes => kept_if_else("${identifier}_group_ok", "${identifier}_group_repaired", "${identifier}_group_not_repaired"); | |
file_exists.edit_mode.edit_recurse.!is_symlink:: | |
"${fileName}" | |
perms => m("${mode}"), | |
depth_search => recurse_with_current("inf"), | |
comment => "Setting the file mode", | |
classes => kept_if_else("${identifier}_mode_ok", "${identifier}_mode_repaired", "${identifier}_mode_not_repaired"); | |
reports: | |
is_symlink:: | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Will not adjust permissions on ${fileName}, because it is a symlink"; | |
!file_exists:: | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#File or directory not found: ${fileName}"; | |
user_absent:: | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#The requested user (${user}) was not found on this machine: ${fileName}'s owner can't be set"; | |
group_absent:: | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#The requested group (${group}) was not found on this machine: ${fileName}'s group can't be set"; | |
edit_recurse:: | |
"@@FilesPermissions@@log_info@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Permissions will be applied recursively for ${fileName}"; | |
file_exists.can_edit_suid_sgid:: | |
# User | |
"@@FilesPermissions@@log_info@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner ${user} already matches current owner for: ${fileName}" | |
ifvarclass => "${identifier}_owner_ok.!${identifier}_owner_repaired"; | |
"@@FilesPermissions@@log_repaired@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner reset to ${user} for: ${fileName}" | |
ifvarclass => "${identifier}_owner_repaired"; | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner ${user} could not be set for: ${fileName}" | |
ifvarclass => "${identifier}_owner_not_repaired"; | |
# Group | |
"@@FilesPermissions@@log_info@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Group ${group} already matches current group for: ${fileName}" | |
ifvarclass => "${identifier}_group_ok.!${identifier}_group_repaired"; | |
"@@FilesPermissions@@log_repaired@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Group reset to ${group} for: ${fileName}" | |
ifvarclass => "${identifier}_group_repaired"; | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Group ${group} could not be set for: ${fileName}" | |
ifvarclass => "${identifier}_group_not_repaired"; | |
# Mode | |
"@@FilesPermissions@@log_info@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Mode ${extended_modes}${mode} already matches current mode for: ${fileName}" | |
ifvarclass => "${identifier}_mode_ok.!${identifier}_mode_repaired"; | |
"@@FilesPermissions@@log_repaired@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Mode reset to ${extended_modes}${mode} for: ${fileName}" | |
ifvarclass => "${identifier}_mode_repaired"; | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Mode ${extended_modes}${mode} could not be set for: ${fileName}" | |
ifvarclass => "${identifier}_mode_not_repaired"; | |
# Final report | |
"@@FilesPermissions@@result_success@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner, group and permissions already correct for ${fileName}" | |
# Success if nothing in error AND nothing repaired | |
ifvarclass => "(!${identifier}_owner_not_repaired.!${identifier}_group_not_repaired.!${identifier}_mode_not_repaired).(!${identifier}_owner_repaired.!${identifier}_group_repaired.!${identifier}_mode_repaired)"; | |
"@@FilesPermissions@@result_repaired@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner, group or permissions were fixed for: ${fileName}" | |
# Repaired if nothing in error AND something repaired | |
ifvarclass => "!${identifier}_owner_not_repaired.!${identifier}_group_not_repaired.!${identifier}_mode_not_repaired.(${identifier}_owner_repaired|${identifier}_group_repaired|${identifier}_mode_repaired)"; | |
"@@FilesPermissions@@result_error@@${directiveId}@@File permissions@@${fileName}@@${g.execRun}##${g.uuid}@#Owner, group or permissions could not be set for: ${fileName}" | |
# Error if something in error | |
ifvarclass => "${identifier}_owner_not_repaired|${identifier}_group_not_repaired|${identifier}_mode_not_repaired"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# List of files permission | |
# Format of the file : | |
# directiveId:file:user;;group;;mode;;edituser;;editgroup;;editmode;;suid;;sgid;;recursion | |
&TRACKINGKEY, FILEPERMISSION_FILENAME, FILEPERMISSION_USER, FILEPERMISSION_GROUP, FILEPERMISSION_MODE, FILEPERMISSION_EDITUSER, FILEPERMISSION_EDITGROUP, FILEPERMISSION_EDITMODE, FILEPERMISSION_SUID, FILEPERMISSION_SGID, FILEPERMISSION_RECURSION:{directiveId, fileName, user, group, perm, edituser, editgroup, editperm, suid, sgid, recursion | &directiveId&:&fileName&:&user&;;&group&;;&perm&;;&edituser&;;&editgroup&;;&editperm&;;&suid&;;&sgid&;;&recursion& | |
}& | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
################################################################# | |
# Checks if a file matches a given content. If not, updates it. # | |
################################################################# | |
bundle agent check_generic_file_content { | |
vars: | |
tier1:: | |
&GENERIC_FILE_CONTENT_PATH:{path |"generic_file_content_path[&i&]" string => "&path&"; | |
}& | |
&GENERIC_FILE_CONTENT_OWNER:{owner |"generic_file_content_owner[&i&]" string => "&owner&"; | |
}& | |
&GENERIC_FILE_CONTENT_GROUP:{group |"generic_file_content_group[&i&]" string => "&group&"; | |
}& | |
&GENERIC_FILE_CONTENT_PERM:{perms |"generic_file_content_perms[&i&]" string => "&perms&"; | |
}& | |
# Because the stupid StringTemplate systems passes the indentation as-is inside the generated variable | |
&GENERIC_FILE_CONTENT_PAYLOAD:{payload |"generic_file_content_payload[&i&]" string => "&payload&"; | |
}& | |
&GENERIC_FILE_CONTENT_ENFORCE:{enforce |"generic_file_content_enforced[&i&]" string => "&enforce&"; | |
}& | |
&GENERIC_FILE_CONTENT_POST_HOOK_COMMAND:{command |"generic_file_content_posthook[&i&]" string => "&command&"; | |
}& | |
&GENERIC_FILE_CONTENT_DELETION_REGEXP:{delreg |"generic_file_content_deletion_regexp[&i&]" string => "&delreg&"; | |
}& | |
&GENERIC_FILE_CONTENT_MODIFICATION_REGEXP:{delreg |"generic_file_content_modification_regexp[&i&]" string => "&delreg&"; | |
}& | |
&GENERIC_FILE_CONTENT_MODIFICATION_DESTINATION:{destination |"generic_file_content_modification_destination[&i&]" string => "&destination&"; | |
}& | |
&GENERIC_FILE_SECTION_HEADER:{header |"generic_file_content_section_header[&i&]" string => "&header&"; | |
}& | |
# Since content is multiline, it is not indented to prevent spurious space from being inserted within | |
&GENERIC_FILE_SECTION_CONTENT:{content |"generic_file_content_section_content[&i&]" string => "&content&"; | |
}& | |
&GENERIC_FILE_SECTION_FOOTER:{footer |"generic_file_content_section_footer[&i&]" string => "&footer&"; | |
}& | |
&GENERIC_FILE_CONTENT_MIGRATE_TO_ZONE_BOOLEAN:{migrate_to_zone |"migrate_to_zone[&i&]" string => "&migrate_to_zone&"; | |
}& | |
&GENERIC_FILE_CONTENT_ZONE_HEADER:{header |"generic_file_content_modification_only_zone_header[&i&]" string => "&header&"; | |
}& | |
&GENERIC_FILE_CONTENT_ZONE_FOOTER:{footer |"generic_file_content_modification_only_zone_footer[&i&]" string => "&footer&"; | |
}& | |
&TRACKINGKEY:{piuuid |"generic_file_content_uuid[&i&]" string => "&piuuid&"; | |
}& | |
# Since classes of a bundle are not visible to the bundle edit_line, we need to define variable | |
# and check their values in the bundle_edit_line | |
&GENERIC_FILE_CONTENT_DELETION_BOOLEAN:{deletion | "generic_file_content_deletion_boolean[&i&]" string => "&deletion&"; | |
}& | |
&GENERIC_FILE_CONTENT_MODIFICATION_BOOLEAN:{modification |"generic_file_content_modification_boolean[&i&]" string => "&modification&"; | |
}& | |
&GENERIC_FILE_CONTENT_SECTION_MANAGEMENT:{enforce_section |"generic_file_content_section_boolean[&i&]" string => "&enforce_section&"; | |
}& | |
"index" slist => getindices("generic_file_content_path"); | |
"file_edit_go" string => "go"; | |
# When we define the file to be checked only at creation, it means that we want to create it | |
&GENERIC_FILE_CONTENT_CREATE_BOOLEAN:{createfile | tier1.!enforce_at_creation_only_&i&:: | |
"generic_file_content_creation[&i&]" string => "&createfile&"; | |
}& | |
&GENERIC_FILE_CONTENT_CREATE_BOOLEAN:{createfile | tier1.enforce_at_creation_only_&i&:: | |
"generic_file_content_creation[&i&]" string => "true"; | |
}& | |
classes: | |
# Set a class to define when we need to run the post-modification hook | |
&GENERIC_FILE_CONTENT_POST_HOOK_RUN:{run |"execute_command_&i&" expression => strcmp("&run&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_PERMISSION_ADJUSTMENT:{adjust |"adjust_permissions_&i&" expression => strcmp("&adjust&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_DELETION_BOOLEAN:{deletion |"delete_lines_&i&" expression => strcmp("&deletion&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_MODIFICATION_BOOLEAN:{modification |"modify_lines_&i&" expression => strcmp("&modification&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_ENFORCE_CREATE_ONLY_BOOLEAN:{enforce_at_creation_only |"enforce_at_creation_only_&i&" expression => strcmp("&enforce_at_creation_only&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_SECTION_MANAGEMENT:{enforce_section |"enforce_section_&i&" expression => strcmp("&enforce_section&", "true"); | |
}& | |
&GENERIC_FILE_CONTENT_ONLY_ZONE_BOOLEAN:{only_zone |"edit_only_in_a_zone_&i&" expression => strcmp("&only_zone&", "true"); | |
}& | |
"edit_section_valid_${index}" and => { isvariable("generic_file_content_section_header[${index}]"), isvariable("generic_file_content_section_footer[${index}]") } ; | |
"file_doesnt_exist_${index}" not => fileexists("${generic_file_content_path[${index}]}"); | |
"creation_only_but_already_exists_${index}" expression => "enforce_at_creation_only_${index}.!file_doesnt_exist_${index}"; | |
# define if we need to migrate to zone | |
"migrate_to_zone_${index}" expression => strcmp("${migrate_to_zone[${index}]}", "true"); | |
# Workaround for #3014: no value = empty value | |
# In some conditions, the value of replacement is | |
# considerered as null instead of empty. | |
# This class will ensure that no variable (=null) will be considered | |
# as an empty variable. | |
"generic_file_content_modification_destination_defined_${index}" expression => isvariable("generic_file_content_modification_destination[${index}]"); | |
# Check that value has been set before to edit the file | |
"edit_content_${index}" expression => isvariable("generic_file_content_payload[${index}]"); | |
"tier1" expression => "any"; | |
"tier2" expression => isvariable("file_edit_go"); | |
files: | |
tier2:: | |
# Edit the file | |
# Defines classes for the file edition globaly, as it can be globally kept even if part are modified | |
# (for instance, section edition have a global status kept, but several repaired status) | |
# Note: it is too hard to make a single bundle for editing this file, with support of zone edition and non zone edition | |
# So, we call a different bundle_edit_line based on the type of edition we want | |
"${generic_file_content_path[${index}]}" | |
edit_line => check_generic_file_content_edition( | |
"${generic_file_content_payload[${index}]}", "${generic_file_content_enforced[${index}]}", | |
"${generic_file_content_deletion_regexp[${index}]}", "${generic_file_content_deletion_boolean[${index}]}", | |
"${generic_file_content_modification_regexp[${index}]}", "${generic_file_content_modification_destination[${index}]}", "${generic_file_content_modification_boolean[${index}]}", | |
"${generic_file_content_section_header[${index}]}", "${generic_file_content_section_footer[${index}]}", "${generic_file_content_section_content[${index}]}", "${generic_file_content_section_boolean[${index}]}", | |
"${index}" | |
), | |
create => "${generic_file_content_creation[${index}]}", | |
edit_defaults => rudder_empty_select("${generic_file_content_enforced[${index}]}"), | |
ifvarclass => "!creation_only_but_already_exists_${index}.!edit_only_in_a_zone_${index}", | |
classes => kept_if_else("file_edition_global_files_status_${index}_kept", "file_edition_global_files_status_${index}_repaired", "file_edition_global_files_status_${index}_failed"), | |
comment => "Editing ${generic_file_content_path[${index}]}..."; | |
"${generic_file_content_path[${index}]}" | |
edit_line => check_generic_file_content_edition_in_zone( | |
"${generic_file_content_payload[${index}]}", "${generic_file_content_enforced[${index}]}", | |
"${generic_file_content_deletion_regexp[${index}]}", "${generic_file_content_deletion_boolean[${index}]}", | |
"${generic_file_content_modification_regexp[${index}]}", "${generic_file_content_modification_destination[${index}]}", "${generic_file_content_modification_boolean[${index}]}", | |
"${generic_file_content_section_header[${index}]}", "${generic_file_content_section_footer[${index}]}", "${generic_file_content_section_content[${index}]}", "${generic_file_content_section_boolean[${index}]}", | |
"${generic_file_content_modification_only_zone_header[${index}]}", "${generic_file_content_modification_only_zone_footer[${index}]}", "${migrate_to_zone[${index}]}", | |
"${index}" | |
), | |
create => "${generic_file_content_creation[${index}]}", | |
edit_defaults => rudder_empty_select("${generic_file_content_enforced[${index}]}"), | |
ifvarclass => "!creation_only_but_already_exists_${index}.edit_only_in_a_zone_${index}", | |
classes => kept_if_else("file_edition_global_files_status_${index}_kept", "file_edition_global_files_status_${index}_repaired", "file_edition_global_files_status_${index}_failed"), | |
comment => "Editing ${generic_file_content_path[${index}]}..."; | |
"${generic_file_content_path[${index}]}" | |
create => "${generic_file_content_creation[${index}]}", | |
perms => mog("${generic_file_content_perms[${index}]}", "${generic_file_content_owner[${index}]}", "${generic_file_content_group[${index}]}"), | |
classes => kept_if_else("perms_${index}_kept", "perms_${index}_modified", "perms_${index}_failed"), | |
ifvarclass => "adjust_permissions_${index}.!creation_only_but_already_exists_${index}", | |
comment => "Setting ${generic_file_content_path[${index}]} permissions..."; | |
commands: | |
tier2:: | |
"${generic_file_content_posthook[${index}]}" | |
classes => if_else("generic_file_content_posthook_${index}_command_run_ok", "generic_file_content_posthook_${index}_command_run_failed"), | |
contain => in_shell, | |
ifvarclass => "execute_command_${index}.file_edition_global_files_status_${index}_repaired"; | |
reports: | |
tier2:: | |
# Files edition | |
# No line migrations | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the policy" | |
ifvarclass => "!migrate_to_zone_${index}.edit_content_${index}.((content_${index}_kept.!content_${index}_modified)|(file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired))"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated" | |
ifvarclass => "!migrate_to_zone_${index}.content_${index}_modified.file_edition_global_files_status_${index}_repaired"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated" | |
ifvarclass => "!migrate_to_zone_${index}.content_${index}_failed"; | |
# if we want to migrate lines | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the policy" | |
ifvarclass => "migrate_to_zone_${index}.edit_content_${index}.((content_${index}_kept.!content_${index}_modified.delete_out_of_zone_content_${index}_kept.!delete_out_of_zone_content_${index}_repaired)|(file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired))"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated" | |
ifvarclass => "migrate_to_zone_${index}.file_edition_global_files_status_${index}_repaired.(content_${index}_modified|delete_out_of_zone_content_${index}_repaired)"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated" | |
ifvarclass => "migrate_to_zone_${index}.(content_${index}_failed|delete_out_of_zone_content_${index}_failed)"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#No content was given to check file ${generic_file_content_path[${index}]}, skipping" | |
ifvarclass => "!edit_content_${index}"; | |
# Files edition - deletion | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Line deletion regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was not set for any line deletion" | |
ifvarclass => "!delete_lines_${index}"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Line deletion regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the deletion policy" | |
ifvarclass => "delete_lines_${index}.((content_deletion_kept_${index}.!content_deletion_modified_${index}.!content_deletion_failed_${index})|(file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired))"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Line deletion regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated using the deletion policy" | |
ifvarclass => "content_deletion_modified_${index}.file_edition_global_files_status_${index}_repaired"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Line deletion regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated using the deletion policy" | |
ifvarclass => "content_deletion_failed_${index}"; | |
# Files edition - replacement | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Line replacement regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was not set for any line replacement" | |
ifvarclass => "!modify_lines_${index}"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Line replacement regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the replacement policy" | |
ifvarclass => "content_modification_kept_${index}.!content_modification_modified_${index}.!content_modification_failed_${index}"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Line replacement regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated using the replacement policy" | |
ifvarclass => "content_modification_modified_${index}"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Line replacement regular expressions@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated using the replacement policy" | |
ifvarclass => "content_modification_failed_${index}"; | |
# File edition - enforce only at creation | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@File@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} already exists, skipping content editing" | |
ifvarclass => "edit_content_${index}.creation_only_but_already_exists_${index}"; | |
# Permissions edition | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Permission adjustment@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} uses default permissions" | |
ifvarclass => "!adjust_permissions_${index}"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Permission adjustment@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} permissions are OK" | |
ifvarclass => "perms_${index}_kept"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Permission adjustment@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} permissions were adjusted" | |
ifvarclass => "perms_${index}_modified"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Permission adjustment@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} permissions could not be adjusted" | |
ifvarclass => "perms_${index}_failed"; | |
# Permissions edition - enforce only at creation | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Permission adjustment@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already existing, skipping permission checking" | |
ifvarclass => "adjust_permissions_${index}.creation_only_but_already_exists_${index}"; | |
#Section edition | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was not set for section edition, skipping" | |
ifvarclass => "!enforce_section_${index}"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was set for section edition, but no header or footer was defined" | |
ifvarclass => "enforce_section_${index}.!edit_section_valid_${index}"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} already exists, skipping section edition" | |
ifvarclass => "enforce_section_${index}.creation_only_but_already_exists_${index}"; | |
# Section edition - No migration | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the section content policy" | |
ifvarclass => "!migrate_to_zone_${index}.enforce_section_${index}.((section_content_modification_kept_${index}.!section_content_modification_modified_${index})|(file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired))"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated using the section content policy" | |
ifvarclass => "!migrate_to_zone_${index}.section_content_modification_modified_${index}.!section_content_modification_failed_${index}.file_edition_global_files_status_${index}_repaired"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated using the section content policy" | |
ifvarclass => "!migrate_to_zone_${index}.section_content_modification_failed_${index}"; | |
# Section edition - migration | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was already in accordance with the section content policy" | |
ifvarclass => "migrate_to_zone_${index}.enforce_section_${index}.((section_content_modification_kept_${index}.!section_content_modification_modified_${index}.delete_out_of_zone_section_${index}_kept.!delete_out_of_zone_section_${index}_repaired)|(file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired))"; | |
"@@checkGenericFileContent@@result_repaired@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} was successfully updated using the section content policy" | |
ifvarclass => "migrate_to_zone_${index}.((section_content_modification_modified_${index}.!section_content_modification_failed_${index})|(delete_out_of_zone_section_${index}_repaired.!delete_out_of_zone_section_${index}_failed)).file_edition_global_files_status_${index}_repaired"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Enforce content by section@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The file ${generic_file_content_path[${index}]} could not be updated using the section content policy" | |
ifvarclass => "migrate_to_zone_${index}.(section_content_modification_failed_${index}|delete_out_of_zone_section_${index}_failed)"; | |
# Posthook report | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Post-modification hook@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#No command for ${generic_file_content_path[${index}]} was to be executed" | |
ifvarclass => "!execute_command_${index}"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Post-modification hook@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#${generic_file_content_path[${index}]} was in the proper state, so no command to execute" | |
ifvarclass => "execute_command_${index}.file_edition_global_files_status_${index}_kept.!file_edition_global_files_status_${index}_repaired"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Post-modification hook@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The command for ${generic_file_content_path[${index}]} was correctly executed" | |
ifvarclass => "generic_file_content_posthook_${index}_command_run_ok"; | |
"@@checkGenericFileContent@@result_error@@${generic_file_content_uuid[${index}]}@@Post-modification hook@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#The command for ${generic_file_content_path[${index}]} could not to be executed" | |
ifvarclass => "generic_file_content_posthook_${index}_command_run_failed"; | |
"@@checkGenericFileContent@@result_success@@${generic_file_content_uuid[${index}]}@@Post-modification hook@@${generic_file_content_path[${index}]}@@${g.execRun}##${g.uuid}@#${generic_file_content_path[${index}]} already exists, skipping command execution" | |
ifvarclass => "execute_command_${index}.creation_only_but_already_exists_${index}"; | |
} | |
# The file edition should be unitary made in this bundle | |
bundle edit_line check_generic_file_content_edition( | |
content, enforce_content_boolean, | |
deletion_regex, deletion_boolean, | |
modification_regex, modification_replacement, modification_boolean, | |
section_start, section_end, section_content, section_boolean, | |
index # For the reporting | |
) | |
{ | |
vars: | |
# define all the information for the section edition | |
"csection" string => canonify("${section_start}"); | |
"escaped_section_start" string => escape(${section_start}); | |
"escaped_section_end" string => escape(${section_end}); | |
# define the classes that will define which edition we are to do | |
classes: | |
"preserve_content" expression => strcmp("true", "${enforce_content_boolean}"); | |
# when need to check the validity of the content on the original value, otherwise local context is always true | |
"edit_content" expression => isvariable("check_generic_file_content.generic_file_content_payload[${index}]"); | |
"delete_lines" expression => strcmp("${deletion_boolean}", "true"); | |
"replace_lines" expression => strcmp("${modification_boolean}", "true"); | |
"replace_lines_destination_defined" expression => isvariable("check_generic_file_content.generic_file_content_modification_destination[${index}]"); | |
"section_edition" expression => strcmp("${section_boolean}", "true"); | |
"edit_section_valid" and => { isvariable("check_generic_file_content.generic_file_content_section_header[${index}]"), isvariable("check_generic_file_content.generic_file_content_section_footer[${index}]") } ; | |
# Detect if section is already there | |
"has_${csection}" expression => regline("${escaped_section_start}", "${edit.filename}"); | |
delete_lines: | |
delete_lines:: | |
"${deletion_regex}" | |
classes => kept_if_else("content_deletion_kept_${index}", "content_deletion_modified_${index}", "content_deletion_failed_${index}"), | |
comment => "Deleting lines using the given regexps..."; | |
section_edition.edit_section_valid:: | |
# Delete the content of the section | |
".*" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"), | |
ifvarclass => "has_${csection}"; | |
insert_lines: | |
preserve_content.edit_content:: | |
"${content}" | |
classes => kept_if_else("content_${index}_kept", "content_${index}_modified", "content_${index}_failed"), | |
insert_type => "preserve_block", | |
comment => "Editing ..."; | |
!preserve_content.edit_content:: | |
"${content}" | |
classes => kept_if_else("content_${index}_kept", "content_${index}_modified", "content_${index}_failed"), | |
comment => "Editing ..."; | |
section_edition.edit_section_valid:: | |
# Insert new, empty section if it doesn't exist already. | |
"${section_start} | |
${section_end}" | |
insert_type => "preserve_block", | |
ifvarclass => "!has_${csection}"; | |
# Insert missing lines into the section | |
"${section_content}" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"), | |
classes => kept_if_else("section_content_modification_kept_${index}", "section_content_modification_modified_${index}", "section_content_modification_failed_${index}"); | |
replace_patterns: | |
replace_lines.replace_lines_destination_defined:: | |
"${modification_regex}" | |
replace_with => value("${modification_replacement}"), | |
classes => kept_if_else("content_modification_kept_${index}", "content_modification_modified_${index}", "content_modification_failed_${index}"), | |
comment => "Replacing lines using the given regexps..."; | |
replace_lines.!replace_lines_destination_defined:: | |
"${modification_regex}" | |
replace_with => value(""), | |
classes => kept_if_else("content_modification_kept_${index}", "content_modification_modified_${index}", "content_modification_failed_${index}"), | |
comment => "Replacing lines using the given regexps..."; | |
} | |
# The file edition should be unitary made in this bundle | |
bundle edit_line check_generic_file_content_edition_in_zone( | |
content, enforce_content_boolean, | |
deletion_regex, deletion_boolean, | |
modification_regex, modification_replacement, modification_boolean, | |
section_start, section_end, section_content, section_boolean, | |
zone_start, zone_end, migrate_to_zone, | |
index # For the reporting | |
) | |
{ | |
vars: | |
# define all the information for the section edition | |
"csection" string => canonify("${section_start}"); | |
"escaped_section_start" string => escape(${section_start}); | |
"escaped_section_end" string => escape(${section_end}); | |
"section_delimiters" slist => { "${escaped_section_start}", "${escaped_section_end}" }; | |
"escaped_zone_start" string => escape(${zone_start}); | |
"escaped_zone_end" string => escape(${zone_end}); | |
# define the classes that will define which edition we are to do | |
classes: | |
# CAUTION, the semantic of "preserve content" means we empty the file in this technique | |
"preserve_content" expression => strcmp("true", "${enforce_content_boolean}"); | |
# when need to check the validity of the content on the original value, otherwise local context is always true | |
"edit_content" expression => isvariable("check_generic_file_content.generic_file_content_payload[${index}]"); | |
"delete_lines" expression => strcmp("${deletion_boolean}", "true"); | |
"replace_lines" expression => strcmp("${modification_boolean}", "true"); | |
"replace_lines_destination_defined" expression => isvariable("check_generic_file_content.generic_file_content_modification_destination[${index}]"); | |
"section_edition" expression => strcmp("${section_boolean}", "true"); | |
"edit_section_valid" and => { isvariable("check_generic_file_content.generic_file_content_section_header[${index}]"), isvariable("check_generic_file_content.generic_file_content_section_footer[${index}]") } ; | |
!preserve_content:: | |
# Detect if section is already there | |
# computation in this case is more complex: | |
# if section already inside of zone, we can edit it | |
# if section is outside of zone then remove it, and add it back in the zone | |
# so always delete the content of the section, then delete section out of zone. then ensure header and footer section in zone. and add content in it | |
"has_${csection}" expression => regline("${escaped_section_start}", "${edit.filename}"); | |
# i can edit only if zone is there | |
"has_begin_zone" expression => regline("${zone_start}", "${edit.filename}"); | |
"has_end_zone" expression => regline("${zone_end}", "${edit.filename}"); | |
"end_zone_defined" not => strcmp("", "${zone_end}"); | |
"has_zone" expression => "has_begin_zone.(has_end_zone|!end_zone_defined)"; | |
any:: | |
# If we migrate to zone, then lines ensured from the zone would be removed from outside the zone | |
"migrate_to_zone" expression => strcmp("${migrate_to_zone}", "true"); | |
"pass_two" expression => "pass_one"; | |
"pass_one" expression => "any"; | |
delete_lines: | |
delete_lines.pass_two:: | |
"${deletion_regex}" | |
classes => kept_if_else("content_deletion_kept_${index}", "content_deletion_modified_${index}", "content_deletion_failed_${index}"), | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
comment => "Deleting lines in zone using the given regexps..."; | |
section_edition.edit_section_valid:: | |
# Delete the content of the section | |
".*" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"), | |
ifvarclass => "has_${csection}"; | |
# move section to zone if we decide to do so | |
# to move, we delete from everywhere, and add it back in the proper location | |
section_edition.migrate_to_zone.edit_section_valid:: | |
"${section_delimiters}" | |
classes => rudder_common_classes("delete_out_of_zone_section_${index}"), | |
comment => "Removing matched lines out of zone ..."; | |
# remove line out of zone if we decide to do so | |
edit_content.migrate_to_zone.pass_two:: | |
"${content}" | |
classes => rudder_common_classes("delete_out_of_zone_content_${index}"), | |
comment => "Removing matched lines out of zone ..."; | |
insert_lines: | |
!has_zone:: | |
"${zone_start} | |
${zone_end}"; | |
preserve_content.edit_content.pass_two:: | |
"${content}" | |
classes => kept_if_else("content_${index}_kept", "content_${index}_modified", "content_${index}_failed"), | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
insert_type => "preserve_block", | |
comment => "Editing ..."; | |
!preserve_content.edit_content.pass_two:: | |
"${content}" | |
classes => kept_if_else("content_${index}_kept", "content_${index}_modified", "content_${index}_failed"), | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
comment => "Editing ..."; | |
section_edition.edit_section_valid.pass_two:: | |
# Insert new, empty section always, as we remove it always to empty it | |
"${section_start} | |
${section_end}" | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
insert_type => "preserve_block"; | |
# Insert missing lines into the section | |
"${section_content}" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"), | |
classes => kept_if_else("section_content_modification_kept_${index}", "section_content_modification_modified_${index}", "section_content_modification_failed_${index}"); | |
replace_patterns: | |
replace_lines.replace_lines_destination_defined:: | |
"${modification_regex}" | |
replace_with => value("${modification_replacement}"), | |
classes => kept_if_else("content_modification_kept_${index}", "content_modification_modified_${index}", "content_modification_failed_${index}"), | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
comment => "Replacing lines using the given regexps..."; | |
replace_lines.!replace_lines_destination_defined:: | |
"${modification_regex}" | |
replace_with => value(""), | |
classes => kept_if_else("content_modification_kept_${index}", "content_modification_modified_${index}", "content_modification_failed_${index}"), | |
select_region => rudder_section_selector("${escaped_zone_start}", "${escaped_zone_end}"), | |
comment => "Replacing lines using the given regexps..."; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent download_from_shared_folder | |
{ | |
vars: | |
©FILE_NAME:{name |"copyfile[&i&][name]" string => "&name&"; | |
}& | |
©FILE_EXCLUDE_INCLUDE:{exclude_include |"copyfile[&i&][exclude_include]" string => "&exclude_include&"; | |
}& | |
©FILE_EXCLUDE_INCLUDE_OPTION:{exclude_include_option |"copyfile[&i&][exclude_include_option]" string => "&exclude_include_option&"; | |
}& | |
©FILE_RECURSION:{rec |"copyfile[&i&][recursion]" string => "&rec&"; | |
}& | |
©FILE_OWNER:{owner |"copyfile[&i&][owner]" string => "&owner&"; | |
}& | |
©FILE_GROUP:{group |"copyfile[&i&][group]" string => "&group&"; | |
}& | |
©FILE_PURGE:{purge |"copyfile[&i&][purge]" string => "&purge&"; | |
}& | |
©FILE_COMPARE_METHOD:{compare_method |"copyfile[&i&][compare_method]" string => "&compare_method&"; | |
}& | |
©FILE_PERM:{perms |"copyfile[&i&][perm]" string => "&perms&"; | |
}& | |
©FILE_DESTINATION:{destination |"copyfile[&i&][destination]" string => "&destination&"; | |
}& | |
©FILE_POST_HOOK_COMMAND:{command |"copyfile[&i&][posthook]" string => "&command&"; | |
}& | |
&TRACKINGKEY:{piuuid |"copyfile[&i&][uuid]" string => "&piuuid&"; | |
}& | |
"shared_folder" string => "&SHARED_FILES_FOLDER&"; | |
"index" slist => getindices("copyfile"); | |
iteration_1:: | |
"extended_modes_${index}" | |
string => "4", | |
ifvarclass => "enable_suid_${index}.!enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "2", | |
ifvarclass => "!enable_suid_${index}.enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "6", | |
ifvarclass => "enable_suid_${index}.enable_sgid_${index}"; | |
"extended_modes_${index}" | |
string => "0", | |
ifvarclass => "!enable_suid_${index}.!enable_sgid_${index}"; | |
classes: | |
"is_valid" not => strcmp("&SHARED_FILES_FOLDER&", ""); | |
"exist_${index}" expression => fileexists("${copyfile[${index}][destination]}"); | |
"is_file_${index}" not => isdir("${copyfile[${index}][destination]}"); | |
"copy_file_${index}_dest_notdir" not => isdir(dirname("${copyfile[${index}][destination]}")); | |
"copy_file_${index}_user_absent" not => userexists("${copyfile[${index}][owner]}"); | |
"copy_file_${index}_group_absent" not => groupexists("${copyfile[${index}][group]}"); | |
"need_exclusion_${index}" and => { isvariable("copyfile[${index}][exclude_include]"), strcmp("${copyfile[${index}][exclude_include_option]}", "exclude") }; | |
"need_inclusion_${index}" and => { isvariable("copyfile[${index}][exclude_include]"), strcmp("${copyfile[${index}][exclude_include_option]}", "include") }; | |
"apply_regex_${index}" or => { "need_exclusion_${index}", "need_inclusion_${index}"}; | |
©FILE_SUID:{suid |"enable_suid_&i&" expression => strcmp("&suid&", "true"); | |
}& | |
©FILE_SGID:{sgid |"enable_sgid_&i&" expression => strcmp("&sgid&", "true"); | |
}& | |
# Set a class to define when we need to run the post-modification hook | |
©FILE_POST_HOOK_RUN:{run |"execute_command_&i&" expression => strcmp("&run&", "true"); | |
}& | |
"iteration_2" expression => "iteration_1"; | |
"iteration_1" expression => "any"; | |
files: | |
is_valid.iteration_2:: | |
# If it's a directory, without exclusion | |
"${copyfile[${index}][destination]}" | |
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"), | |
depth_search => recurse("${copyfile[${index}][recursion]}"), | |
perms => mog( | |
"${copyfile[${index}][perm]}", | |
"${copyfile[${index}][owner]}", | |
"${copyfile[${index}][group]}" | |
), | |
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", | |
classes => rudder_common_classes("copy_file_${index}"), | |
ifvarclass => "(!exist_${index}|!is_file_${index}).!apply_regex_${index}"; | |
# If it's a directory, with exclusion | |
"${copyfile[${index}][destination]}" | |
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"), | |
depth_search => recurse("${copyfile[${index}][recursion]}"), | |
file_select => exclude("${copyfile[${index}][exclude_include]}"), | |
perms => mog( | |
"${copyfile[${index}][perm]}", | |
"${copyfile[${index}][owner]}", | |
"${copyfile[${index}][group]}" | |
), | |
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method", | |
classes => rudder_common_classes("copy_file_${index}"), | |
ifvarclass => "(!exist_${index}|!is_file_${index}).need_exclusion_${index}"; | |
# If it's a directory, with inclusion | |
"${copyfile[${index}][destination]}" | |
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"), | |
depth_search => recurse("${copyfile[${index}][recursion]}"), | |
file_select => by_name("${copyfile[${index}][exclude_include]}"), | |
perms => mog( | |
"${copyfile[${index}][perm]}", | |
"${copyfile[${index}][owner]}", | |
"${copyfile[${index}][group]}" | |
), | |
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method with inclusion of '${copyfile[${index}][exclude_include]}'", | |
classes => rudder_common_classes("copy_file_${index}"), | |
ifvarclass => "(!exist_${index}|!is_file_${index}).need_inclusion_${index}"; | |
# If it s a file, the depth_search prevents from enforcing the file content | |
# Besides it is possible to specify suid or sgid only for a file since this | |
# is too dangerous to apply suid or sgid recursively and only copy an empty | |
# directory does not make sense. | |
# Don't take purge in account as well. | |
"${copyfile[${index}][destination]}" | |
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"), | |
perms => mog( | |
"${extended_modes_${index}}${copyfile[${index}][perm]}", | |
"${copyfile[${index}][owner]}", | |
"${copyfile[${index}][group]}" | |
), | |
comment => "Enforce content of file ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method with exclusion of '${copyfile[${index}][exclude_include]}'", | |
classes => rudder_common_classes("copy_file_${index}"), | |
ifvarclass => "exist_${index}.is_file_${index}"; | |
commands: | |
"${copyfile[${index}][posthook]}" | |
contain => in_shell, | |
classes => if_else("copyfile_posthook_${index}_command_run_ok", "copyfile_posthook_${index}_command_run_failed"), | |
ifvarclass => "execute_command_${index}.copy_file_${index}_repaired.!copy_file_${index}_error", | |
comment => "Execute the posthook command if a file was changed"; | |
reports: | |
!is_valid:: | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#There is no shared folder on the Rudder Server, so it's not possible to copy a file from it"; | |
is_valid:: | |
"@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content of the file(s) is valid" | |
ifvarclass => "copy_file_${index}_kept.!copy_file_${index}_repaired.!copy_file_${index}_error"; | |
"@@copyFile@@result_repaired@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content or permissions of the file(s) has been repaired" | |
ifvarclass => "copy_file_${index}_repaired.!copy_file_${index}_error"; | |
# Error conditons | |
## The destination is not an existing directory | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The copy of the file failed: the destination (${copyfile[${index}][destination]}) is not stored in a valid directory" | |
ifvarclass => "copy_file_${index}_dest_notdir"; | |
## File access denied | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The copy of the file failed: access to ${copyfile[${index}][name]} denied by the server" | |
ifvarclass => "copy_file_${index}_denied"; | |
## User does not exist | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The permissions could not be applied on the file: user \"${copyfile[${index}][owner]}\" not found" | |
ifvarclass => "copy_file_${index}_user_absent"; | |
## Group does not exist | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The permissions could not be applied on the file: group \"${copyfile[${index}][group]}\" not found" | |
ifvarclass => "copy_file_${index}_group_absent"; | |
## Generic failure | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Copy file@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The content or permissions of the file(s) could not have been repaired (file not found?)" | |
ifvarclass => "copy_file_${index}_error.!copy_file_${index}_dest_notdir.!copy_file_${index}_denied.!copy_file_${index}_user_absent.!copy_file_${index}_group_absent"; | |
#posthook reports | |
"@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#No post-hook command for ${copyfile[${index}][destination]} was defined, not executing" | |
ifvarclass => "!execute_command_${index}"; | |
"@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#${copyfile[${index}][destination]} was already in the desired state, so no command was executed" | |
ifvarclass => "execute_command_${index}.copy_file_${index}_kept.!copy_file_${index}_repaired"; | |
"@@copyFile@@result_success@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The post-hook command for ${copyfile[${index}][destination]} was correctly executed" | |
ifvarclass => "copyfile_posthook_${index}_command_run_ok"; | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#The post-hook command for ${copyfile[${index}][destination]} couldn't be executed" | |
ifvarclass => "copyfile_posthook_${index}_command_run_failed"; | |
# A copy_from + perms could result in any combinaision of success/repaired/failed, so we have to cover the failed.modified which results in no copy | |
"@@copyFile@@result_error@@${copyfile[${index}][uuid]}@@Post-modification hook@@${copyfile[${index}][name]}@@${g.execRun}##${g.uuid}@#${copyfile[${index}][destination]} couldn't be copied, so the post-hook command is not executed" | |
ifvarclass => "execute_command_${index}.copy_file_${index}_error"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################### | |
# Download a file from an arbitrary http/https/ftp server # | |
########################################################### | |
bundle agent execute_file_download # WARNING : If there is many instance, isn't there a risk of a bundle name collision ??? | |
{ | |
vars: | |
# If curl is here, use it | |
!windows.curl_installed:: | |
"download_command" string => "${g.rudder_curl} -f --proxy '' -o \"&DOWNLOADFILE_DESTINATION&\" &DOWNLOADFILE_SOURCE&"; | |
# If no curl is present, fallback to minicurl | |
!windows.!curl_installed:: | |
"download_command" string => "${g.minicurl} --get --file \"&DOWNLOADFILE_DESTINATION&\" --url &DOWNLOADFILE_SOURCE&"; | |
# Windows always use curl | |
windows:: | |
"download_command" string => "\"${g.rudder_curl}\" -f --proxy '' -o \"&DOWNLOADFILE_DESTINATION&\" &DOWNLOADFILE_SOURCE&"; | |
classes: | |
"file_not_found" not => fileexists("&DOWNLOADFILE_DESTINATION&"); | |
files: | |
!windows:: | |
"&DOWNLOADFILE_DESTINATION&" | |
pathtype => "literal", # force literal interpretation | |
perms => mog("&DOWNLOADFILE_MODE&","&DOWNLOADFILE_USER&","&DOWNLOADFILE_GROUP&"), | |
classes => kept_if_else("file_perms_idle", "file_perms_ok", "file_perms_fail"); | |
commands: | |
file_not_found:: | |
"${download_command}" | |
comment => "Getting the file from the server", | |
classes => kept_if_else("file_download_idle", "file_download_ok", "file_download_fail"); | |
reports: | |
# File downloading part | |
!curl_installed:: | |
"@@downloadFile@@log_info@@&TRACKINGKEY&@@Download a file@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#No usable cURL binary detected, falling back to miniperl instead"; | |
!file_not_found.!file_download_ok.!file_download_fail:: | |
"@@downloadFile@@result_success@@&TRACKINGKEY&@@Download a file@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The file &DOWNLOADFILE_SOURCE& already present"; | |
file_download_ok.!file_download_fail:: | |
"@@downloadFile@@result_repaired@@&TRACKINGKEY&@@Download a file@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The file &DOWNLOADFILE_SOURCE& has been successfully downloaded"; | |
file_download_fail:: | |
"@@downloadFile@@result_error@@&TRACKINGKEY&@@Download a file@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The file &DOWNLOADFILE_SOURCE& was could not be downloaded"; | |
# File permissions part | |
!windows.file_perms_idle.!file_perms_ok.!file_perms_fail:: | |
"@@downloadFile@@result_success@@&TRACKINGKEY&@@Permissions (on UNIX systems)@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The permissions on file &DOWNLOADFILE_SOURCE& are ok. Skipping ..."; | |
!windows.file_perms_ok.!file_perms_fail:: | |
"@@downloadFile@@result_repaired@@&TRACKINGKEY&@@Permissions (on UNIX systems)@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The permissions on file &DOWNLOADFILE_SOURCE& were successfully fixed"; | |
!windows.file_perms_fail:: | |
"@@downloadFile@@result_error@@&TRACKINGKEY&@@Permissions (on UNIX systems)@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#The permissions on file &DOWNLOADFILE_SOURCE& were could not be fixed"; | |
windows:: | |
"@@downloadFile@@result_success@@&TRACKINGKEY&@@Permissions (on UNIX systems)@@&DOWNLOADFILE_SOURCE&@@${g.execRun}##${g.uuid}@#This is a windows machine. The &DOWNLOADFILE_SOURCE& file permissions will not be altered."; | |
} | |
bundle agent job_scheduler | |
{ | |
vars: | |
"all_hours" slist => { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" }; | |
&JOB_COMMAND:{command |"job_scheduler_command[&i&]" string => "&command&"; | |
}& | |
&JOB_TIMEOUT:{timeout |"job_scheduler_timeout[&i&]" string => "&timeout&"; | |
}& | |
&JOB_KEPTCODES:{keptcodes |"job_scheduler_keptcodes[&i&]" string => "&keptcodes&"; | |
}& | |
&JOB_REPAIRCODES:{repaircodes |"job_scheduler_repaircodes[&i&]" string => "&repaircodes&"; | |
}& | |
&JOB_ERRORCODES:{errorcodes |"job_scheduler_errorcodes[&i&]" string => "&errorcodes&"; | |
}& | |
&JOB_TIME_MIN:{mintime |"job_scheduler_time_min[&i&]" string => "&mintime&"; | |
}& | |
&JOB_TIME_MAX:{maxtime |"job_scheduler_time_max[&i&]" string => "&maxtime&"; | |
}& | |
&TRACKINGKEY:{uuid |"job_scheduler_uuids[&i&]" string => "&uuid&"; | |
}& | |
"iterator" slist => getindices("job_scheduler_uuids"); | |
"job_scheduler_canon_name[${iterator}]" string => canonify("${job_scheduler_command[${iterator}]}"); | |
"kept_returncodes_${iterator}" slist => splitstring("${job_scheduler_keptcodes[${iterator}]}",",","128"); | |
"repaired_returncodes_${iterator}" slist => splitstring("${job_scheduler_repaircodes[${iterator}]}",",","128"); | |
"error_returncodes_${iterator}" slist => splitstring("${job_scheduler_errorcodes[${iterator}]}",",","128"); | |
nos:: | |
"test_hours_${iterator}[${all_hours}]" string => "job_scheduler_${all_hours}_${iterator}", | |
ifvarclass => "test_${all_hours}_${iterator}"; | |
# This should work, but produces errors when CFEngine checks the promises like: "Unable to parse class expression: [garbage]" | |
# ifvarclass => or(and(isgreaterthan("${all_hours}", "${job_scheduler_time_min[${iterator}]}"), islessthan("${all_hours}", "${job_scheduler_time_max[${iterator}]}")), strcmp("${job_scheduler_time_min[${iterator}]}", "${all_hours}")); | |
nos2:: | |
"test_hours_list_${iterator}" slist => getvalues("test_hours_${iterator}"); | |
classes: | |
"job_scheduler_random_time" expression => splayclass("${sys.host}${sys.ipv4}","hourly"); | |
# This is only necessary because the above ifvarclass produces errors like: "Unable to parse class expression: [garbage]" | |
"test_${all_hours}_enclosed_${iterator}" and => { isgreaterthan("${all_hours}", "${job_scheduler_time_min[${iterator}]}"), islessthan("${all_hours}", "${job_scheduler_time_max[${iterator}]}") }; | |
"test_${all_hours}_${iterator}" or => { "test_${all_hours}_enclosed_${iterator}", strcmp("${job_scheduler_time_min[${iterator}]}", "${all_hours}") }; | |
nos2:: | |
"run_time_${iterator}" select_class => { "@{test_hours_list_${iterator}}" }; | |
any:: | |
"nos2" expression => "nos"; | |
"nos" expression => "any"; | |
commands: | |
nos2:: | |
"${job_scheduler_command[${iterator}]}" | |
action => bg("10", "${job_scheduler_timeout[${iterator}]}"), | |
contain => in_shell, | |
ifvarclass => "job_scheduler_${all_hours}_${iterator}.Hr${all_hours}.job_scheduler_random_time.!job_scheduler_lock_${iterator}", | |
classes => kept_if_else_exclusive_persist("${job_scheduler_canon_name[${iterator}]}_ok", | |
"${job_scheduler_canon_name[${iterator}]}_repaired", | |
"${job_scheduler_canon_name[${iterator}]}_failed", | |
"1440", # Persist the reporting classes for 24 hours, this PT deals with daily jobs (for now anyway) | |
"@{job_scheduler.kept_returncodes_${iterator}}", | |
"@{job_scheduler.repaired_returncodes_${iterator}}", | |
"@{job_scheduler.error_returncodes_${iterator}}"); | |
reports: | |
nos2:: | |
# Note: if the command has not been executed (ever or since > frequency), no report will be sent until the splayclass is defined | |
# This will cause Rudder to report an "Unknown" status, and is by design | |
"@@jobScheduler@@result_success@@${job_scheduler_uuids[${iterator}]}@@Job@@${job_scheduler_command[${iterator}]}@@${g.execRun}##${g.uuid}@#Job returned a success return code after the last completed execution (${job_scheduler_command[${iterator}]})" | |
ifvarclass => "${job_scheduler_canon_name[${iterator}]}_ok"; | |
"@@jobScheduler@@result_repaired@@${job_scheduler_uuids[${iterator}]}@@Job@@${job_scheduler_command[${iterator}]}@@${g.execRun}##${g.uuid}@#Job returned a repaired return code on last completed execution (${job_scheduler_command[${iterator}]})" | |
ifvarclass => "${job_scheduler_canon_name[${iterator}]}_repaired"; | |
"@@jobScheduler@@result_error@@${job_scheduler_uuids[${iterator}]}@@Job@@${job_scheduler_command[${iterator}]}@@${g.execRun}##${g.uuid}@#Job failed on last completed execution (${job_scheduler_command[${iterator}]})" | |
ifvarclass => "${job_scheduler_canon_name[${iterator}]}_failed"; | |
"@@jobScheduler@@log_info@@${job_scheduler_uuids[${iterator}]}@@Job@@${job_scheduler_command[${iterator}]}@@${g.execRun}##${g.uuid}@#Job has been launched (${job_scheduler_command[${iterator}]}), result will be reported on next run" | |
ifvarclass => "job_scheduler_${all_hours}_${iterator}.Hr${all_hours}.job_scheduler_random_time.!job_scheduler_lock_${iterator}", | |
# we define here the persistent class, as the command exection is done on the last iteration | |
comment => "Define a persistent class to prevent multiple job executions", | |
classes => rudder_always_classes_persist("job_scheduler_lock_${iterator}", "5"); | |
"@@jobScheduler@@log_info@@${job_scheduler_uuids[${iterator}]}@@Job@@${job_scheduler_command[${iterator}]}@@${g.execRun}##${g.uuid}@#The command will be run at a random time after ${all_hours}:00 on this node (${job_scheduler_command[${iterator}]})" | |
ifvarclass => "job_scheduler_${all_hours}_${iterator}"; | |
} | |
body classes kept_if_else_exclusive_persist(kept, repaired, failed, persist, keptcodes, repairedcodes, errorcodes) | |
{ | |
kept_returncodes => { "@{keptcodes}" }; | |
repaired_returncodes => { "@{repairedcodes}" }; | |
failed_returncodes => { "@{errorcodes}" }; | |
promise_kept => { "${kept}" }; | |
cancel_kept => { "${repaired}", "${failed}" }; | |
promise_repaired => { "${repaired}" }; | |
cancel_repaired => { "${kept}", "${failed}" }; | |
repair_failed => { "${failed}" }; | |
repair_denied => { "${failed}" }; | |
repair_timeout => { "${failed}" }; | |
cancel_notkept => { "${kept}", "${repaired}" }; | |
persist_time => "${persist}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Failsafe file | |
# | |
body common control | |
{ | |
bundlesequence => { "check_lock_db_problem", "init_files", "update" }; | |
inputs => { "common/1.0/update.cf" }; | |
output_prefix => "rudder"; | |
} | |
body agent control { | |
skipidentify => "&SKIPIDENTIFY&"; | |
} | |
bundle common g | |
{ | |
vars: | |
android:: | |
"rudder_base" string => "/data/rudder"; | |
"rudder_var" string => "/data/rudder"; | |
!windows.!android:: | |
"rudder_base" string => "/opt/rudder"; | |
solaris:: | |
"rudder_var" string => "/opt/rudder/var"; | |
!windows.!android.!solaris:: | |
"rudder_var" string => "/var/rudder"; | |
!windows:: | |
"rudder_bin" string => "${rudder_base}/bin"; | |
"rudder_sbin" string => "${rudder_base}/sbin"; | |
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed | |
"rudder_tools" string => "${rudder_var}/tools"; | |
"rudder_ncf" string => "${rudder_var}/ncf"; | |
&if(NOVA)& | |
windows:: | |
"rudder_base" string => "${sys.winprogdir}\Rudder"; | |
"rudder_var" string => "${sys.winprogdir}\Rudder\var"; | |
"rudder_bin" string => "${rudder_base}\bin"; | |
"rudder_sbin" string => "${rudder_base}\sbin"; | |
"rudder_tools" string => "${rudder_sbin}"; | |
"rudder_ncf" string => "${rudder_var}\ncf"; | |
&endif& | |
any:: | |
"uuid" string => "&UUID&"; | |
"excludedreps" slist => { "\.X11", ".*kde.*", "\.svn", "perl" }; | |
"rudder_tools_origin" string => "/var/rudder/tools"; | |
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree"; | |
"rudder_ncf_origin_local" string => "&CONFIGURATION_REPOSITORY_FOLDER&/ncf"; | |
"rudder_tools_updated_origin" string => "${rudder_tools_origin}/rudder_tools_updated"; | |
"rudder_tools_updated" string => "${rudder_tools}/rudder_tools_updated"; | |
# The time at which the execution started | |
(linux|cygwin).!(centos_3|redhat_3|centos_4|redhat_4):: | |
"execRun" string => execresult("/bin/date --rfc-3339=second", "noshell"); | |
(linux|cygwin).(centos_3|redhat_3|centos_4|redhat_4):: | |
# We would like to use date's "--rfc-3339=second" option here, but it is not available on older OSes (RHEL 3/4, AIX 5...) | |
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell"); | |
&if(NOVA)& | |
windows.!cygwin:: | |
"execRun" string => execresult("\"${g.rudder_sbin}\getDate.bat\"", "noshell"); | |
&endif& | |
android:: | |
"execRun" string => execresult("/system/xbin/date \"+%Y-%m-%d %T+02:00\"", "noshell"); | |
aix:: | |
# AIX's date command doesn't have a "%z" option, so we fake it by using UTC | |
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell"); | |
!linux.!cygwin.!windows.!android.!aix:: | |
"execRun" string => execresult("/bin/date \"+%Y-%m-%d %T%:z\"", "noshell"); | |
# definition of the node roles | |
&NODEROLE& | |
} | |
bundle common rudder_roles | |
{ | |
classes: | |
# Abort if no uuid is defined | |
"should_not_continue" not => fileexists("${g.uuid_file}"); | |
# Policy Server is a machine which delivers promises | |
"policy_server" expression => strcmp("root","${g.uuid}"); | |
# Root Server is the top policy server machine | |
"root_server" expression => strcmp("root","${g.uuid}"); | |
# We are in the failsafe phase | |
"failsafe" expression => "any"; | |
} | |
############################################ | |
#generate a key if not present | |
bundle agent init_files | |
{ | |
vars: | |
"components" slist => { "cf-agent", "cf-serverd", "cf-execd", "cf-monitord", "cf-promises", "cf-runagent", "cf-key", "cf-hub" }; | |
nova_edition:: | |
"cfengine_install_path" string => "/usr/local"; | |
community_edition:: | |
"cfengine_install_path" string => "${g.rudder_base}"; | |
classes: | |
"missing_key" not => fileexists("${sys.workdir}/ppkeys/localhost.priv"); | |
files: | |
cfengine_community.!windows:: | |
"${sys.workdir}/bin/${components}" | |
perms => u_p("700"), | |
copy_from => cp("${cfengine_install_path}/bin/${components}","localhost"), | |
action => immediate; | |
commands: | |
cygwin.missing_key:: | |
"${sys.workdir}/bin/cf-key.exe"; | |
&if(NOVA)& | |
windows.missing_key.!cygwin:: | |
"\"${sys.workdir}\bin\cf-key\""; | |
&endif& | |
!windows.!cygwin.missing_key:: | |
"${sys.workdir}/bin/cf-key"; | |
} | |
# This bundle will check the "last successful inputs update", and if it is older | |
# than 1 hour, remove cf_lock.db (and only this DB), to give CFEngine a chance | |
# to run properly again. | |
bundle agent check_lock_db_problem{ | |
vars: | |
cfengine_3_0|cfengine_3_1|cfengine_3_2:: | |
"cf_lock_filename" string => "cf_lock.db"; | |
!(cfengine_3_0|cfengine_3_1|cfengine_3_2):: | |
"cf_lock_filename" string => "cf_lock.tcdb"; | |
files: | |
# The aim of this promise is to create a class when this file is older | |
# than one hour. The class can not be created without touching but in | |
# order to not modifing the mtime we use WarnOnly. | |
"${sys.workdir}/last_successful_inputs_update" | |
file_select => over_an_hour, | |
touch => "true", | |
action => WarnOnly, | |
classes => success("last_successful_inputs_update_too_old", "last_successful_inputs_update_check_error", "last_successful_inputs_update_ok"); | |
"${sys.workdir}/state/${cf_lock_filename}" | |
delete => tidy, | |
ifvarclass => "last_successful_inputs_update_too_old", | |
classes => success("cf_lock_removed", "cf_lock_error_removing", "cf_lock_not_deleted"); | |
reports: | |
cf_lock_removed:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Promises had not been updated for over an hour, this could indicate a broken lockfile. cf_lock DB file was removed."; | |
cf_lock_error_removing:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Promises have not been updated for over an hour, this could indicate a broken lockfile, but an error occured when trying to remove it"; | |
} | |
body file_select over_an_hour() | |
{ | |
# Select file which are older than one hour | |
# Use of positive mtime instead of negative one | |
# In order to avoid corner effects | |
mtime => irange(ago(0,0,0,1,0,0), now); | |
file_result => "!mtime"; | |
} | |
body depth_search recurse(d) | |
{ | |
depth => "${d}"; | |
} | |
#perms validation | |
body perms u_p(p) | |
{ | |
mode => "${p}"; | |
} | |
#server may be a list | |
body copy_from cp(from,server) | |
{ | |
servers => { "${server}" }; | |
source => "${from}"; | |
compare => "digest"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
body copy_from copy_digest(from) | |
{ | |
source => "${from}"; | |
copy_backup => "false"; | |
preserve => "true"; | |
compare => "digest"; | |
} | |
body action immediate | |
{ | |
ifelapsed => "0"; | |
} | |
body depth_search recurse_ignore(d,list) | |
{ | |
depth => "${d}"; | |
exclude_dirs => { @{list} }; | |
} | |
body delete tidy | |
{ | |
dirlinks => "delete"; | |
rmdirs => "true"; | |
} | |
body action WarnOnly | |
{ | |
action_policy => "warn"; | |
} | |
body file_select exclude(name) | |
{ | |
leaf_name => { "${name}"}; | |
file_result => "!leaf_name"; | |
} | |
&GENERATIONTIMESTAMP& | |
#!/usr/bin/env perl | |
# | |
##################################################################################### | |
# Copyright 2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# This script uploads or downloads a file using Perl's LWP library and PUT/GET HTTP method. | |
# | |
use strict; | |
use warnings; | |
use Getopt::Long; | |
# HTTP operations | |
use LWP::UserAgent; | |
use HTTP::Request::Common; | |
use MIME::Base64 qw( encode_base64 ); | |
# File handling | |
use File::Basename; | |
# Version | |
my $program_name = "minicurl.pl"; | |
my $program_version = "1.0"; | |
my $program_description = "Perl HTTP, HTTP/S, FTP download and upload tool"; | |
## Argument handling (Getopt) | |
my ($get, $put, $httpstatus, $help, $debug, $version); | |
$get = $put = $httpstatus = $help = $debug = $version = 0; | |
my ($url, $file, $authentication, $response); | |
$url = $file = $authentication = $response = ''; | |
GetOptions( "get!" => \$get, | |
"put!" => \$put, | |
"url:s" => \$url, | |
"file:s" => \$file, | |
"authentication=s" => \$authentication, | |
"http-status!" => \$httpstatus, | |
"help!" => \$help, | |
"debug!" => \$debug, | |
"version!" => \$version); | |
sub usage { | |
print "This is " . $program_name . ", v" . $program_version . ": " . $program_description . "\n"; | |
print "Usage: $0 [--help] [--debug] [--http-status] [--authentication <user:password>] --get/--put --url <url> --file <file>\n"; | |
} | |
if ($version >= 1) { | |
print $program_name . ", version " . $program_version . "\n"; | |
exit(0); | |
} elsif ($help >= 1) { | |
usage(); | |
exit(0); | |
} | |
if ($get == $put) { | |
print "ERROR: Please specify only one method to use.\n"; | |
usage(); | |
exit(1); | |
} elsif ($url eq "" || $file eq "") { | |
print "ERROR: The --url and --file arguments are mandatory!\n"; | |
usage(); | |
exit(1); | |
} | |
# Build the file basename | |
my $file_basename = basename($file); | |
# Create a HTTP Basic authentication string if applicable | |
$authentication = encode_base64($authentication) if ($authentication ne ""); | |
# Make sure we use SSLv3 at least while connecting to HTTP/S | |
$ENV{HTTPS_VERSION} = 3; | |
# Create a new LWP object | |
my $ua = LWP::UserAgent->new; | |
if ($put == 1) { | |
# PUT | |
# Create a variable from the target file | |
my $message; | |
open(my $fh, '<', $file) or die "ERROR: Unable to open file $file.\n"; | |
{ | |
local $/; | |
$message = <$fh>; | |
} | |
close($fh); | |
# Send the file using the PUT method | |
if ($authentication eq "") { | |
$response = $ua->request(PUT $url . $file_basename, Content => $message); | |
} else { | |
$response = $ua->request(PUT $url . "/" . $file_basename, Authorization => "Basic " . $authentication, Content => $message); | |
} | |
} else { | |
# GET | |
# Get the file using the GET method | |
if ($authentication eq "") { | |
$response = $ua->request(GET $url); | |
} else { | |
$response = $ua->request(GET $url, Authorization => "Basic " . $authentication); | |
} | |
open my $fh, ">", $file or die("ERROR: Unable to open file $file.\n"); | |
print $fh $response->content; | |
} | |
if ($response->is_success) { | |
print "OK (" . $response->status_line . ")\n" if ($debug >= 1); | |
print $response->code . "\n" if ($httpstatus >= 1); | |
exit(0); | |
} | |
else { | |
print "FAILED (" . $response->status_line . ")\n" if ($debug >= 1); | |
print $response->code . "\n" if ($httpstatus >= 1); | |
exit(1); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
####################################################### | |
# | |
# promises.cf | |
# | |
####################################################### | |
body common control | |
{ | |
any:: | |
output_prefix => "rudder"; | |
inputs => { | |
@{va.ncf_inputs}, | |
&INPUTLIST& | |
}; | |
bundlesequence => { @{va.bs} &BUNDLELIST& , @{va.end} }; | |
android:: | |
# if native syslog is not available, use cfengine implementation (eg: android) | |
syslog_host => "${server_info.cfserved}"; | |
syslog_port => "&SYSLOGPORT&"; | |
} | |
bundle common va | |
{ | |
vars: | |
policy_server:: | |
"bs" slist => { | |
"startExecution", | |
"check_disable_agent", | |
"clean_red_button", | |
"update", | |
"set_red_button", | |
"internal_security", | |
"check_red_button_status", | |
"process_matching", | |
"check_cf_processes", | |
"check_uuid", | |
"check_log_system", | |
"check_rsyslog_version", | |
"check_cron_daemon", | |
"garbage_collection", | |
"check_binaries_freshness", | |
"check_zypper", | |
"nxlog_enable", | |
"configuration" | |
}; | |
!policy_server:: | |
"bs" slist => { | |
"startExecution", | |
"check_disable_agent", | |
"clean_red_button", | |
"update", | |
"set_red_button", | |
"internal_security", | |
"check_red_button_status", | |
"process_matching", | |
"check_cf_processes", | |
"check_cron_daemon", | |
"garbage_collection", | |
"check_binaries_freshness", | |
"check_log_system", | |
"check_rsyslog_version", | |
"nxlog_enable", | |
"check_zypper", | |
"check_uuid", | |
"configuration" | |
}; | |
any:: | |
"end" slist => { "endExecution" }; | |
!android.!windows:::: | |
"rudder_var" string => "/var/rudder"; | |
android:: | |
"rudder_var" string => "/data/rudder"; | |
!windows:: | |
"ncf_path" string => "${rudder_var}/ncf"; | |
"rudder_tools" string => "${rudder_var}/tools"; | |
windows:: | |
"rudder_base" string => "${sys.winprogdir}\Rudder"; | |
"rudder_tools" string => "${rudder_base}\sbin"; | |
"ncf_path" string => "${rudder_base}\ncf"; | |
!windows:: | |
"list_compatible_inputs" string => "NCF_CACHE_PATH=${sys.workdir}/state /bin/sh ${ncf_path}/common/10_ncf_internals/list-compatible-inputs"; | |
"ncf_common_inputs_10_40" slist => splitstring(execresult("${list_compatible_inputs} ${sys.cf_version} ${ncf_path}/common 10_ncf_internals 20_cfe_basics 30_generic_methods 40_it_ops_knowledge", "useshell"), "\n", 10000); | |
"ncf_common_inputs_50_60" slist => splitstring(execresult("${list_compatible_inputs} ${sys.cf_version} ${ncf_path}/common 50_techniques 60_services", "useshell"), "\n", 10000); | |
"ncf_local_inputs_10_40" slist => splitstring(execresult("${list_compatible_inputs} ${sys.cf_version} ${ncf_path}/local 10_ncf_internals 20_cfe_basics 30_generic_methods 40_it_ops_knowledge", "useshell"), "\n", 10000); | |
"ncf_local_inputs_50_60" slist => splitstring(execresult("${list_compatible_inputs} ${sys.cf_version} ${ncf_path}/local 50_techniques 60_services", "useshell"), "\n", 10000); | |
# ncf_inputs contains all the files of ncf, and ignore the empty lists | |
"ncf_inputs" slist => { | |
"@{ncf_common_inputs_10_40}", | |
"@{ncf_common_inputs_50_60}", | |
"@{ncf_local_inputs_10_40}", | |
"@{ncf_local_inputs_50_60}", | |
}, | |
policy => "ifdefined"; | |
windows:: | |
# Windows agent only exists in 3.6 version, so as a shortcut, we can load all files of ncf | |
# It should be replaced by a proper script, as explained in #5659 | |
"ncf_common_inputs" slist => splitstring(execresult("c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command \"ls -Path 'c:\Program Files\Rudder\var\ncf\common' -Name *.cf -Recurse -Exclude promises.cf | % { Write-Host c:\Program Files\Rudder\var\ncf\common\$_ } \"", "useshell"), "\n", 10000); | |
"ncf_local_inputs" slist => splitstring(execresult("c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command \"ls -Path 'c:\Program Files\Rudder\var\ncf\local' -Name *.cf -Recurse -Exclude promises.cf | % { Write-Host c:\Program Files\Rudder\var\ncf\local\$_ } \"", "useshell"), "\n", 10000); | |
# ncf_inputs contains all the files of ncf, and ignore the empty lists | |
"ncf_inputs" slist => { | |
"@{ncf_common_inputs}", | |
"@{ncf_local_inputs}", | |
}, | |
policy => "ifdefined"; | |
# definition of the machine roles | |
&NODEROLE& | |
} | |
bundle common rudder_roles | |
{ | |
classes: | |
# Abort if no uuid is defined | |
"should_not_continue" not => fileexists("${g.uuid_file}"); | |
# Policy Server is a machine which delivers promises | |
"policy_server" expression => strcmp("root","${g.uuid}"); | |
# Root Server is the top policy server machine | |
"root_server" expression => strcmp("root","${g.uuid}"); | |
} | |
######################################################### | |
# Control execution | |
######################################################### | |
bundle agent startExecution | |
{ | |
reports: | |
cfengine_3:: | |
"@@Common@@log_info@@&TRACKINGKEY&@@common@@StartRun@@${g.execRun}##${g.uuid}@#Start execution"; | |
} | |
bundle agent endExecution | |
{ | |
reports: | |
cfengine_3:: | |
"@@Common@@log_info@@&TRACKINGKEY&@@common@@EndRun@@${g.execRun}##${g.uuid}@#End execution"; | |
rudder_promises_generated_error|no_update:: | |
"********************************************************************************* | |
* rudder-agent could not get an updated configuration from the policy server. * | |
* This can be caused by a network issue, an unavailable server, or if this * | |
* node was deleted from the Rudder root server. * | |
* Any existing configuration policy will continue to be applied without change. * | |
*********************************************************************************"; | |
} | |
########################################################## | |
# Check for "disable-agent" file and cleanly stop and | |
# warn about this if it is present | |
########################################################## | |
bundle agent check_disable_agent | |
{ | |
vars: | |
"components" slist => { "cf-serverd", "cf-execd", "cf-monitord" }; | |
classes: | |
"should_disable_agent" expression => fileexists("${g.rudder_disable_agent_file}"); | |
# Only define this class when we're ready to die - this is a special class name in "abortclasses" | |
"should_not_continue" | |
expression => "should_disable_agent", | |
ifvarclass => "abort_report_done"; | |
processes: | |
should_disable_agent:: | |
"${sys.workdir}/bin/${components}" | |
signals => { "term", "kill" }; | |
reports: | |
should_disable_agent:: | |
"FATAL: The file ${g.rudder_disable_agent_file} is present. Rudder will kill all running daemons and halt immediately." | |
classes => if_ok("abort_report_done"); | |
} | |
########################################################## | |
# Red Button part. | |
# When the file ${sys.workdir}/inputs/stop exists, we must stop the | |
# execution of the agent on all client machines | |
########################################################## | |
bundle agent clean_red_button() | |
{ | |
files: | |
safe.policy_server:: | |
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile" | |
delete => tidy, | |
comment => "Deleting the stop file on clients promises, cfengine is good to go"; | |
safe.!policy_server:: | |
"${sys.workdir}/inputs/stopFile" | |
delete => tidy, | |
comment => "Deleting the stop file, cfengine is good to go"; | |
commands: | |
safe.policy_server:: | |
"${sys.workdir}/bin/cf-runagent" | |
args => "-Dsafe", | |
comment => "Propagate the safe information to children"; | |
reports: | |
safe:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Red Button@@None@@${g.execRun}##${g.uuid}@#Authorizing Cfengine to restart"; | |
} | |
bundle agent set_red_button() | |
{ | |
classes: | |
policy_server:: | |
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile"); | |
methods: | |
danger:: | |
"any" usebundle => setStopFile; | |
danger.policy_server:: | |
"any" usebundle => stopClients; | |
} | |
bundle agent setStopFile | |
{ | |
files: | |
danger.!policy_server:: | |
"${sys.workdir}/inputs/stopFile" | |
create => "true"; | |
danger.policy_server:: | |
"${g.rudder_var}/share/[a-f0-9A-F\-]+/rules/cfengine-(community|nova)/stopFile" | |
create => "true"; | |
reports: | |
danger.!policy_server:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Red Button@@None@@${g.execRun}##${g.uuid}@#Creating local stop file for this node"; | |
danger.policy_server:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Red Button@@None@@${g.execRun}##${g.uuid}@#Creating stop files for all clients of this policy server"; | |
} | |
bundle agent stopClients | |
{ | |
classes: | |
policy_server:: | |
"danger" expression => fileexists("${g.rudder_var}/share/root/stopFile"); | |
commands: | |
danger.policy_server:: | |
"${sys.workdir}/bin/cf-runagent" | |
args => "-Ddanger", | |
comment => "Propagate the danger information to children"; | |
reports: | |
danger.policy_server:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Red Button@@None@@${g.execRun}##${g.uuid}@#Actively stopping CFEngine operations on all clients of this policy server (via cf-runagent)"; | |
} | |
bundle agent check_red_button_status() | |
{ | |
classes: | |
!policy_server:: | |
"should_not_continue" expression => fileexists("${sys.workdir}/inputs/stopFile"); | |
reports: | |
!should_not_continue:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Red Button@@None@@${g.execRun}##${g.uuid}@#Red Button is not in effect, continuing as normal..."; | |
} | |
################################################### | |
# Check that CFengine services are up | |
################################################### | |
bundle agent check_cf_processes | |
{ | |
vars: | |
# process_term defines how many maximum instances of this | |
# binary should be running before attempting to SIGTERM them. | |
# process_kill is the same for SIGKILL. | |
!windows:: | |
# On windows, cf-execd is a service, and there can be only one instance of it running (by design) | |
"process_term[execd]" string => "2"; | |
"process_kill[execd]" string => "5"; | |
any:: | |
"process_term[agent]" string => "5"; | |
"process_kill[agent]" string => "8"; | |
"binaries" slist => getindices("process_term"); | |
processes: | |
windows:: | |
# Using the path on windows fails, as process are not reported the same way | |
# And unfortunately, the cf-serverd is not a service. | |
"cf-serverd" restart_class => "start_server"; | |
!windows:: | |
"${sys.workdir}/bin/cf-serverd" restart_class => "start_server"; | |
"${sys.workdir}/bin/cf-execd" restart_class => "start_executor"; | |
# If there are more than 2 cf-execd's, it means cf-execd is starting to | |
# go crazy, so we ask politely to these processes to shut down. | |
"${sys.workdir}/bin/cf-${binaries}" | |
process_count => check_range("${binaries}", "0","${process_term[${binaries}]}"), | |
signals => { "term" }, | |
classes => if_repaired("${binaries}_has_gone_wild"), | |
comment => "Checking if cf-${binaries} has gone wild"; | |
# If there are too much cf-execd's/cf-agents running, it means that they are really | |
# going crazy. Let's be a bit less polite and more violent about killing them. | |
# | |
# These two promises overlap, because when you go past the 2/5-limit treshold, | |
# you still leave a chance for them to die with SIGTERM before the SIGKILL. | |
# | |
# Reason: The backend databases that stores the classes and some runtime | |
# parameters do really not appreciate beeing killed violently and may prevent | |
# the agent from operating properly. | |
"${sys.workdir}/bin/cf-${binaries}" | |
process_count => check_range("${binaries}", "0","${process_kill[${binaries}]}"), | |
signals => { "kill" }, | |
classes => if_repaired("${binaries}_has_gone_really_wild"), | |
comment => "Checking if cf-${binaries} has gone really wild"; | |
&if(NOVA)& | |
windows:: | |
# Windows does only implement SIGTERM. Using SIGKILL makes no sense on it. | |
"cf-${binaries}" | |
process_count => check_range("${binaries}", "0","${process_term[${binaries}]}"), | |
signals => { "term" }, | |
classes => if_repaired("${binaries}_has_gone_wild"), | |
comment => "Checking if cf-${binaries} has gone wild"; | |
services: | |
# By design, there can be only one cf-execd service running on Windows | |
windows:: | |
"CfengineNovaExec" | |
service_policy => "start", | |
service_method => u_bootstart, | |
comment => "Start the executor windows service now and at boot time"; | |
&endif& | |
commands: | |
start_server:: | |
"${sys.cf_serverd}" | |
action => u_ifwin_bg, | |
classes => outcome("server"); | |
start_executor:: | |
"${sys.cf_execd}" | |
action => u_ifwin_bg, | |
classes => outcome("executor"); | |
reports: | |
cfengine_3:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Process checking@@None@@${g.execRun}##${g.uuid}@#There is an acceptable number of CFEngine processes running on the machine" | |
# Here, I can not use the binaries variable as CFEngine will iterate and output two reports, breaking the reporting. | |
ifvarclass => "!agent_has_gone_wild.!agent_has_gone_really_wild.!execd_has_gone_wild.!execd_has_gone_really_wild"; | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Process checking@@None@@${g.execRun}##${g.uuid}@#Warning, more than ${process_term[${binaries}]} cf-${binaries} processes were detected. They have been sent a graceful termination signal." | |
ifvarclass => "${binaries}_has_gone_wild.!${binaries}_has_gone_really_wild"; | |
"@@Common@@result_error@@&TRACKINGKEY&@@Process checking@@None@@${g.execRun}##${g.uuid}@#ALERT: more than ${process_term[${binaries}]} cf-${binaries} processes were detected. Killing processes that do not respect graceful termination signals." | |
ifvarclass => "${binaries}_has_gone_really_wild"; | |
} | |
####################################################### | |
# UUID file enforcing | |
bundle agent check_uuid | |
{ | |
files: | |
"${g.uuid_file}" | |
create => "true", | |
edit_line => enforce_content("${g.uuid}"), | |
edit_defaults => noempty_backup, | |
perms => m("644"), | |
comment => "Setting the uuid variable in a machine"; | |
} | |
####################################################### | |
# Check the log system, and configure it accordingly | |
# This only works with unix flavoured system | |
bundle agent check_log_system | |
{ | |
vars: | |
debian:: | |
"syslog_ng_source" string => "s_src"; | |
SuSE:: | |
"syslog_ng_source" string => "src"; | |
redhat:: | |
"syslog_ng_source" string => "s_sys"; | |
any:: | |
"syslog_conf_comment" string => "# Autogenerated by rudder, do not edit${const.n}"; | |
"syslog_ng_conf_prefix" string => "filter f_local_rudder{facility(local6) and program(\"rudder.*\");};destination loghost {tcp(\""; | |
"syslog_ng_conf_suffix" string => "\" port (&SYSLOGPORT&));};log {source(${syslog_ng_source});filter(f_local_rudder);destination(loghost);"; | |
"syslog_ng_conf_final" string => "flags(final);};"; | |
"syslog_ng_conf" string => concat("${syslog_conf_comment}", "${syslog_ng_conf_prefix}", "${server_info.cfserved}", "${syslog_ng_conf_suffix}", "${syslog_ng_conf_final}"); | |
"syslog_ng_conf_regex" string => concat("filter\ f\_local\_rudder\{facility\(local6\)\ and\ program\(\"rudder\.\*\"\)\;\}\;destination\ loghost\ \{(tcp|udp)\(\"", "[^\"]+", escape("${syslog_ng_conf_suffix}"), ".*"); | |
classes: | |
!android:: | |
"rsyslogd" expression => fileexists("/etc/rsyslog.conf"); | |
"syslogng" expression => fileexists("/etc/syslog-ng/syslog-ng.conf"); | |
"syslogd" expression => fileexists("/etc/syslog.conf"); | |
files: | |
!windows.rsyslogd:: | |
"/etc/rsyslog.conf" | |
edit_line => append_if_no_lines("$IncludeConfig /etc/rsyslog.d/*.conf"), | |
edit_defaults => noempty_backup, | |
comment => "Add the rsyslog.conf.d include if not already present", | |
classes => kept_if_else("rsyslog_kept", "rsyslog_repaired" , "rsyslog_failed"); | |
!windows.rsyslogd.!policy_server:: | |
"/etc/rsyslog.d/rudder-agent.conf" | |
edit_line => append_if_no_lines("#Rudder log system${const.n}if $syslogfacility-text == 'local6' and $programname startswith 'rudder' then @@${server_info.cfserved}:&SYSLOGPORT&${const.n}if $syslogfacility-text == 'local6' and $programname startswith 'rudder' then ~"), | |
create => "true", | |
edit_defaults => empty_backup, | |
classes => kept_if_else("rsyslog_kept", "rsyslog_repaired" , "rsyslog_failed"); | |
SuSE.rsyslogd.policy_server:: | |
# For SuSE, ensure that SYSLOG_DAEMON is set to 'rsyslogd' even if another syslog has been installed before | |
"/etc/sysconfig/syslog" | |
edit_line => ensure_rsyslogd_on_suse, | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("rsyslog_kept", "rsyslog_repaired" , "rsyslog_failed"); | |
!windows.syslogng.!policy_server:: | |
"/etc/syslog-ng/syslog-ng.conf" | |
edit_line => edit_syslog_conf_file("${syslog_ng_conf}", "${syslog_ng_conf_regex}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("syslog_ng_kept", "syslog_ng_repaired" , "syslog_ng_failed"); | |
!windows.syslogd.!policy_server:: | |
"/etc/syslog.conf" | |
edit_line => fix_syslogd("@${server_info.cfserved}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("syslogd_kept", "syslogd_repaired" , "syslogd_failed"); | |
#Probably, we want to do something if it is repaired ? | |
commands: | |
SuSE.(syslog_ng_repaired|rsyslog_repaired|syslogd_repaired):: | |
"/etc/init.d/syslog" | |
args => "restart", | |
comment => "Restarting syslog-ng after it's been updated"; | |
syslog_ng_repaired.!SuSE:: | |
"/etc/init.d/syslog-ng" | |
args => "restart", | |
comment => "Restarting syslog-ng after it's been updated"; | |
rsyslog_repaired.!(SuSE|fedora):: | |
"/etc/init.d/rsyslog" | |
args => "restart", | |
comment => "Restarting rsyslog after it's been updated"; | |
rsyslog_repaired.fedora:: | |
"/bin/systemctl" | |
args => "restart rsyslog", | |
comment => "Restarting rsyslog after it's been updated"; | |
syslogd_repaired.!SuSE.!solaris.!aix:: | |
"/etc/init.d/syslog" | |
args => "restart", | |
comment => "Restarting rsyslog after it's been updated"; | |
solaris.(syslog_ng_repaired|rsyslog_repaired|syslogd_repaired):: | |
"svcadm refresh svc:/system/system-log:default"; | |
aix.syslogd_repaired:: | |
"/usr/bin/refresh -s syslogd"; | |
reports: | |
syslogd:: | |
"@@Common@@log_info@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Detected running syslog as syslogd"; | |
syslogng:: | |
"@@Common@@log_info@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Detected running syslog as syslog-ng"; | |
rsyslogd:: | |
"@@Common@@log_info@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Detected running syslog as rsyslog"; | |
syslogd_failed|syslog_ng_failed|rsyslog_failed:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Logging system could not be configured for report centralization"; | |
syslogd_repaired|syslog_ng_repaired|rsyslog_repaired:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Configured logging system for report centralization"; | |
(syslogd.syslogd_kept.!syslogd_failed.!syslogd_repaired)|(syslogng.syslog_ng_kept.!syslog_ng_failed.!syslog_ng_repaired)|(rsyslogd.rsyslog_kept.!rsyslog_failed.!rsyslog_repaired):: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Logging system for report centralization is already correctly configured"; | |
android:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#This is an android machine: Logging system configuration skipped."; | |
} | |
####################################################### | |
# Check the version of rsyslog, and correct the conf | |
# file if > 5.7.1 | |
# This is done in another bundle than check_log_system | |
# as it would make it too complex to read and maintain | |
# (we would have needed to delay the restart of the services | |
# at later iteration) | |
bundle agent check_rsyslog_version { | |
vars: | |
SuSE:: | |
"syslog_restart_cmd" string => "/etc/init.d/syslog restart"; | |
fedora:: | |
"syslog_restart_cmd" string => "/bin/systemctl restart rsyslog"; | |
!(SuSE|fedora):: | |
"syslog_restart_cmd" string => "/etc/init.d/rsyslog restart"; | |
classes: | |
"check_rsyslog_version_present" expression => fileexists("${g.rudder_tools}/check_rsyslog_version"); | |
"rsyslogd" expression => fileexists("/etc/rsyslog.conf"); | |
files: | |
rsyslogd.rsyslog_greater_than_5_7_1:: | |
"/etc/rsyslog.d/remove_limit.conf" | |
edit_line => append_if_no_lines("$SystemLogRateLimitInterval 0"), | |
edit_defaults => noempty_backup, | |
create => "true", | |
comment => "Add a config line in the rsyslog.conf file to prevent from dropping rudder messages", | |
classes => rudder_common_classes("rsyslog_limit"); | |
commands: | |
rsyslogd.check_rsyslog_version_present:: | |
"${g.rudder_tools}/check_rsyslog_version" | |
contain => in_shell, | |
module => "true", | |
comment => "Check rsyslog version in order to add or not a configuration line in rsyslog.conf"; | |
rsyslog_limit_repaired:: | |
"${syslog_restart_cmd}" | |
args => "restart", | |
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"), | |
comment => "restarting rsyslog"; | |
reports: | |
rsyslogd.!check_rsyslog_version_present:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#The file ${g.rudder_tools}/check_rsyslog_version is missing"; | |
rsyslog_limit_error:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Could not remove limitation of message in rsyslog"; | |
rsyslog_limit_repaired:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Updated the rsyslog configuration to remove limitation of messages"; | |
rsyslog_restarted:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Configured logging system for report centralization"; | |
cant_restart_rsyslog:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Log system for reports@@None@@${g.execRun}##${g.uuid}@#Could not restart the logging system"; | |
} | |
####################################################### | |
# Check if the cron daemon is running | |
# This only works with unix flavoured systems too | |
bundle agent check_cron_daemon | |
{ | |
vars: | |
redhat.!fedora:: | |
"cron_bin" string => "crond$"; | |
"cron_restartcmd" string => "/etc/init.d/crond restart"; | |
fedora:: | |
"cron_bin" string => "/usr/sbin/crond -n$"; | |
"cron_restartcmd" string => "/bin/systemctl restart crond.service"; | |
ubuntu:: | |
"cron_bin" string => "cron$"; | |
"cron_restartcmd" string => "/etc/init.d/cron restart"; | |
!(redhat|fedora|ubuntu):: | |
"cron_bin" string => "/usr/sbin/cron$"; | |
"cron_restartcmd" string => "/etc/init.d/cron restart"; | |
processes: | |
!android.!windows:: | |
"${cron_bin}" | |
restart_class => "restart_crond"; | |
commands: | |
restart_crond:: | |
"${cron_restartcmd}" | |
comment => "Restarting crond", | |
classes => kept_if_else("crond_ok" ,"crond_restarted" , "crond_failed"); | |
reports: | |
crond_failed:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon was not running and could not be restarted"; | |
crond_restarted:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon has been successfully restarted"; | |
!restart_crond.!crond_restarted.!crond_failed.!android.!windows:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#The CRON daemon is running"; | |
android|windows:: | |
"@@Common@@result_na@@&TRACKINGKEY&@@CRON Daemon@@None@@${g.execRun}##${g.uuid}@#This is a system without CRON: CRON verifications skipped !"; | |
} | |
################################################################### | |
# Trash every output report and modified files older than the TTL # | |
################################################################### | |
bundle agent garbage_collection | |
{ | |
files: | |
"${sys.workdir}/outputs" | |
delete => tidy, | |
file_select => days_old("&CFENGINE_OUTPUTS_TTL&"), | |
depth_search => recurse("inf"); | |
"${g.rudder_var}/modified-files" | |
delete => tidy, | |
file_select => days_old("&MODIFIED_FILES_TTL&"), | |
depth_search => recurse("inf"); | |
} | |
####################################################### | |
# Copy the CFengine binaries from the /opt repository | |
# to the CFengine working directory | |
bundle agent check_binaries_freshness | |
{ | |
vars: | |
community_edition:: | |
"components" slist => { "cf-agent", "cf-serverd", "cf-execd", "cf-monitord", "cf-promises", "cf-runagent", "cf-key", "rpmvercmp" }; | |
files: | |
!android.!nova_edition:: | |
"${sys.workdir}/bin/${components}" | |
perms => u_p("700"), | |
copy_from => cp("${g.rudder_bin}/${components}", "localhost"), | |
classes => kept_if_else("binaries_fresh", "binaries_rotten", "binaries_missing"), | |
action => immediate, | |
comment => "Copying the CFengine binaries from ${g.rudder_sbin}/sbin to ${sys.workdir}/bin"; | |
reports: | |
binaries_fresh.!binaries_rotten.!binaries_missing:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Binaries update@@None@@${g.execRun}##${g.uuid}@#The CFengine binaries in ${sys.workdir}/bin are up to date"; | |
binaries_rotten.!binaries_missing:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Binaries update@@None@@${g.execRun}##${g.uuid}@#The CFengine binaries have been updated in ${sys.workdir}/bin"; | |
binaries_missing:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Binaries update@@None@@${g.execRun}##${g.uuid}@#An error occurred while updating the CFengine binaries in ${sys.workdir}/bin"; | |
android:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Binaries update@@None@@${g.execRun}##${g.uuid}@#This is an android machine: no CFEngine binaries update needed"; | |
nova_edition:: | |
"@@Common@@result_na@@&TRACKINGKEY&@@Binaries update@@None@@${g.execRun}##${g.uuid}@#This is an CFEngine enterprise system: binaries update are handled differently"; | |
} | |
####################################################### | |
body agent control | |
{ | |
# if default runtime is 5 mins we need this for long jobs | |
ifelapsed => "1"; | |
#define here some environment variables | |
environment => { "DEBIAN_FRONTEND=noninteractive" }; | |
abortclasses => { "should_not_continue" }; | |
agentfacility => "LOG_LOCAL6"; | |
skipidentify => "&SKIPIDENTIFY&"; | |
# Repository where to put the copy of modified files | |
default_repository => "${g.rudder_var}/modified-files"; | |
} | |
####################################################### | |
body executor control | |
{ | |
splaytime => "&AGENT_RUN_SPLAYTIME&"; | |
schedule => { &AGENT_RUN_SCHEDULE& }; | |
executorfacility => "LOG_DAEMON"; | |
windows:: | |
# CFEngine best practice is to use full paths on Windows | |
exec_command => "${sys.cf_agent} -f \"${sys.workdir}\inputs\failsafe.cf\" \& ${sys.cf_agent}"; | |
!windows:: | |
exec_command => "${sys.cf_agent} -f failsafe.cf \&\& ${sys.cf_agent}"; | |
} | |
######################################################## | |
#Enforce that the file only contains this information | |
bundle edit_line enforce_content(str) | |
{ | |
delete_lines: | |
"${str}" not_matching => "true"; | |
insert_lines: | |
"${str}"; | |
} | |
# Fix syslogd content : caution, the @ must be in the argument | |
bundle edit_line fix_syslogd(syslogd) | |
{ | |
delete_lines: | |
any:: | |
"^(local6)\s+(?!${syslogd}).*" | |
comment => "Delete missconfigured rudder syslogd destination"; | |
"^local6\.\*\s+${syslogd}" | |
comment => "Delete old rudder syslogd format"; | |
insert_lines: | |
any:: | |
"# Rudder specific logging parameters"; | |
"local6.notice ${syslogd}" | |
comment => "Add the rudder syslogd destination"; | |
} | |
bundle edit_line edit_syslog_conf_file(line_to_add, pattern_to_remove) | |
{ | |
delete_lines: | |
"${pattern_to_remove}"; | |
"\$\(syslog_ng_conf\)"; | |
insert_lines: | |
"${line_to_add}" | |
location => syslogng_log_part; | |
} | |
body location syslogng_log_part | |
{ | |
select_line_matching => "^\s*log\s*\{.*"; | |
before_after => "before"; | |
first_last => "first"; | |
} | |
bundle edit_line ensure_rsyslogd_on_suse | |
{ | |
field_edits: | |
# match a line starting like 'SYSLOG_DAEMON=something' | |
"^SYSLOG_DAEMON=.*$" | |
edit_field => col("=","2","\"rsyslogd\"","set"), | |
comment => "Match a line starting like key = something"; | |
} | |
##################################################################################### | |
# Copyright 2012 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Rudder Promise Body and Bundle Library | |
# | |
# This library includes standardized bundles and bodies to be used as part of the | |
# "best practices" in the Techniques writing | |
# | |
################################################## | |
# classes body | |
################################################## | |
# | |
# Automatically defines classes bases on a given prefix | |
# The classes are defined based on the romises outcome | |
# | |
body classes rudder_common_classes(prefix) | |
{ | |
promise_kept => { "${prefix}_kept" }; | |
promise_repaired => { "${prefix}_repaired" }; | |
repair_failed => { "${prefix}_failed" , "${prefix}_error" }; | |
repair_denied => { "${prefix}_denied" , "${prefix}_error" }; | |
repair_timeout => { "${prefix}_timeout", "${prefix}_error" }; | |
} | |
# | |
# Automatically defines classes bases on a given prefix | |
# The classes are defined based on the promises outcome | |
# Same as above but persist classes for ${persist} mins | |
# | |
body classes rudder_common_classes_persist(prefix, persist) | |
{ | |
promise_kept => { "${prefix}_kept" }; | |
promise_repaired => { "${prefix}_repaired" }; | |
repair_failed => { "${prefix}_failed" , "${prefix}_error" }; | |
repair_denied => { "${prefix}_denied" , "${prefix}_error" }; | |
repair_timeout => { "${prefix}_timeout", "${prefix}_error" }; | |
persist_time => ${persist}; | |
} | |
# | |
# Always define a class, with the given persist time | |
# Define the class for ${persist} minutes | |
# | |
body classes rudder_always_classes_persist(always, persist) | |
{ | |
promise_kept => { "${always}" }; | |
promise_repaired => { "${always}" }; | |
repair_failed => { "${always}" }; | |
repair_denied => { "${always}" }; | |
repair_timeout => { "${always}" }; | |
persist_time => "${persist}"; | |
} | |
################################################## | |
# files bundles | |
################################################## | |
# | |
# Insert the standard Rudder disclaimer into a file | |
# | |
bundle edit_line rudder_common_disclaimer | |
{ | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
} | |
# | |
# Select files older than X months | |
# | |
body file_select rudder_common_months_old(months) | |
{ | |
mtime => irange(0,ago(0,"${months}",0,0,0,0)); | |
file_result => "mtime"; | |
} | |
# | |
# Select files older than X days | |
# | |
body file_select rudder_common_days_old(days) | |
{ | |
mtime => irange(0,ago(0,0,"${days}",0,0,0)); | |
file_result => "mtime"; | |
} | |
# | |
# Select files older than X hours | |
# | |
body file_select rudder_common_hours_old(hours) | |
{ | |
mtime => irange(0,ago(0,0,0,"${hours}",0,0)); | |
file_result => "mtime"; | |
} | |
# | |
# Select files older than X minutes | |
# | |
body file_select rudder_common_minutes_old(minutes) | |
{ | |
mtime => irange(0,ago(0,0,0,0,"${minutes}",0)); | |
file_result => "mtime"; | |
} | |
# enforce content of section | |
bundle edit_line rudder_ensure_section_content(section_start, section_end, content) | |
{ | |
vars: | |
"csection" string => canonify("${section_start}"); | |
"escaped_section_start" string => escape(${section_start}); | |
"escaped_section_end" string => escape(${section_end}); | |
classes: | |
# Detect if section is already there | |
"has_${csection}" expression => regline("${escaped_section_start}", "${edit.filename}"); | |
delete_lines: | |
".*" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"), | |
ifvarclass => "has_${csection}"; | |
insert_lines: | |
# Insert new, empty section if it doesn't exist already. | |
"${section_start} | |
${section_end}" | |
insert_type => "preserve_block", | |
ifvarclass => "!has_${csection}"; | |
# Insert missing lines into the section | |
"${content}" | |
select_region => rudder_section_selector("${escaped_section_start}", "${escaped_section_end}"); | |
} | |
body select_region rudder_section_selector(section_start, section_end) | |
{ | |
select_start => "${section_start}"; | |
select_end => "${section_end}"; | |
} | |
################################################ | |
# Reporting bundles | |
################################################ | |
# | |
# Create and send a report to the server | |
# This bundle takes 6 parameters : | |
# technique_name : the name of the technique, human readable | |
# status : the status of the Component, among the following values | |
# result_success | |
# result_error | |
# result_repaired | |
# log_repaired (for logging only) | |
# log_warn (for logging only) | |
# log_info (for logging only) | |
# log_debug (for logging only) | |
# log_trace (for logging only) | |
# identifier : the identifier of the current Rule and Directive | |
# component_name : the name of the component within the Technique | |
# component_key : the value of the component reference variable (or None if undefined) | |
# message : An explanation message understandable by a human | |
# | |
bundle agent rudder_common_report(technique_name, status, identifier, component_name, component_key, message) | |
{ | |
reports: | |
cfengine_3:: | |
"@@${technique_name}@@${status}@@${identifier}@@${component_name}@@${component_key}@@${g.execRun}##${g.uuid}@#${message}"; | |
} | |
# | |
# Automatically create reports based on existing classes starting by | |
# class_prefix (as defined by the body classes rudder_common_classes) | |
# Takes 6 parameters | |
# technique_name : the name of the technique, human readable | |
# class_prefix : the prefix of a set of classes to reporting on (suffixes with "kept", "repaired" or "error") | |
# identifier : the identifier of the current Rule and Directive | |
# component_name : the name of the component within the Technique | |
# component_key : the value of the component reference variable (None if it does not exists) | |
# message_prefix : The begining of an explanation message understandable by a human | |
# | |
bundle agent rudder_common_reports_generic(technique_name, class_prefix, identifier, component_name, component_key, message_prefix) | |
{ | |
methods: | |
"success" | |
usebundle => rudder_common_report("${technique_name}", "result_success", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was correct"), | |
ifvarclass => "${class_prefix}_kept.!${class_prefix}_repaired.!${class_prefix}_error"; | |
"repaired" | |
usebundle => rudder_common_report("${technique_name}", "result_repaired", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} was repaired"), | |
ifvarclass => "${class_prefix}_repaired.!${class_prefix}_error"; | |
"error" | |
usebundle => rudder_common_report("${technique_name}", "result_error", "${identifier}", "${component_name}", "${component_key}", "${message_prefix} could not be repaired"), | |
ifvarclass => "${class_prefix}_error"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
####################################################### | |
# | |
# Site specific promises | |
# | |
####################################################### | |
bundle common g | |
{ | |
vars: | |
android:: | |
"rudder_base" string => "/data/rudder"; | |
"rudder_var" string => "/data/rudder"; | |
"rudder_curl" string => "/system/bin/curl"; | |
"rudder_rm" string => "/system/xbin/rm"; | |
!windows.!android:: | |
"rudder_base" string => "/opt/rudder"; | |
"rudder_curl" string => "/usr/bin/curl"; | |
"rudder_rm" string => "/bin/rm"; | |
solaris:: | |
"rudder_var" string => "/opt/rudder/var"; | |
!solaris.!windows.!android:: | |
"rudder_var" string => "/var/rudder"; | |
!windows:: | |
"rudder_bin" string => "${rudder_base}/bin"; | |
"rudder_sbin" string => "${rudder_base}/sbin"; | |
"rudder_var_tmp" string => "${rudder_var}/tmp"; # tmp generated data | |
"rudder_base_sbin" string => "${rudder_base}/sbin"; #folder where tools are installed | |
"rudder_inventories" string => "${rudder_var}/inventories"; | |
"uuid_file" string => "${rudder_base}/etc/uuid.hive"; | |
"rudder_disable_agent_file" string => "${rudder_base}/etc/disable-agent"; | |
"rudder_tools" string => "${rudder_var}/tools"; | |
"rudder_ncf" string => "${rudder_var}/ncf"; | |
"crontab" string => "/etc/crontab"; | |
"gzip" string => "/bin/gzip"; | |
# DEPRECATED: This variable is used in pre-2.9 Techniques. | |
"rudder_dependencies" string => "${rudder_var}/tools"; | |
windows:: | |
"rudder_base" string => "${sys.winprogdir}\Rudder"; | |
"rudder_bin" string => "${rudder_base}\bin"; | |
"rudder_sbin" string => "${rudder_base}\sbin"; | |
"rudder_var" string => "${sys.winprogdir}\Rudder\var"; | |
"rudder_var_tmp" string => "${rudder_var}\tmp"; # tmp generated data | |
"rudder_base_sbin" string => "${rudder_base}\sbin"; #folder where tools are installed | |
"rudder_inventories" string => "${rudder_var}\inventories"; | |
"rudder_base_sbin_arg" string => "${sys.winprogdir}\Rudder\sbin"; # for the installer command line | |
"rudder_tools" string => "${rudder_sbin}"; | |
"rudder_ncf" string => "${rudder_base}\ncf"; | |
"escaped_workdir" string => escape("${sys.workdir}"); | |
"rudder_curl" string => "\"${rudder_base_sbin}\curl\curl.exe\""; | |
"uuid_file" string => "${rudder_base}\etc\uuid.hive"; | |
"rudder_disable_agent_file" string => "${rudder_base}\etc\disable-agent"; | |
# DEPRECATED: This variable is used in pre-2.9 Techniques. | |
"rudder_dependencies" string => "${rudder_sbin}"; | |
any:: | |
"uuid" string => readfile("${g.uuid_file}", 60); | |
"server_shares_folder" string => "/var/rudder/share/${uuid}/promises/shares"; | |
"rudder_var_reports" string => "${rudder_var}/reports"; | |
"davuser" string => "&DAVUSER&"; | |
"davpw" string => "&DAVPASSWORD&"; | |
"minicurl" string => "${rudder_bin}/rudder-perl ${sys.workdir}/inputs/common/utilities/minicurl"; | |
"excludedreps" slist => { "\.X11", ".*kde.*", "\.svn", "perl" }; | |
"rudder_tools_origin" string => "/var/rudder/tools"; | |
# Path where all the configurations (git with techniques, groups, ncf, etc) are stored | |
"rudder_configuration_repository" | |
string => "&CONFIGURATION_REPOSITORY_FOLDER&"; | |
"rudder_ncf_origin_common" string => "/usr/share/ncf/tree"; | |
"rudder_ncf_origin_local" string => "${rudder_configuration_repository}/ncf"; | |
"rudder_tools_updated_origin" string => "${rudder_tools_origin}/rudder_tools_updated"; | |
"rudder_tools_updated" string => "${rudder_tools}/rudder_tools_updated"; | |
# DEPRECATED: This variable is used in pre-2.9 Techniques. | |
"rudder_dependencies_origin" string => "/var/rudder/tools"; | |
# The time at which the execution started | |
(linux|cygwin).!(centos_3|redhat_3|centos_4|redhat_4):: | |
"execRun" string => execresult("/bin/date --rfc-3339=second", "noshell"); | |
(linux|cygwin).(centos_3|redhat_3|centos_4|redhat_4):: | |
# We would like to use date's "--rfc-3339=second" option here, but it is not available on older OSes (RHEL 3/4, AIX 5...) | |
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell"); | |
windows.!cygwin:: | |
"execRun" string => execresult("\"${g.rudder_sbin}\getDate.bat\"", "noshell"); | |
android:: | |
"execRun" string => execresult("/system/xbin/date \"+%Y-%m-%d %T%z\" | sed 's/\([-+][0-9][0-9]\)\([0-9][0-9]\)$/\1:\2/'", "useshell"); | |
aix:: | |
# AIX's date command doesn't have a "%z" option, so we fake it by using UTC | |
"execRun" string => execresult("/bin/date -u \"+%Y-%m-%d %T+00:00\"", "noshell"); | |
!linux.!cygwin.!windows.!android.!aix:: | |
"execRun" string => execresult("/bin/date \"+%Y-%m-%d %T%:z\"", "noshell"); | |
classes: | |
"curl_installed" expression => isexecutable("${rudder_curl}"); | |
} | |
&AGENT_RUN_INTERVAL& | |
##################################################################################### | |
# Copyright 2011-2012 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# This is Rudder's library of common CFEngine functions. | |
# | |
# Only bodies and editbundles are to be appended here !!! | |
# | |
##################################################################################### | |
################################################### | |
# Knowledge from the original stdlib | |
################################################### | |
# Uses a specific prefix to avoid collision | |
# when the stdlib will be updated | |
################################################### | |
bundle common rudder_debian_knowledge | |
# @depends paths | |
# @brief common Rudder Debian knowledge bundle | |
# | |
# This common bundle has useful information about Debian. | |
{ | |
vars: | |
"dpkg_compare_equal" string => "/usr/bin/dpkg --compare-versions '${v1}' eq '${v2}'"; | |
"dpkg_compare_less" string => "/usr/bin/dpkg --compare-versions '${v1}' lt '${v2}'"; | |
} | |
bundle common rudder_rpm_knowledge | |
# @depends paths | |
# @brief common Rudder RPM knowledge bundle | |
# | |
# This common bundle has useful information about platforms using RPM | |
{ | |
vars: | |
"rpm_compare_equal" string => "${sys.workdir}/bin/rpmvercmp '${v1}' eq '${v2}'"; | |
"rpm_compare_less" string => "${sys.workdir}/bin/rpmvercmp '${v1}' lt '${v2}'"; | |
} | |
################################################### | |
body depth_search recurse_visible(d) | |
{ | |
depth => "${d}"; | |
exclude_dirs => { "\..*" }; | |
} | |
#perms validation | |
body perms u_p(p) | |
{ | |
mode => "${p}"; | |
} | |
######################################################### | |
#server may be a list | |
body copy_from cp(from,server) | |
{ | |
servers => { "${server}" }; | |
source => "${from}"; | |
compare => "digest"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
body copy_from scp(from, server,compare,trustkey,preserve,purge) | |
{ | |
servers => { "${server}" }; | |
source => "${from}"; | |
compare => "${compare}"; | |
encrypt => "true"; | |
verify => "true"; | |
trustkey => "${trustkey}"; | |
preserve => "${preserve}"; #preserver permissions | |
purge => "${purge}"; | |
copy_backup => "timestamp"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
# This is an evolved version of copy_from scp that uses local copies if we are | |
# running on a policy server instead of copying from a localhost remote blindly. | |
body copy_from rudder_copy_from(from, server,compare,trustkey,preserve,purge) { | |
source => "${from}"; | |
compare => "${compare}"; | |
encrypt => "true"; | |
verify => "true"; | |
trustkey => "${trustkey}"; | |
preserve => "${preserve}"; # Preserve the permissions | |
purge => "${purge}"; | |
copy_backup => "timestamp"; | |
!root_server:: | |
servers => { "${server}" }; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
body copy_from copy(from) | |
{ | |
source => "${from}"; | |
copy_backup => "false"; | |
preserve => "true"; | |
} | |
body copy_from copy_digest(from) | |
{ | |
source => "${from}"; | |
copy_backup => "timestamp"; | |
preserve => "true"; | |
compare => "digest"; | |
} | |
######################################################### | |
# This body is deprecated, and should not be used anymore | |
######################################################### | |
body classes class_trigger(if,else,kept) | |
{ | |
promise_kept => { "${kept}" }; | |
promise_repaired => { "${if}" }; | |
repair_failed => { "${else}" }; | |
repair_denied => { "${else}" }; | |
repair_timeout => { "${else}" }; | |
} | |
######################################################### | |
body location append | |
{ | |
before_after => "after"; | |
} | |
######################################################### | |
body package_method yum_remi | |
{ | |
package_changes => "bulk"; | |
package_list_command => "/usr/bin/yum list installed"; | |
package_list_name_regex => "([^.]+).*"; | |
package_list_version_regex => "[^\s]\s+([^\s]+).*"; | |
package_list_arch_regex => "[^.]+\.([^\s]+).*"; | |
package_installed_regex => ".*installed.*"; | |
package_name_convention => "${name}.${arch}"; | |
package_delete_convention => "${name}"; | |
package_add_command => "/usr/bin/yum --enablerepo=remi -y install"; | |
package_delete_command => "/bin/rpm -e"; | |
package_verify_command => "/bin/rpm -V"; | |
} | |
#perms validation | |
body perms p(user,mode) | |
{ | |
owners => { "${user}" }; | |
mode => "${mode}"; | |
} | |
############################################ | |
body file_select cf3_files | |
{ | |
leaf_name => { "cf-.*" }; | |
file_result => "leaf_name"; | |
} | |
######################################################### | |
body changes lay_trip_wire | |
{ | |
hash => "best"; | |
report_changes => "content"; | |
update_hashes => "yes"; | |
} | |
######################################################## | |
body action longjob | |
{ | |
ifelapsed => "240"; # run only every 4 hours | |
} | |
####################################################### | |
# For the library | |
####################################################### | |
body edit_defaults noempty_backup | |
{ | |
empty_file_before_editing => "false"; | |
edit_backup => "timestamp"; # we want to keep a track of everything | |
max_file_size => "1024000"; | |
} | |
body edit_defaults empty_backup | |
{ | |
empty_file_before_editing => "true"; | |
edit_backup => "timestamp"; | |
max_file_size => "1024000"; | |
} | |
body edit_defaults def_no_backup | |
{ | |
empty_file_before_editing => "false"; | |
edit_backup => "false"; | |
max_file_size => "1024000"; | |
} | |
######################################################## | |
######################################################## | |
bundle edit_line DeleteLinesMatching(regex) | |
{ | |
delete_lines: | |
"${regex}" | |
action => WarnOnly; | |
} | |
######################################################## | |
body action WarnOnly | |
{ | |
action_policy => "warn"; | |
} | |
######################################## | |
# Bodies | |
######################################## | |
body replace_with With(x) | |
{ | |
replace_value => "${x}"; | |
occurrences => "all"; | |
} | |
######################################## | |
################################ | |
# For commands with a > | |
################################ | |
body contain outputable | |
{ | |
useshell => "true"; | |
no_output => "false"; | |
} | |
################################ | |
# For commands with a >, in a dir | |
################################ | |
body contain outputable_dir(dir) | |
{ | |
useshell => "true"; | |
no_output => "false"; | |
chdir => "${dir}"; | |
} | |
################################ | |
# Process is launched ? | |
################################ | |
body process_count islaunched(class) | |
{ | |
match_range => irange("1", "500"); | |
in_range_define => { "${class}"}; | |
out_of_range_define => {"no_${class}"}; | |
} | |
########################################################################################### | |
# Cancel class | |
# Cancel every classes passed by argument | |
########################################################################################## | |
body classes cancel_all_classes(class_to_cancel) { | |
cancel_kept => { "${class_to_cancel}" }; | |
cancel_repaired => { "${class_to_cancel}" }; | |
cancel_notkept => { "${class_to_cancel}" }; | |
} | |
########################################################################################### | |
# Persistent class | |
# If the promise is repaired, define repaired for length minutes and undefine failed | |
# If the promise is not kept, undefine repaired and define failed for length minutes | |
########################################################################################## | |
body classes persistant_class(repaired, failed, length) | |
{ | |
promise_repaired => { "${repaired}" }; | |
repair_failed => { "${failed}" }; | |
repair_denied => { "${failed}" }; | |
repair_timeout => { "${failed}" }; | |
cancel_repaired => {"${failed}"}; | |
cancel_notkept => {"${repaired}"}; | |
persist_time => "${length}"; | |
} | |
########################################################################################### | |
# Persistent class | |
# If the promise is repaired/kept, define repaired for length minutes and undefine failed | |
# If the promise is not kept, undefine repaired and define failed for length minutes | |
########################################################################################## | |
body classes set_persist_classes(repaired, failed, length) | |
{ | |
promise_kept => { "${repaired}" }; | |
promise_repaired => { "${repaired}" }; | |
repair_failed => { "${failed}" }; | |
repair_denied => { "${failed}" }; | |
repair_timeout => { "${failed}" }; | |
cancel_kept => {"${failed}"}; | |
cancel_repaired => {"${failed}"}; | |
cancel_notkept => {"${repaired}"}; | |
persist_time => "${length}"; | |
} | |
################################################ | |
# kept_if_else | |
# set kept if the promise is kept | |
# yes if repaired | |
# no if cannot repair | |
################################################ | |
body classes kept_if_else(kept, yes,no) | |
{ | |
promise_kept => { "${kept}" }; | |
promise_repaired => { "${yes}" }; | |
repair_failed => { "${no}" }; | |
repair_denied => { "${no}" }; | |
repair_timeout => { "${no}" }; | |
} | |
######################################### | |
# Make a local copy with a digest check # | |
######################################### | |
body copy_from digest_cp(from) | |
{ | |
source => "${from}"; | |
compare => "digest"; | |
copylink_patterns => { ".*" }; | |
copy_backup => "timestamp"; | |
} | |
################################################ | |
# kept_if_else with persistant classes | |
# set kept if the promise is kept | |
# yes if repaired | |
# no if cannot repair | |
################################################ | |
body classes kept_if_else_persist(kept, repaired, failed, persist) { | |
promise_kept => { "${kept}" }; | |
promise_repaired => { "${repaired}" }; | |
repair_failed => { "${failed}" }; | |
repair_denied => { "${failed}" }; | |
repair_timeout => { "${failed}" }; | |
persist_time => "${persist}"; | |
} | |
################################################ | |
# Special kept_if_else | |
# set kept if the promise is kept | |
# yes if repaired | |
# no if cannot repair | |
# Trigger an additionnal promise if repaired | |
################################################ | |
body classes kept_if_else_hook(kept,yes,no,hook) | |
{ | |
promise_kept => { "${kept}" }; | |
promise_repaired => { "${yes}", "${hook}" }; | |
repair_failed => { "${no}" }; | |
repair_denied => { "${no}" }; | |
repair_timeout => { "${no}" }; | |
} | |
################################################ | |
# Simple group adjustment body | |
################################################ | |
body perms group(group) | |
{ | |
groups => { "${group}" }; | |
} | |
################################################ | |
# Same as recurse but without xdev | |
# and including the current dir | |
################################################ | |
body depth_search recurse_with_current(d) | |
{ | |
depth => "${d}"; | |
include_basedir => "true"; | |
xdev => "false"; | |
} | |
######################################################################## | |
# Mount an NFS share, and allow the user to select if it is persistent # | |
######################################################################## | |
body mount rudder_nfs(server,source,type,persistence) | |
{ | |
mount_type => "${type}"; | |
mount_source => "${source}"; | |
mount_server => "${server}"; | |
edit_fstab => "${persistence}"; | |
} | |
######################################################################## | |
# Same as std_defs, allowing user to specify the file erase policy # | |
######################################################################## | |
body edit_defaults rudder_empty_select(select) | |
{ | |
empty_file_before_editing => "${select}"; | |
max_file_size => "1024000"; | |
edit_backup => "timestamp"; | |
} | |
######################################################################## | |
# Handle a directory recursively, including the dir itself # | |
######################################################################## | |
body depth_search recurse_withroot(d) | |
{ | |
depth => "${d}"; | |
# xdev => "true"; | |
include_basedir => "true"; | |
} | |
######################################################################## | |
# Change group and mode of a file/directory # | |
######################################################################## | |
body perms mg(mode,group) | |
{ | |
groups => { "${group}" }; | |
mode => "${mode}"; | |
} | |
######################################################################## | |
# Select a file using a date AND a pattern # | |
######################################################################## | |
body file_select date_pattern(age, pattern) | |
{ | |
mtime => irange("0", ago(0,0,"${age}",0,0,0)); | |
leaf_name => { "${pattern}" }; | |
file_result => "leaf_name.mtime"; | |
} | |
######################################################################## | |
# Install a package using rug # | |
######################################################################## | |
body package_method rudder_rug | |
{ | |
package_changes => "individual"; | |
package_list_command => "/bin/rpm -qa --queryformat \"i | repos | %{name} | %{version}-%{release} | %{arch}\n\""; | |
package_list_update_ifelapsed => "240"; | |
package_installed_regex => "i.*"; | |
package_list_name_regex => "[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_version_regex => "[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_list_arch_regex => "[^|]+\|[^|]+\|[^|]+\|[^|]+\|\s+([^\s]+).*"; | |
package_name_convention => "${name}"; | |
package_add_command => "/usr/bin/rug install -y"; | |
package_delete_command => "/usr/bin/rug remove -y"; | |
package_update_command => "/usr/bin/rug update -y"; | |
package_verify_command => "/usr/bin/rug verify -y$"; # $ means no args | |
# make correct version comparisons | |
package_version_less_command => "${rudder_rpm_knowledge.rpm_compare_less}"; | |
package_version_equal_command => "${rudder_rpm_knowledge.rpm_compare_equal}"; | |
} | |
######################################################################## | |
# Install a package using yum but with a check from rpm # | |
######################################################################## | |
body package_method rudder_yum | |
{ | |
package_changes => "bulk"; | |
package_list_command => "/bin/rpm -qa --qf '%{name} %{version}-%{release} %{arch}\n'"; | |
package_list_name_regex => "^(\S+?)\s\S+?\s\S+$"; | |
package_list_version_regex => "^\S+?\s(\S+?)\s\S+$"; | |
package_list_arch_regex => "^\S+?\s\S+?\s(\S+)$"; | |
package_installed_regex => ".*"; | |
package_name_convention => "${name}"; | |
package_list_update_command => "/usr/bin/yum --quiet check-update"; | |
package_list_update_ifelapsed => "240"; | |
package_patch_name_regex => "([^.]+).*"; | |
package_patch_version_regex => "[^\s]\s+([^\s]+).*"; | |
package_patch_arch_regex => "[^.]+\.([^\s]+).*"; | |
package_add_command => "/usr/bin/yum -y install"; | |
package_update_command => "/usr/bin/yum -y update"; | |
package_patch_command => "/usr/bin/yum -y update"; | |
package_delete_command => "/bin/rpm -e --nodeps --allmatches"; | |
package_verify_command => "/bin/rpm -V"; | |
# make correct version comparisons | |
package_version_less_command => "${rudder_rpm_knowledge.rpm_compare_less}"; | |
package_version_equal_command => "${rudder_rpm_knowledge.rpm_compare_equal}"; | |
} | |
################################################### | |
# edit_line prepend | |
################################################### | |
bundle edit_line prepend(lines) | |
{ | |
insert_lines: | |
"${lines}" | |
comment => "Prepending line: ${lines}", | |
location => start; | |
} | |
################################################### | |
# edit_line rudder_line_insertion | |
################################################### | |
bundle edit_line rudder_line_insertion(lines, location) | |
{ | |
insert_lines: | |
"${lines}" | |
comment => "Adding line: ${lines}", | |
location => rudder_location_before_after("${location}"); | |
} | |
######################################################### | |
body location rudder_location_before_after(location) | |
{ | |
before_after => "${location}"; | |
} | |
################################################### | |
# edit_line replace_line | |
################################################### | |
bundle edit_line replace_line(regex,replacement) | |
{ | |
replace_patterns: | |
"${regex}" | |
replace_with => With("${replacement}"), | |
comment => "Replace every occurence of ${regex} with ${replacement}"; | |
} | |
################################################### | |
# edit_line from_to | |
################################################### | |
bundle edit_line from_to(from,to) | |
{ | |
delete_lines: | |
"${from}" comment => "Reset ${from}"; | |
insert_lines: | |
"${to}" comment => "Add ${to}"; | |
} | |
################################################### | |
# contain in_shell_silent | |
################################################### | |
body contain in_shell_silent | |
{ | |
useshell => "true"; | |
no_output => "true"; | |
} | |
################################################### | |
# edit_line insert_rudder_disclaimer | |
################################################### | |
bundle edit_line insert_rudder_disclaimer | |
{ | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start; | |
} | |
################################################### | |
# edit_line rudder_change_aix_password_entry | |
################################################### | |
bundle edit_line rudder_change_aix_password_entry(user, entry, content) | |
{ | |
field_edits: | |
"\s*${entry}\s*=.*" | |
select_region => rudder_aix_user_section("${user}"), | |
edit_field => col("=","2"," ${content}","set"); | |
} | |
################################################### | |
# select_region rudder_aix_user_section | |
################################################### | |
body select_region rudder_aix_user_section(x) | |
{ | |
select_start => "${x}:\s*"; | |
select_end => "\S*:\s*"; | |
} | |
##################################################################################### | |
# Copyright 2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# This promise installs and configures nxlog | |
# | |
# This program monitors the windows event log and sends every | |
# Nova related information to a remote syslog, the Rudder main server | |
# in our case. | |
bundle agent nxlog_enable | |
{ | |
methods: | |
windows:: | |
"any" usebundle => nxlog_install; | |
"any" usebundle => nxlog_configure; | |
&if(NOVA)& | |
"any" usebundle => nxlog_launch; | |
&endif& | |
(nxlog_install_repaired|nxlog_configure_repaired|nxlog_service_repaired).!(nxlog_install_error|nxlog_configure_error|nxlog_service_error):: | |
"report" usebundle => rudder_common_report("Common", "result_repaired", "&TRACKINGKEY&", "Log system for reports", "None", "NXLog service was not installed, configured and running. Fixed."); | |
!nxlog_install_repaired.!nxlog_install_error.nxlog_configure_kept.!nxlog_configure_repaired.!nxlog_configure_error.nxlog_service_kept.!nxlog_service_repaired.!nxlog_service_error:: | |
"report" usebundle => rudder_common_report("Common", "result_success", "&TRACKINGKEY&", "Log system for reports", "None", "NXLog service already installed, configured and running as expected."); | |
} | |
bundle common nxlog_common | |
{ | |
vars: | |
windows:: | |
"nxlog_exe" string => "${g.rudder_tools}/nxlog-ce-2.8.1248.msi"; | |
"nxlog_tpl" string => "${g.rudder_tools}/nxlog.conf"; | |
} | |
bundle agent nxlog_install | |
{ | |
classes: | |
!x86_64:: | |
"nxlog_ok" expression => fileexists("${sys.winprogdir}\nxlog\nxlog.exe"); | |
x86_64:: | |
"nxlog_ok" expression => fileexists("${sys.winprogdir86}\nxlog\nxlog.exe"); | |
methods: | |
nxlog_install_repaired:: | |
"report" usebundle => rudder_common_report("Common", "log_repaired", "&TRACKINGKEY&", "Log system for reports", "None", "Installed NXLog"); | |
nxlog_install_failed:: | |
"report" usebundle => rudder_common_report("Common", "result_error", "&TRACKINGKEY&", "Log system for reports", "None", "Failed to install NXLog"); | |
commands: | |
windows.!nxlog_ok:: | |
"\"${sys.winsysdir}\msiexec.exe\"" | |
args => "/q /i \"${g.rudder_sbin}\nxlog-ce-2.8.1248.msi", | |
classes => rudder_common_classes("nxlog_install"), | |
comment => "Installing nxlog"; | |
} | |
bundle agent nxlog_configure | |
{ | |
vars: | |
!x86_64:: | |
"nxlog_config_file" string => "${sys.winprogdir}\nxlog\conf\nxlog.conf"; | |
"install_path" string => "${sys.winprogdir}"; | |
x86_64:: | |
"nxlog_config_file" string => "${sys.winprogdir86}\nxlog\conf\nxlog.conf"; | |
"install_path" string => "${sys.winprogdir86}"; | |
files: | |
"${nxlog_config_file}" | |
create => "true", | |
classes => rudder_common_classes("nxlog_configure"), | |
edit_line => nxlog_parameters("${server_info.cfserved}", "&SYSLOGPORT&", "TCP", "${nxlog_common.nxlog_tpl}", "${nxlog_configure.install_path}"), | |
edit_defaults => empty_backup; | |
methods: | |
nxlog_configure_error:: | |
"report" usebundle => rudder_common_report("Common", "result_error", "&TRACKINGKEY&", "Log system for reports", "None", "Failed to configure NXLog"); | |
nxlog_configure_repaired:: | |
"report" usebundle => rudder_common_report("Common", "log_repaired", "&TRACKINGKEY&", "Log system for reports", "None", "Update NXLog configuration"); | |
} | |
&if(NOVA)& | |
bundle agent nxlog_launch | |
{ | |
methods: | |
nxlog_service_error:: | |
"report" usebundle => rudder_common_report("Common", "result_error", "&TRACKINGKEY&", "Log system for reports", "None", "Error while checking or restarting NXLog server"); | |
nxlog_service_repaired:: | |
"report" usebundle => rudder_common_report("Common", "log_repaired", "&TRACKINGKEY&", "Log system for reports", "None", "NXLog was restarted"); | |
services: | |
"nxlog" | |
service_policy => "start", | |
service_method => u_bootstart, | |
classes => rudder_common_classes("nxlog_service"); | |
} | |
&endif& | |
# Parameters are used in the template, expanded thanks to the expand_scalars => true | |
bundle edit_line nxlog_parameters(server, port, protocol, template, install_path) | |
{ | |
insert_lines: | |
"${template}" | |
insert_type => "file", | |
expand_scalars => "true"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent internal_security | |
{ | |
vars: | |
!windows:: | |
"mode" string => "600"; | |
"user" string => "root"; | |
"group" string => "0"; # This is "root" on most UNIX-like systems, but "system" on AIX | |
#windows:: | |
# "mode" string => "755"; | |
# "user" string => "Administrator"; | |
# "group" string => "Administrators"; | |
files: | |
!windows:: | |
"${g.rudder_var}/cfengine-community/inputs" | |
depth_search => recurse("inf"), | |
perms => mog("${mode}", "${user}", "${group}"), | |
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); | |
"${g.rudder_var}/cfengine-community/inputs" | |
perms => mog("${mode}", "${user}", "${group}"), | |
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); | |
"${g.rudder_var}/cfengine-community/ppkeys" | |
depth_search => recurse("inf"), | |
perms => mog("${mode}", "${user}", "${group}"), | |
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); | |
"${g.rudder_var}/cfengine-community/ppkeys" | |
perms => mog("${mode}", "${user}", "${group}"), | |
classes => kept_if_else("security_sanitization_ok", "security_sanitization_repaired", "security_sanitization_failed"); | |
reports: | |
security_sanitization_ok.!security_sanitization_repaired:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Security parameters@@None@@${g.execRun}##${g.uuid}@#The internal environment security is acceptable"; | |
security_sanitization_repaired:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Security parameters@@None@@${g.execRun}##${g.uuid}@#Some internal security parameters were adjusted"; | |
security_sanitization_failed:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Security parameters@@None@@${g.execRun}##${g.uuid}@#The internal environment security is NOT acceptable!"; | |
windows:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Security parameters@@None@@${g.execRun}##${g.uuid}@#No internal security parameters defined for Windows OSes yet"; | |
} | |
##################################################################################### | |
# Copyright 2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent check_zypper | |
{ | |
commands: | |
SuSE:: | |
"${g.rudder_tools}/check_zypper_version" | |
module => "true"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent process_matching | |
{ | |
vars: | |
# This deliberately excludes cf-execd which is handled separately below | |
"cf_components" slist => { | |
"cf-key", | |
# "cf-monitord", Disabled | |
"cf-promises", | |
"cf-runagent", | |
"cf-serverd" | |
}; | |
windows:: | |
"stop_signal" string => "kill"; | |
!windows:: | |
"stop_signal" string => "term"; | |
classes: | |
"restart_cf" expression => "Hr05.Min00_05"; | |
files: | |
linux:: | |
# This is to cleanup /etc/crontab from pre-2.5 usage | |
# and initial promises before 2.7 | |
"${g.crontab}" | |
edit_defaults => noempty_backup, | |
edit_line => cron_cleanup; | |
# Temporary cron file added by rudder-agent postinst to prevent from UUID removal. | |
# When this promise will be generated, this cron will be useless then removed. | |
# (see http://www.rudder-project.org/redmine/issues/3925 and http://www.rudder-project.org/redmine/issues/3930). | |
"/etc/cron.d/rudder-agent-uuid" delete => tidy; | |
community_edition.!aix:: | |
"/etc/cron.d/rudder-agent" | |
create => "true", | |
perms => mog("644", "root", "root"), | |
edit_defaults => empty_backup, | |
edit_line => expand_template("${sys.workdir}/inputs/common/cron/rudder_agent_community_cron"); | |
&if(NOVA)& | |
nova_edition.!aix.!windows:: | |
"/etc/cron.d/rudder-agent-nova" | |
create => "true", | |
perms => mog("644", "root", "root"), | |
edit_defaults => empty_backup, | |
edit_line => expand_template("${sys.workdir}/inputs/common/cron/rudder_agent_nova_cron"); | |
&endif& | |
aix:: | |
# Cleanup the crontab | |
"/var/spool/cron/crontabs/root" | |
edit_defaults => noempty_backup, | |
edit_line => delete_lines_matching("0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* if \[ -x /opt/rudder/bin/check-rudder-agent \]; then /opt/rudder/bin/check-rudder-agent; fi"); | |
# Add Rudder entry | |
"/var/spool/cron/crontabs/root" | |
create => "true", | |
perms => mog("600", "root", "cron"), | |
edit_line => insert_lines("0,5,10,15,20,25,30,35,40,45,50,55 * * * * if [ -x /opt/rudder/bin/check-rudder-agent ]; then /opt/rudder/bin/check-rudder-agent >/dev/null; fi"), | |
classes => rudder_common_classes("rudder_aix_crontab_insertion"), | |
comment => "Insert an AIX-compatible user crontab to run /opt/rudder/bin/check-rudder-agent"; | |
processes: | |
windows:: | |
# Always stop cf-monitord | |
"${g.escaped_workdir}\/bin\/cf-monitord" signals => { "${stop_signal}" }; | |
!windows:: | |
# Always stop cf-monitord | |
"${sys.workdir}/bin/cf-monitord" signals => { "${stop_signal}" }; | |
restart_cf.!policy_server:: | |
"${cf_components}" signals => { "${stop_signal}" }; | |
# Policy servers have both Nova and Community, don't blindly kill the wrong processes | |
restart_cf.policy_server:: | |
"${sys.workdir}/bin/${cf_components}" signals => { "${stop_signal}" }; | |
restart_cf.!windows:: | |
"${sys.workdir}/bin/cf-execd" signals => { "${stop_signal}" }; | |
# Note: cron will get restarted automatically by init (respawn directive in inittab) | |
aix.rudder_aix_crontab_insertion:: | |
"^/usr/sbin/cron" signals => { "${stop_signal}" }; | |
&if(NOVA)& | |
services: | |
restart_cf.windows:: | |
"CfengineNovaExec" | |
service_policy => "stop", | |
comment => "Stop the executor service, part of scheduled restart"; | |
"CfengineNovaExec" | |
service_policy => "start", | |
comment => "Start the executor service, part of scheduled restart"; | |
&endif& | |
commands: | |
restart_cf.!windows:: | |
"${sys.cf_serverd}"; | |
"${sys.cf_execd}"; | |
reports: | |
restart_cf:: | |
"Reloaded configuration of all Cfengine components"; | |
} | |
# This is to cleanup /etc/crontab from pre-2.5 usage | |
# and initial promises before 2.7 | |
bundle edit_line cron_cleanup | |
{ | |
# Remove old lines to replace them with new version | |
delete_lines: | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-execd; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-execd; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-execd; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-execd; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/cfengine/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/cfengine/bin/cf-agent -f failsafe.cf \&\& /var/cfengine/bin/cf-agent; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep cf-execd \| grep \"/var/rudder/cfengine-community/bin/cf-execd\" \| grep -v grep \| wc -l\` -eq 0 \]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \&\& /var/rudder/cfengine-community/bin/cf-agent; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/cfengine/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/cfengine/bin/cf-agent -f failsafe.cf \&\& /var/cfengine/bin/cf-agent; fi"; | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/rudder/cfengine-community/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \&\& /var/rudder/cfengine-community/bin/cf-agent; fi"; | |
# Remove entry with wrong escapements from /etc/crontab | |
"0,5,10,15,20,25,30,35,40,45,50,55 \* \* \* \* root if \[ ! -e /opt/rudder/etc/disable-agent -a \`ps -efww \| grep -E \"\(cf-execd\|cf-agent\)\" \| grep -E \"/var/rudder/cfengine-community/bin/\(cf-execd\|cf-agent\)\" \| grep -v grep \| wc -l\` -eq 0 ]; then /var/rudder/cfengine-community/bin/cf-agent -f failsafe.cf \\\&\\\& /var/rudder/cfengine-community/bin/cf-agent; fi"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Define what an agent has to do when it updates | |
# its promises | |
# | |
#simple copy method | |
body copy_from remote(server, path) | |
{ | |
servers => { | |
"${server}" | |
}; | |
encrypt => "true"; | |
trustkey => "true"; | |
source => "${path}"; | |
compare => "digest"; | |
preserve => "false"; #preserver permissions | |
verify => "true"; | |
purge => "true"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
#simple copy method, unencrypted | |
body copy_from remote_unsecured(server, path) | |
{ | |
servers => { | |
"${server}" | |
}; | |
encrypt => "false"; | |
trustkey => "true"; | |
source => "${path}"; | |
compare => "mtime"; | |
preserve => "true"; #preserver permissions | |
verify => "true"; | |
purge => "true"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
body copy_from copy_digest_without_perms(from) | |
{ | |
source => "${from}"; | |
copy_backup => "false"; | |
preserve => "false"; | |
compare => "digest"; | |
purge => "true"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
body copy_from remote_unsecured_without_perms(server, path) | |
{ | |
servers => { | |
"${server}" | |
}; | |
encrypt => "false"; | |
trustkey => "true"; | |
source => "${path}"; | |
compare => "digest"; | |
preserve => "false"; | |
verify => "true"; | |
purge => "true"; | |
community_edition:: | |
portnumber => "&COMMUNITYPORT&"; | |
} | |
bundle common server_info | |
{ | |
vars: | |
any:: | |
"policy_files" string => "/var/rudder/share/&UUID&"; #directory where to look for promises in the server for that client | |
policy_server:: | |
"cfserved" string => "&POLICYSERVER&"; | |
!policy_server:: | |
"policy_server_file" | |
string => translatepath("${sys.workdir}/policy_server.dat"), | |
comment => "Path to file containing address to policy server"; | |
"cfserved" string => readfile("${policy_server_file}", 2048); | |
} | |
# The update is now split in two parts | |
# - the action part, only launched during failsafe | |
# it copies files, restarts deamons, defines persistent classes | |
# - the report part, not done during failsafe but during regular run | |
# note that if in verbose_mode, then the reporting will be done | |
# as well during failsafe | |
# | |
# Since the defined class are persistent, the classes are still | |
# available during the "normal" agent execution, for reporting | |
bundle agent update | |
{ | |
methods: | |
failsafe:: | |
"update" usebundle => update_action; | |
(!failsafe|verbose_mode):: | |
"report" usebundle => update_reports; | |
reports: | |
# We want to have always reports if something goes bad | |
rudder_promises_generated_error|no_update:: | |
"********************************************************************************* | |
* rudder-agent could not get an updated configuration from the policy server. * | |
* This can be caused by a network issue, an unavailable server, or if this * | |
* node was deleted from the Rudder root server. * | |
* Any existing configuration policy will continue to be applied without change. * | |
*********************************************************************************" | |
action => immediate; | |
} | |
bundle agent update_action | |
{ | |
vars: | |
"client_inputs" string => "${sys.workdir}/inputs"; #where to put the files on the client when downloaded | |
"file_to_check_update" string => "rudder_promises_generated"; | |
nova_edition:: | |
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-nova"; #actual directory with promises | |
community_edition:: | |
"server_inputs" string => "${server_info.policy_files}/rules/cfengine-community"; #actual directory with promises | |
files: | |
any:: | |
"${g.rudder_ncf}/." | |
create => "true", | |
comment => "Make sure the ncf directory exists"; | |
root_server:: | |
"${g.rudder_ncf}/common" | |
copy_from => copy_digest_without_perms("${g.rudder_ncf_origin_common}"), | |
depth_search => recurse_ignore("inf", @{g.excludedreps}), | |
perms => u_mog("644", "root", "root"), | |
action => immediate, | |
classes => success("rudder_ncf_common_updated", "rudder_ncf_common_update_error", "rudder_ncf_common_updated_ok"), | |
comment => "Update the common Rudder ncf instance"; | |
"${g.rudder_ncf}/local" | |
copy_from => copy_digest_without_perms("${g.rudder_ncf_origin_local}"), | |
depth_search => recurse_ignore("inf", @{g.excludedreps}), | |
perms => u_mog("644", "root", "root"), | |
action => immediate, | |
classes => success("rudder_ncf_local_updated", "rudder_ncf_local_update_error", "rudder_ncf_local_updated_ok"), | |
comment => "Update the local Rudder ncf instance"; | |
!root_server:: | |
"${g.rudder_ncf}/common" | |
copy_from => remote_unsecured_without_perms("${server_info.cfserved}", "${g.rudder_ncf_origin_common}"), | |
depth_search => recurse_ignore("inf", @{g.excludedreps}), | |
perms => u_mog("644", "root", "0"), | |
action => immediate, | |
classes => success("rudder_ncf_common_updated", "rudder_ncf_common_update_error", "rudder_ncf_common_updated_ok"), | |
comment => "Update the common Rudder ncf instance"; | |
"${g.rudder_ncf}/local" | |
copy_from => remote_unsecured_without_perms("${server_info.cfserved}", "${g.rudder_ncf_origin_local}"), | |
depth_search => recurse_ignore("inf", @{g.excludedreps}), | |
perms => u_mog("644", "root", "0"), | |
action => immediate, | |
classes => success("rudder_ncf_local_updated", "rudder_ncf_local_update_error", "rudder_ncf_local_updated_ok"), | |
comment => "Update the local Rudder ncf instance"; | |
"${client_inputs}/${file_to_check_update}" | |
copy_from => remote("${server_info.cfserved}","${server_inputs}/${file_to_check_update}"), | |
action => immediate, | |
classes => success("rudder_promises_generated_repaired", "rudder_promises_generated_error", "rudder_promises_generated_ok"); | |
# The defined class are persistent, so if they are already set, promises has already been updated | |
# a short while ago | |
rudder_promises_generated_repaired.!root_server:: | |
"${client_inputs}" | |
copy_from => remote("${server_info.cfserved}","${server_inputs}"), | |
depth_search => recurse("inf"), | |
action => immediate, | |
classes => success("config", "no_update", "config_ok"); | |
root_server|(rudder_promises_generated_ok|(rudder_promises_generated_repaired.(config|config_ok)).!no_update.!rudder_promises_generated_error):: | |
# Every time we check update inputs successfully (already up to date or | |
# updated), touch a file to let other promises know we are doing ok | |
"${sys.workdir}/last_successful_inputs_update" | |
touch => "true"; | |
# Copy the tools only if the file rudder_tools_updated is not up to date | |
any:: | |
"${g.rudder_tools_updated}" | |
copy_from => remote_unsecured("${server_info.cfserved}", "${g.rudder_tools_updated_origin}"), | |
action => immediate, | |
classes => success("rudder_tools_updated_repaired", "rudder_tools_updated_error", "rudder_tools_updated_kept"), | |
comment => "Check if we need to update the tools"; | |
# We copy only if we have the class rudder_tools_updated_repaired | |
rudder_tools_updated_repaired:: | |
"${g.rudder_tools}" | |
copy_from => remote_unsecured("${server_info.cfserved}", "${g.rudder_tools_origin}"), | |
depth_search => recurse_ignore("inf", @{g.excludedreps}), | |
action => immediate, | |
classes => success("rudder_tools_updated", "rudder_tools_update_error", "rudder_tools_updated_ok"), | |
comment => "Update the Rudder tools"; | |
processes: | |
config.!windows:: | |
"cf-serverd" restart_class => "start_server"; | |
config.!windows:: | |
"cf-execd" restart_class => "start_exec"; | |
&if(NOVA)& | |
services: | |
windows:: | |
"CfengineNovaExec" | |
service_policy => "start", | |
service_method => u_bootstart, | |
classes => outcome("executor"), | |
comment => "Start the executor windows service now and at boot time"; | |
&endif& | |
commands: | |
start_exec.!windows:: | |
"${sys.cf_execd}" | |
action => u_ifwin_bg, | |
classes => outcome("executor"); | |
start_exec.cygwin:: | |
"${sys.cf_execd}" | |
action => u_ifwin_bg, | |
classes => outcome("executor"); | |
start_server:: | |
"${sys.cf_serverd}" | |
action => u_ifwin_bg, | |
classes => outcome("server"); | |
######################################################### | |
reports: | |
server_ok:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Started the server (cf-serverd)"; | |
executor_ok:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Started the scheduler (cf-execd)"; | |
} | |
# This bundle is responsible for the reporting of what happened in the update | |
# It can work because the classes defined during the update are persistent, so | |
# the classes are available for the next 4 minutes | |
bundle agent update_reports | |
{ | |
reports: | |
no_update:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update node's policy (CFEngine promises)"; | |
rudder_tools_update_error:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update Rudder tools"; | |
rudder_ncf_common_update_error:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update common Rudder ncf instance"; | |
rudder_ncf_local_update_error:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update local Rudder ncf instance"; | |
rudder_promises_generated_error:: | |
"@@Common@@result_error@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Cannot update node's policy"; | |
(rudder_promises_generated_ok|(rudder_tools_updated_ok.rudder_ncf_common_updated_ok.rudder_ncf_local_updated_ok.config_ok)).!(rudder_promises_generated_repaired|rudder_promises_generated_error|rudder_tools_updated|rudder_tools_update_error|rudder_ncf_common_updated|rudder_ncf_common_update_error|rudder_ncf_local_updated|rudder_ncf_local_update_error|config|no_update):: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder policy, tools and ncf instance are already up to date. No action required."; | |
rudder_tools_updated:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder tools updated"; | |
rudder_ncf_common_updated:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder ncf common instance updated"; | |
rudder_ncf_local_updated:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder ncf local instance updated"; | |
config:: | |
"@@Common@@log_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Node's policy (CFEngine promises) updated"; | |
rudder_promises_generated_repaired|config|rudder_tools_updated|rudder_ncf_common_updated|rudder_ncf_local_updated|server_ok|executor_ok:: | |
"@@Common@@result_repaired@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder policy, tools or ncf instance were updated or CFEngine service restarted"; | |
policy_server:: | |
"@@Common@@result_success@@&TRACKINGKEY&@@Update@@None@@${g.execRun}##${g.uuid}@#Rudder policy server doesn't need to be updated"; | |
} | |
############################################ | |
body classes outcome(x) | |
{ | |
promise_repaired => {"${x}_ok"}; | |
} | |
############################################ | |
body action u_background | |
{ | |
background => "true"; | |
} | |
############################################ | |
body classes success(if, else, kept) | |
{ | |
promise_kept => { "${kept}" }; | |
promise_repaired => { "${if}" }; | |
repair_failed => { "${else}" }; | |
repair_denied => { "${else}" }; | |
repair_timeout => { "${else}" }; | |
# persist for 4 minutes so that it wont overlap with the next | |
# execution in 5 minutes | |
persist_time => "4"; | |
} | |
############################################ | |
body action u_ifwin_bg | |
{ | |
windows:: | |
background => "true"; | |
} | |
&if(NOVA)& | |
body service_method u_bootstart | |
{ | |
service_autostart_policy => "boot_time"; | |
} | |
&endif& | |
body perms u_mog(mode,user,group) | |
{ | |
owners => { "${user}" }; | |
groups => { "${group}" }; | |
mode => "${mode}"; | |
} | |
# Cron file for Rudder | |
# | |
# Will manually run cf-agent in case cf-execd is no longer running. cf-agent will fire up a new cf-execd. | |
# | |
# To temporarily avoid this behaviour, touch /opt/rudder/etc/disable-agent. | |
# Don't forget to remove that file when you're done! | |
# | |
# If you want to report a specific message if the Rudder agent fails to restart, please create the | |
# /opt/rudder/etc/rudder-restart-message.txt file with your custom message inside. It will be sent by mail | |
# instead of the default one. | |
# Add a decent PATH to the environment before triggering anything | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
0,5,10,15,20,25,30,35,40,45,50,55 * * * * root . /etc/profile; if [ -e ${g.rudder_base}/bin/check-rudder-agent ]; then ${g.rudder_base}/bin/check-rudder-agent >/dev/null; else if [ ! -e ${g.rudder_base}/etc/disable-agent -a `ps -efww | grep -E "(cf-execd|cf-agent)" | grep -E "${sys.workdir}/bin/(cf-execd|cf-agent)" | grep -v grep | wc -l` -eq 0 ]; then ${sys.workdir}/bin/cf-agent -f failsafe.cf >/dev/null 2>\&1 \&\& ${sys.workdir}/bin/cf-agent >/dev/null 2>\&1; if [ $? != 0 ]; then if [ -f /opt/rudder/etc/rudder-restart-message.txt ]; then cat /opt/rudder/etc/rudder-restart-message.txt; else echo "Rudder agent was unable to restart on ${hostname}."; fi; fi; fi; fi | |
##################################################################################### | |
# Copyright 2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# This file contain the Global Parameters, to be available within all | |
# promises, in the form ${rudder_parameters.parameterName} | |
bundle common rudder_parameters { | |
vars: | |
&RUDDER_PARAMETERS:{parameter | "¶meter.parameterName&" string => "¶meter.escapedValue&"; | |
}& | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
####################################################### | |
# | |
# Server specific configuration | |
# | |
####################################################### | |
bundle server access_rules | |
{ | |
&if(CLIENTSLIST)& | |
# Access rules are only defined on a policy server. Standard nodes should not share any files. | |
access: | |
policy_server:: | |
&if(NOVA)& | |
"&UUID&" | |
handle => "policy_server_uuid", | |
resource_type => "literal", | |
admit => {".*"}; | |
&endif& | |
"${def.dir_masterfiles}" | |
handle => "grant_access_policy", | |
comment => "Grant access to the policy updates", | |
maproot => { @{def.acl} }, | |
admit => { @{def.acl} }; | |
"${g.rudder_tools}" | |
maproot => { @{def.acl} }, | |
admit => { @{def.acl} }; | |
"${g.rudder_ncf_origin_common}" | |
maproot => { @{def.acl} }, | |
admit => { @{def.acl} }; | |
"${g.rudder_ncf_origin_local}" | |
maproot => { @{def.acl} }, | |
admit => { @{def.acl} }; | |
&if(SHARED_FILES_FOLDER)& | |
"&SHARED_FILES_FOLDER&" | |
comment => "Grant access to the share files", | |
maproot => { @{def.acl} }, | |
admit => { @{def.acl} }; | |
&endif& | |
any:: | |
&if(SKIPIDENTIFY)& | |
&MANAGED_NODES_NAME, MANAGED_NODES_ID : {host, uuid | | |
"/var/rudder/share/&uuid&/" | |
maproot => { escape("&host&") }, | |
admit => { escape("&host&") }; | |
} & | |
&else& | |
&MANAGED_NODES_NAME, MANAGED_NODES_ID : {host, uuid | | |
"/var/rudder/share/&uuid&/" | |
maproot => { host2ip("&host&"), escape("&host&") }, | |
admit => { host2ip("&host&"), escape("&host&") }; | |
} & | |
&endif& | |
# the policy server must have access to the cfengine folder | |
"${sys.workdir}" | |
maproot => { host2ip("&POLICYSERVER&"), escape("&POLICYSERVER&") }, | |
admit => { host2ip("&POLICYSERVER&"), escape("&POLICYSERVER&") }; | |
&endif& | |
roles: | |
# Allow user root to set any class | |
".*" authorize => { "root" }; | |
} | |
bundle common def | |
{ | |
vars: | |
"policy_server_file" | |
string => translatepath("${sys.workdir}/policy_server.dat"), | |
comment => "Path to file containing address to policy server"; | |
"policy_server" | |
string => readfile("${policy_server_file}", 2048), | |
comment => "IP address or hostname to locate your policy host."; | |
"dir_masterfiles" string => translatepath("${sys.workdir}/masterfiles"); | |
# List here the IP masks that we grant access to on the server | |
&if(AUTHORIZED_NETWORKS)& | |
policy_server:: | |
"acl" slist => { | |
"127.0.0.0/8" , "::1", | |
"${def.policy_server}", # the policy server can connect to a relay | |
&AUTHORIZED_NETWORKS:{net|"&net&",}& | |
}; | |
&endif& | |
!policy_server:: | |
"acl" slist => { | |
"${def.policy_server}" | |
}; | |
} | |
body server control | |
{ | |
&if(SKIPIDENTIFY)& | |
trustkeysfrom => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
"&it&"};separator=", "& | |
&endif& | |
}; #trustkey allows the exchange of keys | |
allowconnects => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
"&it&"};separator=", "& | |
&endif& | |
}; | |
allowallconnects => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
"&it&"};separator=", "& | |
&endif& | |
}; | |
&else& | |
trustkeysfrom => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
host2ip("&it&"), "&it&"};separator=", "& | |
&endif& | |
}; #trustkey allows the exchange of keys | |
allowconnects => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
host2ip("&it&"), "&it&"};separator=", "& | |
&endif& | |
}; | |
allowallconnects => { | |
@{def.acl} , | |
&if(MANAGED_NODES_NAME)& | |
&MANAGED_NODES_NAME: { | |
host2ip("&it&"), "&it&"};separator=", "& | |
&endif& | |
}; | |
&endif& | |
maxconnections => "1000"; | |
logallconnections => "true"; | |
cfruncommand => "${sys.workdir}/bin/cf-agent -f failsafe.cf \&\& ${sys.workdir}/bin/cf-agent"; | |
allowusers => { | |
"&POLICYSERVER_ADMIN&", | |
&MANAGED_NODES_ADMIN : {admin | "&admin&" };separator=", "& | |
}; | |
denybadclocks => "&DENYBADCLOCKS&"; | |
skipverify => { "127.0.0.0/8" , "::1", @{def.acl} }; | |
community_edition:: | |
port => "&COMMUNITYPORT&"; | |
} | |
####################################################### | |
&if(CLIENTSLIST)& | |
body runagent control | |
{ | |
hosts => { | |
&CLIENTSLIST: { | |
"&it&",}& | |
}; | |
max_children => "25"; | |
community_edition:: | |
port => "&COMMUNITYPORT&"; | |
} | |
&endif& | |
# Cron file for Rudder | |
# | |
# Will manually run cf-agent in case cf-execd is no longer running. cf-agent will fire up a new cf-execd. | |
# | |
# To temporarily avoid this behaviour, touch /opt/rudder/etc/disable-agent. | |
# Don't forget to remove that file when you're done! | |
# | |
# If you want to report a specific message if the Rudder agent fails to restart, please create the | |
# /opt/rudder/etc/rudder-restart-message.txt file with your custom message inside. It will be sent by mail | |
# instead of the default one. | |
# Add a decent PATH to the environment before triggering anything | |
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
0,5,10,15,20,25,30,35,40,45,50,55 * * * * root . /etc/profile; if [ ! -e ${g.rudder_base}/etc/disable-agent -a `ps -efww | grep -E "(cf-execd|cf-agent)" | grep -E "${sys.workdir}/bin/(cf-execd|cf-agent))" | grep -v grep | wc -l` -eq 0 ]; then ${sys.workdir}/bin/cf-agent -f failsafe.cf >/dev/null 2>\&1 \&\& ${sys.workdir}/bin/cf-agent >/dev/null 2>\&1; if [ $? != 0 ]; then if [ -f /opt/rudder/etc/rudder-restart-message.txt ]; then cat /opt/rudder/etc/rudder-restart-message.txt; else echo "Rudder agent was unable to restart on ${hostname}."; fi; fi; fi | |
/var/log/rudder/apache2/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d apache2 reload > /dev/null | |
else | |
/etc/init.d/apache2 reload > /dev/null | |
fi | |
fi | |
endscript | |
} | |
/var/log/rudder/ldap/slapd.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog rotate > /dev/null | |
else | |
/etc/init.d/rsyslog rotate > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/reports/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog rotate > /dev/null | |
else | |
/etc/init.d/rsyslog rotate > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/core/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
} | |
/var/log/rudder/compliance/non-compliant-reports.log { | |
daily | |
missingok | |
rotate 365 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Configure rsyslog on the orchestrator | |
# This will provide promises to add the backports repos to Debian Lenny: | |
# - in sources.list | |
# - default apt_preferences to upgrade packages installed from backports | |
# - a package_method to install packages from backports via cfengine | |
bundle agent setup_debian_backports | |
{ | |
vars: | |
"apt_source_line" slist => { "deb http://backports.debian.org/debian-backports lenny-backports" }; | |
"apt_components" slist => { "main" }; | |
files: | |
debian_5:: | |
"/etc/apt/sources.list" | |
comment => "Include extra apt repos", | |
edit_line => append_if_no_lines("${apt_source_line} ${apt_components}"), | |
edit_defaults => noempty_backup, | |
classes => if_repaired("apt_sources_updated"); | |
"/etc/apt/preferences" | |
comment => "Set automatic upgrades for packages installed from backports (recommended setting from backports.debian.org)", | |
create => "true", | |
edit_line => append_if_no_lines("Package: *${const.n}Pin: release a=lenny-backports${const.n}Pin-Priority: 200"), | |
edit_defaults => noempty_backup, | |
classes => if_repaired("apt_preferences_repaired"); | |
commands: | |
apt_sources_updated:: | |
"/usr/bin/aptitude" | |
args => "update"; | |
reports: | |
apt_sources_updated:: | |
"apt's sources.list was edited, and an aptitude update will now run"; | |
apt_preferences_repaired:: | |
"apt's /etc/apt/preferences file was changed"; | |
} | |
bundle agent install_rsyslogd { | |
vars: | |
root_server:: | |
"rsyslog_source_file" string => "rudder-rsyslog-root.conf"; | |
policy_server.!root_server:: | |
"rsyslog_source_file" string => "rudder-rsyslog-relay.conf"; | |
files: | |
policy_server:: | |
"/etc/rsyslog.d/rudder.conf" | |
create => "true", | |
edit_defaults => empty, | |
edit_line => expand_template("${sys.workdir}/inputs/distributePolicy/rsyslog.conf/${rsyslog_source_file}"), | |
classes => cf2_if_else("rudder_rsyslog_conf_copied", "cannot_copy_rudder_rsyslog_conf"), | |
comment => "Copying rsyslog conf"; | |
"/etc/rsyslog.conf" | |
edit_line => append_if_no_lines("$IncludeConfig /etc/rsyslog.d/*.conf"), | |
edit_defaults => noempty_backup, | |
comment => "Add the rsyslog.conf.d include if not already present", | |
classes => cf2_if_else("rsyslog_inc_ok" , "rsyslog_inc_failed"); | |
policy_server.debian:: | |
"/etc/rsyslog.d/pgsql.conf" | |
edit_line => comment_all(), | |
edit_defaults => noempty_backup, | |
classes => cf2_if_else("rudder_rsyslog_pgsql", "cannot_update_rudder_rsyslog_pgsql"), | |
comment => "Removing the logging of all in the database"; | |
packages: | |
policy_server.debian_5.!SuSE:: | |
"rsyslog" | |
package_policy => "add", | |
package_method => debian_backports, | |
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"), | |
comment => "Installing rsyslog using apt backports"; | |
"rsyslog-pgsql" | |
package_policy => "add", | |
package_method => debian_backports, | |
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"), | |
comment => "Installing rsyslog_pgsql using apt backports"; | |
policy_server.!debian_5.!SuSE.!redhat:: | |
"rsyslog" | |
package_policy => "add", | |
package_method => generic, | |
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"), | |
comment => "Installing rsyslog using apt backports"; | |
"rsyslog-pgsql" | |
package_policy => "add", | |
package_method => generic, | |
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"), | |
comment => "Installing rsyslog_pgsql using apt backports"; | |
policy_server.!debian_5.!SuSE.redhat:: | |
"rsyslog" | |
package_policy => "add", | |
package_method => rudder_yum, | |
classes => cf2_if_else("rsyslog_installed", "cant_install_rsyslog"), | |
comment => "Installing rsyslog using apt backports"; | |
"rsyslog-pgsql" | |
package_policy => "add", | |
package_method => rudder_yum, | |
classes => cf2_if_else("rsyslog_pgsql_installed", "cant_install_rsyslog_pgsql"), | |
comment => "Installing rsyslog_pgsql using apt backports"; | |
commands: | |
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).!SuSE:: | |
"/etc/init.d/rsyslog" | |
args => "restart", | |
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"), | |
comment => "restarting rsyslog"; | |
policy_server.(rsyslog_installed|rsyslog_pgsql_installed|rudder_rsyslog_conf_copied|rudder_rsyslog_pgsql).SuSE:: | |
"/etc/init.d/syslog" | |
args => "restart", | |
classes => cf2_if_else("rsyslog_restarted", "cant_restart_rsyslog"), | |
comment => "restarting rsyslog"; | |
reports: | |
cant_install_rsyslog|cant_install_rsyslog_pgsql:: | |
"Fatal : Can't install rsyslog or rsyslog_pgsql on the Rudder root server !"; | |
cannot_copy_rudder_rsyslog_conf:: | |
"Fatal : Can't copy the rsyslog configuration !"; | |
rsyslog_inc_failed:: | |
"Fatal : Can't enable the rsyslog include directory !"; | |
cant_restart_rsyslog:: | |
"Fatal : Can't restart rsyslog !"; | |
cannot_update_rudder_rsyslog_pgsql:: | |
"Fatal : Cannot update the pgsql configuration !"; | |
rsyslog_restarted:: | |
"Info : Restarted rsyslog"; | |
} | |
# Package method to install packages from debian-backports | |
body package_method debian_backports | |
{ | |
debian:: | |
package_changes => "bulk"; | |
package_list_command => "/usr/bin/dpkg -l"; | |
package_list_name_regex => "ii\s+([^\s]+).*"; | |
package_list_version_regex => "ii\s+[^\s]+\s+([^\s]+).*"; | |
package_installed_regex => ".*"; # all reported are installed | |
package_name_convention => "${name}"; | |
package_list_update_ifelapsed => "240"; # 4 hours | |
debian.have_aptitude:: | |
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false -t lenny-backports --assume-yes install"; | |
package_list_update_command => "/usr/bin/aptitude update"; | |
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes -q remove"; | |
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/aptitude -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o Aptitude::Delete-Unused=false --assume-yes install"; | |
package_verify_command => "/usr/bin/aptitude show"; | |
package_noverify_regex => "(State: not installed|E: Unable to locate package .*)"; | |
debian.!have_aptitude:: | |
package_add_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -t lenny-backports install"; | |
package_list_update_command => "/usr/bin/apt-get update"; | |
package_delete_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes -q remove"; | |
package_update_command => "/usr/bin/env DEBIAN_FRONTEND=noninteractive LC_ALL=C /usr/bin/apt-get -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -o APT::Get::AutomaticRemove=false --yes install"; | |
package_verify_command => "/usr/bin/dpkg -s"; | |
package_noverify_returncode => "1"; | |
} | |
bundle edit_line comment_all() | |
{ | |
replace_patterns: | |
# comment all lines | |
"^[^#](.*)" | |
replace_with => comments; | |
} | |
body replace_with comments | |
{ | |
replace_value => "#${match.1}"; # backreference 0 | |
occurrences => "all"; # first, last all | |
} | |
/var/log/rudder/apache2/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d apache2 reload > /dev/null | |
else | |
/etc/init.d/apache2 reload > /dev/null | |
fi | |
fi | |
endscript | |
} | |
/var/log/rudder/ldap/slapd.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog reload > /dev/null | |
else | |
/etc/init.d/rsyslog reload > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/reports/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog reload > /dev/null | |
else | |
/etc/init.d/rsyslog reload > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/core/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
} | |
/var/log/rudder/compliance/non-compliant-reports.log { | |
daily | |
missingok | |
rotate 365 | |
compress | |
notifempty | |
create 640 root adm | |
} | |
##################################################################################### | |
# Copyright 2011-2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_logrotate_check | |
{ | |
vars: | |
(debian_5|debian_6).!ubuntu:: | |
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.old-debian"; | |
debian.!(debian_5|debian_6).!ubuntu:: | |
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.debian"; | |
ubuntu:: | |
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.ubuntu"; | |
redhat:: | |
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.rhel"; | |
!debian.!ubuntu.!redhat:: | |
"logrotate_file" string => "${sys.workdir}/inputs/distributePolicy/logrotate.conf/rudder.suse"; | |
files: | |
"/etc/logrotate.d/rudder" | |
copy_from => copy_digest("${logrotate_file}"), | |
classes => kept_if_else("rudder_logrotate_conf_ok", "rudder_logrotate_conf_copied", "cannot_copy_rudder_logrotate_conf"), | |
comment => "Copying the logrotate configuration"; | |
reports: | |
cfengine:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check logrotate configuration@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration is correct" | |
ifvarclass => "rudder_logrotate_conf_ok.!rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check logrotate configuration@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration has been updated" | |
ifvarclass => "rudder_logrotate_conf_copied.!cannot_copy_rudder_logrotate_conf"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check logrotate configuration@@None@@${g.execRun}##${g.uuid}@#The logrotate configuration could not be updated" | |
ifvarclass => "cannot_copy_rudder_logrotate_conf"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_technique_reload | |
{ | |
vars: | |
"root_technique_reload_rest_url" string => "http://localhost:8080/rudder/api/techniqueLibrary/reload"; | |
classes: | |
"root_technique_reload_trigger" expression => fileexists("${g.rudder_base}/etc/force_technique_reload"); | |
files: | |
root_technique_reload_rest_call_repaired:: | |
"${g.rudder_base}/etc/force_technique_reload" | |
delete => tidy, | |
comment => "Deleting the force_technique_reload file because it is no longer relevant"; | |
commands: | |
root_technique_reload_trigger:: | |
"/usr/bin/curl -s ${root_technique_reload_rest_url} |/bin/grep -q OK" | |
contain => in_shell_silent, | |
classes => rudder_common_classes("root_technique_reload_rest_call"), | |
comment => "Reload the Technique library using the Rudder API"; | |
reports: | |
root_technique_reload_trigger:: | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Check Technique library reloading file@@None@@${g.execRun}##${g.uuid}@#The ${g.rudder_base}/etc/force_technique_reload file is present. Reloading Technique library..."; | |
root_technique_reload_rest_call_repaired:: | |
"@@DistributePolicy@@log_repaired@@&TRACKINGKEY&@@Check Technique library reloading file@@None@@${g.execRun}##${g.uuid}@#The Technique library has been reloaded."; | |
root_technique_reload_rest_call_failed:: | |
"@@DistributePolicy@@log_warn@@&TRACKINGKEY&@@Check Technique library reloading file@@None@@${g.execRun}##${g.uuid}@#The Technique library failed to reload. Will try again next time"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_postgres_check | |
{ | |
vars: | |
SuSE:: | |
"configuration_statements" slist => { "host all rudder ::1/128 md5", "host all rudder 127.0.0.1/32 md5" }; | |
files: | |
SuSE:: | |
"/var/lib/pgsql/data/pg_hba.conf" | |
edit_line => prepend("${configuration_statements}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("psql_conf_ok", "psql_conf_updated", "psql_conf_update_error"), | |
comment => "Edit the SuSE postgresql configuration to enable account-less logins"; | |
commands: | |
SuSE:: | |
"/etc/init.d/postgresql" | |
args => "restart", | |
classes => kept_if_else("psql_restart_ok", "psql_restart_ok", "psql_restart_error"), | |
ifvarclass => "psql_conf_updated"; | |
reports: | |
SuSE:: | |
# Report about the configuration file edition | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration is present" | |
ifvarclass => "psql_conf_ok.!psql_conf_updated.!psql_conf_update_error"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration has been added" | |
ifvarclass => "psql_conf_updated.!psql_conf_update_error"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#The SuSE specific postgresql configuration could not be added" | |
ifvarclass => "psql_conf_update_error"; | |
# Reports about Postgres restart status | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#PostgreSQL has been restarted" | |
ifvarclass => "psql_restart_ok"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#PostgreSQL restart has failed! Rudder is most certainly broken..." | |
ifvarclass => "psql_restart_error"; | |
!SuSE:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check PostgreSQL configuration@@None@@${g.execRun}##${g.uuid}@#Their is no need of specific postgresql configuration on this system"; | |
} | |
/var/log/rudder/apache2/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -f "`. /etc/apache2/envvars ; echo ${APACHE_PID_FILE:-/var/run/apache2.pid}`" ]; then | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d apache2 reload > /dev/null | |
else | |
/etc/init.d/apache2 reload > /dev/null | |
fi | |
fi | |
endscript | |
} | |
/var/log/rudder/ldap/slapd.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 syslog adm | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog reload > /dev/null | |
else | |
/etc/init.d/rsyslog reload > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/reports/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 syslog adm | |
delaycompress | |
sharedscripts | |
postrotate | |
if [ -x /usr/sbin/invoke-rc.d ]; then | |
invoke-rc.d rsyslog reload > /dev/null | |
else | |
/etc/init.d/rsyslog reload > /dev/null | |
fi | |
endscript | |
} | |
/var/log/rudder/core/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root adm | |
} | |
/var/log/rudder/compliance/non-compliant-reports.log { | |
daily | |
missingok | |
rotate 365 | |
compress | |
notifempty | |
create 640 root adm | |
} | |
##################################################################################### | |
# Copyright 2014 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent compress_webapp_log | |
{ | |
vars: | |
# compress files older than 2 days | |
"log_compress_delay" int => "2"; | |
files: | |
"/var/log/rudder/webapp" | |
file_select => jetty_logs("${log_compress_delay}"), | |
depth_search => recurse("0"), | |
transformer => "${g.gzip} \"${this.promiser}\""; | |
} | |
body file_select jetty_logs(days) | |
{ | |
leaf_name => { ".*\.log", ".*\.log\.\d+" }; | |
mtime => irange(ago(0,0,"${days}",0,0,0),now); | |
file_result => "leaf_name.!mtime"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_alive_check | |
{ | |
vars: | |
"apps_to_check" slist => { "rudder", "endpoint" }; | |
methods: | |
"any" usebundle => generic_alive_check("${apps_to_check}"); | |
} | |
bundle agent generic_alive_check(app) | |
{ | |
vars: | |
"site_to_check" string => "http://localhost:8080/${app}/api/status"; | |
"sitename" string => canonify("${site_to_check}"); | |
"cleanup_failed_classes" slist => { "site_down_once_${sitename}", "site_alivecheck_restart_jetty_${sitename}" }; | |
"failed_result_class" string => "site_down_once_${sitename}", | |
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed"; | |
"site_failure_persist_time" string => "10", | |
ifvarclass => "!site_down_once_${sitename}.!first_iteration_passed"; | |
"failed_result_class" string => "site_alivecheck_restart_jetty_${sitename}", | |
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed"; | |
"site_failure_persist_time" string => "0", | |
ifvarclass => "site_down_once_${sitename}.!first_iteration_passed"; | |
classes: | |
"first_iteration_passed" expression => "any"; | |
methods: | |
root_server:: | |
"any" usebundle => generic_process_check_process(".*java.*/opt/rudder/jetty7/start.jar", "rudder-jetty", "jetty", "true", "false"), | |
ifvarclass => "site_alivecheck_restart_jetty_${sitename}", | |
classes => set_persist_classes("site_alivecheck_jetty_restarted_${sitename}", "site_down_once_${sitename}" ,"0"); | |
commands: | |
root_server:: | |
"/usr/bin/curl -s ${site_to_check} |/bin/grep -q OK" | |
contain => in_shell_silent, | |
classes => set_persist_classes_alivecheck("site_ok", "${failed_result_class}", "@{generic_alive_check.cleanup_failed_classes}", "${site_failure_persist_time}"), | |
comment => "Checking if ${site_to_check} is alive"; | |
reports: | |
root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check ${app} status@@None@@${g.execRun}##${g.uuid}@#The ${site_to_check} web application is running" | |
ifvarclass => "site_ok.!site_down_once_${sitename}"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check ${app} status@@None@@${g.execRun}##${g.uuid}@#This is the first time the ${site_to_check} web application failed to respond. Deferring the restart." | |
ifvarclass => "site_down_once_${sitename}.!site_alivecheck_restart_jetty_${sitename}"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check ${app} status@@None@@${g.execRun}##${g.uuid}@#The ${site_to_check} web application failed to respond for the second time. Restarting jetty NOW !" | |
ifvarclass => "site_alivecheck_restart_jetty_${sitename}"; | |
policy_server.!root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check ${app} status@@None@@${g.execRun}##${g.uuid}@#The ${site_to_check} web application check do not need to be done on relay servers. Skipping..."; | |
} | |
body classes set_persist_classes_alivecheck(repaired, failed, cancelifok, length) | |
{ | |
promise_kept => { "${repaired}" }; | |
promise_repaired => { "${repaired}" }; | |
repair_failed => { "${failed}" }; | |
repair_denied => { "${failed}" }; | |
repair_timeout => { "${failed}" }; | |
cancel_kept => {"@{cancelifok}"}; | |
cancel_repaired => {"@{cancelifok}"}; | |
cancel_notkept => {"${repaired}"}; | |
persist_time => "${length}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Fetch the promises from the server to be available for others machines | |
# Must not do it on the RootServer though... | |
bundle agent propagatePromises | |
{ | |
vars: | |
any:: | |
"server_data" string => "${server_info.policy_files}/share"; #actual directory with data to propagate | |
"client_data" string => "${g.rudder_var}/share/"; #where to put the files on the client when downloaded | |
classes: | |
root_server:: | |
"rudder_tools_updated_exists" expression => fileexists("${g.rudder_tools_updated_origin}"); | |
files: | |
root_server:: | |
"${g.rudder_tools}" | |
copy_from => copy("${g.rudder_base}/share/tools"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the tools for the promises execution", | |
classes => classes_generic("propagate_tools"); | |
policy_server.!root_server:: | |
"${client_data}" #that's a loop on each files in client_inputs | |
copy_from => remote("${server_info.cfserved}","${server_data}"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the promises to propagate", | |
classes => if_else("promises_propagated", "could_not_propagate_promise"); | |
"${g.rudder_ncf_origin_local}" | |
copy_from => remote("${server_info.cfserved}","${g.rudder_ncf_origin_local}"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the ncf local to propagate", | |
classes => if_else("ncf_local_promises_propagated", "could_not_propagate_ncf_local_promise"); | |
"${g.rudder_ncf_origin_common}" | |
copy_from => remote("${server_info.cfserved}","${g.rudder_ncf_origin_common}"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the ncf common to propagate", | |
classes => if_else("ncf_common_promises_propagated", "could_not_propagate_ncf_common_promise"); | |
"&SHARED_FILES_FOLDER&" | |
copy_from => remote("${server_info.cfserved}","&SHARED_FILES_FOLDER&"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the files shared for the promises execution", | |
classes => if_else("files_propagated", "could_not_propagate_files"); | |
"${g.rudder_tools}" | |
copy_from => remote("${server_info.cfserved}","${g.rudder_tools}"), | |
depth_search => recurse_visible("inf"), | |
comment => "Fetching the tools for the promises execution", | |
classes => if_else("tools_propagated", "could_not_propagate_tools"); | |
"${sys.workdir}/masterfiles" | |
copy_from => remote("${server_info.cfserved}","${sys.workdir}/masterfiles"), | |
depth_search => recurse_visible("inf"), | |
file_select => no_license_dat, #We don't want to propagate a wrong license.dat | |
comment => "Fetching the bootstrap promises", | |
classes => if_else("masterfiles_propagated", "could_not_propagate_masterfiles"); | |
&if(NOVA)& | |
"${sys.workdir}/masterfiles/license.dat" | |
copy_from => local_cp("${sys.workdir}/inputs/license.dat"), | |
comment => "Putting the right license in the bootstrap", | |
classes => if_else("license_copied", "could_not_copy_license"); | |
&endif& | |
# If rudder_tools_updated doesn't exist, or if the tools have been updated, | |
# set rudder_tools_updated content to current timestamp | |
root_server.(!rudder_tools_updated_exists|propagate_tools_repaired):: | |
"${g.rudder_tools_updated_origin}" | |
create => "true", | |
edit_defaults => empty, | |
edit_line => insert_lines("${sys.date}"), | |
comment => "Update the timestamp in the rudder tool updated file"; | |
reports: | |
# Success if files are updated or not changed (kept or repaired). | |
# root server have only tools to be updated and others have tools, | |
# promises, masterfiles folder and licenses to be updated. | |
((root_server.propagate_tools_ok)|(!root_server.propagate_tools_ok.promises_propagated.masterfiles_propagated.license_copied.ncf_local_promises_propagated.ncf_common_promises_propagated)).!(propagate_tools_error|could_not_propagate_promise|could_not_propagate_masterfiles|could_not_copy_license|could_not_propagate_ncf_local_promise|could_not_propagate_ncf_common_promise):: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#All files have been propagated"; | |
could_not_propagate_promise:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate policy files"; | |
could_not_propagate_files:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate shared files"; | |
propagate_tools_error:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate tools"; | |
could_not_propagate_ncf_local_promise:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate local ncf promises"; | |
could_not_propagate_ncf_common_promise:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate common ncf promises"; | |
could_not_propagate_masterfiles:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot propagate masterfiles"; | |
could_not_copy_license:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Propagate promises@@None@@${g.execRun}##${g.uuid}@#Cannot copy local license"; | |
} | |
# Sending the inventory to cmdb (or syncing with the server if we are a simple relay) | |
# We cannot use list of paths to send the inventories because it cause the transformer to fail | |
# for some unknown reason | |
bundle agent sendInventoryToCmdb | |
{ | |
files: | |
root_server:: | |
"${g.rudder_inventories}/incoming" | |
transformer => "${g.rudder_tools}/send-clean.sh &CMDBENDPOINT& ${this.promiser} ${g.rudder_inventories}/received/ ${g.rudder_inventories}/failed/", | |
depth_search => recurse_visible(1), | |
file_select => all_files, | |
classes => rudder_common_classes("rudder_inventory_processing"), | |
comment => "Processing a local inventory"; | |
"${g.rudder_inventories}/accepted-nodes-updates" | |
transformer => "${g.rudder_tools}/send-clean.sh &CMDBENDPOINT& ${this.promiser} ${g.rudder_inventories}/received/ ${g.rudder_inventories}/failed/", | |
depth_search => recurse_visible(1), | |
file_select => all_files, | |
classes => rudder_common_classes("rudder_inventory_processing"), | |
comment => "Processing a local inventory"; | |
policy_server.!root_server:: | |
"${g.rudder_inventories}/incoming" | |
transformer => "/usr/bin/curl -f -s --proxy '' --user rudder:rudder -T ${this.promiser} http://${server_info.cfserved}/inventories/", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => rudder_common_classes("rudder_inventory_relay"), | |
comment => "Sending an inventory to the root server"; | |
"${g.rudder_inventories}/accepted-nodes-updates" | |
transformer => "/usr/bin/curl -f -s --proxy '' --user ${g.davuser}:${g.davpw} -T ${this.promiser} http://${server_info.cfserved}/inventory-updates/", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => rudder_common_classes("rudder_inventory_relay"), | |
comment => "Sending an inventory to the root server"; | |
policy_server.!root_server.!rudder_inventory_relay_error:: | |
"${g.rudder_inventories}/incoming" | |
transformer => "/bin/rm -f ${this.promiser}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => rudder_common_classes("rudder_inventory_cleanup"), | |
comment => "Purging the received inventory files after processing"; | |
"${g.rudder_inventories}/accepted-nodes-updates" | |
transformer => "/bin/rm -f ${this.promiser}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => rudder_common_classes("rudder_inventory_cleanup"), | |
comment => "Purging the received inventory files after processing"; | |
reports: | |
rudder_inventory_processing_repaired.!rudder_inventory_processing_error:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Incoming inventories were successfully added to Rudder"; | |
rudder_inventory_processing_error:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Some inventories failed to add successfully to Rudder"; | |
root_server.!rudder_inventory_processing_repaired.!rudder_inventory_processing_error:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#No inventory to send"; | |
rudder_inventory_relay_repaired.!rudder_inventory_relay_error:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Incoming inventories were successfully relayed to the root server"; | |
rudder_inventory_relay_error:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Cannot relay some inventories to the root server"; | |
policy_server.!root_server.!rudder_inventory_relay_repaired.!rudder_inventory_relay_error:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#No inventory to relay"; | |
rudder_inventory_cleanup_repaired.!rudder_inventory_cleanup_error:: | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Sent incoming inventories were removed from local cache"; | |
rudder_inventory_cleanup_error:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Send inventories to CMDB@@None@@${g.execRun}##${g.uuid}@#Cannot remove incoming inventories from local cache"; | |
} | |
body file_select all_files | |
{ | |
leaf_name => { ".*\..*" }; | |
file_result => "leaf_name"; | |
} | |
body file_select no_license_dat | |
{ | |
leaf_name => { "license\.dat" }; | |
file_result => "!leaf_name"; | |
} | |
/var/log/rudder/apache2/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
sharedscripts | |
postrotate | |
/etc/init.d/apache2 reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/ldap/slapd.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
postrotate | |
/etc/init.d/syslog reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/reports/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
sharedscripts | |
postrotate | |
/etc/init.d/syslog reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/core/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
} | |
/var/log/rudder/compliance/non-compliant-reports.log { | |
daily | |
missingok | |
rotate 365 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_init_check() | |
{ | |
vars: | |
"service[1][name]" string => "slapd"; | |
"service[1][binary]" string => "/opt/rudder/libexec/slapd"; | |
"service[1][initscript]" string => "rudder-slapd"; | |
"service[1][check_on_relay_server]" string => "false"; | |
"service[2][name]" string => "jetty"; | |
"service[2][binary]" string => ".*java.*/opt/rudder/jetty7/start.jar"; | |
"service[2][initscript]" string => "rudder-jetty"; | |
"service[2][check_on_relay_server]" string => "false"; | |
"service[3][name]" string => "postgresql"; | |
"service[3][binary]" string => "postgres: writer process"; | |
"service[3][initscript]" string => "postgresql"; | |
"service[3][check_on_relay_server]" string => "false"; | |
"service[4][name]" string => "apache"; | |
"service[4][check_on_relay_server]" string => "true"; | |
!redhat:: | |
"service[4][binary]" string => "apache2"; | |
"service[4][initscript]" string => "apache2"; | |
redhat:: | |
"service[4][binary]" string => "httpd"; | |
"service[4][initscript]" string => "httpd"; | |
any:: | |
"index" slist => getindices("service"); | |
methods: | |
"any" usebundle => generic_process_check_process("${service[${index}][binary]}", "${service[${index}][initscript]}", "${service[${index}][name]}", "false", "${service[${index}][check_on_relay_server]}"); | |
"any" usebundle => generic_process_check_bootstart("${service[${index}][binary]}", "${service[${index}][initscript]}", "${service[${index}][name]}"); | |
} | |
bundle agent generic_process_check_process(binary, initscript, name, force_restart, check_on_relay_server) { | |
vars: | |
"canoname" string => canonify("${binary}"); | |
classes: | |
"forced_trigger_${canoname}" expression => strcmp("${force_restart}", "true"); | |
# Raise this class if we are handling a process that should be checked even on | |
# relay servers. | |
"process_exception_on_relay" expression => strcmp("${check_on_relay_server}", "true"); | |
processes: | |
root_server|process_exception_on_relay:: | |
# check the service status | |
"${binary}" | |
comment => "Check the process status", | |
restart_class => "process_restart_${canoname}", | |
classes => kept_if_else("service_running_${canoname}", "service_anomaly_${canoname}", "service_error_${canoname}"); | |
commands: | |
root_server|process_exception_on_relay:: | |
"/etc/init.d/${initscript}" | |
args => "restart </dev/null >/dev/null 2>/dev/null", | |
contain => in_shell_silent, | |
# action => bg("0", "120"), | |
classes => kept_if_else("process_restart_ok_${canoname}", "process_restart_ok_${canoname}", "process_restart_error_${canoname}"), | |
ifvarclass => "process_restart_${canoname}|forced_trigger_${canoname}"; | |
reports: | |
root_server|process_exception_on_relay:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check ${name} process@@None@@${g.execRun}##${g.uuid}@#The ${name} process is already running" | |
ifvarclass => "!process_restart_${canoname}.!forced_trigger_${canoname}"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check ${name} process@@None@@${g.execRun}##${g.uuid}@#The ${name} process was not running and has been restarted" | |
ifvarclass => "process_restart_${canoname}.process_restart_ok_${canoname}.!forced_trigger_${canoname}"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check ${name} process@@None@@${g.execRun}##${g.uuid}@#The ${name} process has been restarted" | |
ifvarclass => "process_restart_ok_${canoname}.forced_trigger_${canoname}"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check ${name} process@@None@@${g.execRun}##${g.uuid}@#The ${name} process couldn't be restarted" | |
ifvarclass => "process_restart_error_${canoname}"; | |
policy_server.!root_server.!process_exception_on_relay:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check ${name} process@@None@@${g.execRun}##${g.uuid}@#The ${name} process do not need to be checked on relay servers. Skipping..."; | |
} | |
bundle agent generic_process_check_bootstart(binary, initscript, name) { | |
vars: | |
"canoname" string => canonify("${binary}"); | |
SuSE:: | |
"check_command" string => "/sbin/chkconfig --check ${initscript}"; | |
"bootstart_command" string => "/sbin/insserv -d ${initscript}"; | |
redhat:: | |
"check_command" string => "/sbin/chkconfig --list ${initscript} | grep -q on"; | |
"bootstart_command" string => "/sbin/chkconfig ${initscript} on"; | |
files: | |
debian:: | |
"/etc/rc2.d/S.*${initscript}.*" | |
create => "true", | |
action => WarnOnly, | |
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}"); | |
commands: | |
(SuSE|redhat):: | |
"${check_command}" | |
contain => in_shell_silent, | |
classes => if_else("service_bootstarted_${canoname}", "service_unbootstarted_${canoname}"), | |
comment => "Check if the service ${name} is started on boot"; | |
"${bootstart_command}" | |
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"), | |
ifvarclass => "service_unbootstarted_${canoname}", | |
comment => "Set the service ${name} to start on boot"; | |
debian:: | |
"/usr/sbin/update-rc.d ${initscript} remove \&\& /usr/sbin/update-rc.d ${initscript} defaults" | |
contain => in_shell, | |
classes => if_else("service_bootstarted_ok_${canoname}", "service_bootstarted_fail_${canoname}"), | |
ifvarclass => "service_unbootstarted_${canoname}", | |
comment => "Set the service ${name} to start on boot"; | |
reports: | |
cfengine:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check ${name} boot script@@None@@${g.execRun}##${g.uuid}@#${name} is started on boot as required" | |
ifvarclass => "service_bootstarted_${canoname}"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check ${name} boot script@@None@@${g.execRun}##${g.uuid}@#${name} has been set to start on boot" | |
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_ok_${canoname}"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check ${name} boot script@@None@@${g.execRun}##${g.uuid}@#Could not set ${name} to start on boot!" | |
ifvarclass => "!service_bootstarted_${canoname}.service_bootstarted_fail_${canoname}"; | |
} | |
# Pre-2.8 rotation for Apache | |
# Before the unification of the apache log directories (http://www.rudder-project.org/redmine/issues/4010) | |
# we used this directory to store apache logs. | |
/var/log/rudder/httpd/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
sharedscripts | |
postrotate | |
/etc/init.d/httpd reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/apache2/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
sharedscripts | |
postrotate | |
/etc/init.d/httpd reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/ldap/slapd.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
postrotate | |
/etc/init.d/rsyslog reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/reports/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
sharedscripts | |
postrotate | |
/etc/init.d/rsyslog reload > /dev/null | |
endscript | |
} | |
/var/log/rudder/core/*.log { | |
daily | |
missingok | |
rotate 30 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
} | |
/var/log/rudder/compliance/non-compliant-reports.log { | |
daily | |
missingok | |
rotate 365 | |
compress | |
notifempty | |
create 640 root root | |
delaycompress | |
} | |
##################################################################################### | |
# Copyright 2012 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_networks_check | |
{ | |
vars: | |
"networks" string => join("${const.n}Allow from ","def.acl"); | |
"file_path" string => "/opt/rudder/etc/rudder-networks.conf"; | |
redhat:: | |
"apache_init" string => "httpd"; | |
!redhat:: | |
"apache_init" string => "apache2"; | |
files: | |
"${file_path}" | |
create => "true", | |
perms => mog("644", "root", "root"), | |
edit_defaults => empty_backup, | |
edit_line => insert_lines("Allow from 127.0.0.0/8${const.n}Allow from ${networks}"), | |
classes => kept_if_else("rudder_networks_ok", "rudder_networks_repaired","rudder_networks_failed"), | |
comment => "Copying rudder apache configuration"; | |
commands: | |
rudder_networks_repaired:: | |
"/etc/init.d/${apache_init}" | |
args => "reload", | |
classes => if_else("apache_restarted", "apache_restart_failed"); | |
reports: | |
cfengine:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check rudder-networks.conf file@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file is OK" | |
ifvarclass => "rudder_networks_ok.!rudder_networks_repaired.!rudder_networks_failed"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check rudder-networks.conf file@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file has been corrected" | |
ifvarclass => "rudder_networks_repaired.!rudder_networks_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check rudder-networks.conf file@@None@@${g.execRun}##${g.uuid}@#The ${file_path} apache configuration file was NOT edited because of an error" | |
ifvarclass => "rudder_networks_failed"; | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Check rudder-networks.conf file@@None@@${g.execRun}##${g.uuid}@#The Apache HTTPd has been reloaded successfully" | |
ifvarclass => "apache_restarted.!apache_restart_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check rudder-networks.conf file@@None@@${g.execRun}##${g.uuid}@#The Apache HTTPd failed to restart" | |
ifvarclass => "apache_restart_failed"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Rsyslog Rudder configuration | |
# Disable Repeated message reduction or reports may be lost | |
$RepeatedMsgReduction off | |
# Provides TCP syslog reception | |
$ModLoad imtcp | |
$InputTCPServerRun &SYSLOGPORT& | |
# Provide udp for snare and compatibility with older syslog | |
$ModLoad imudp | |
$UDPServerRun &SYSLOGPORT& | |
# Load postgres module | |
$ModLoad ompgsql | |
# for Snare client | |
$EscapeControlCharactersOnReceive off | |
# Log everything | |
*.* /var/log/rudder/reports/all.log | |
# Direct to DB | |
$ActionQueueType Direct | |
$ActionQueueSaveOnShutdown on | |
# The RudderReportsFormat template specifies how to store | |
# the report in the database. | |
# nodeId : the node id | |
# ruleId : the Rule Id | |
# directiveId : the directive id | |
# eventtype : the severity | |
# policy : the policy name | |
$template RudderReportsFormat,"insert into RudderSysEvents (executionDate, nodeId, ruleId, directiveId, serial, Component, KeyValue, executionTimeStamp, eventType, msg, Policy) values ('%timereported:::date-rfc3339%','%msg:R,ERE,1,DFLT:.*##(.*)@#.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@.*@@(.*)@@.*@@.*@@.*@@.*@@[^#]*##.*--end%' , '%msg:R,ERE,1,ZERO:.*@@.*@@.*@@.*@@(.*)@@.*@@.*@@.*@@[^#]*##.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@.*@@.*@@.*@@(.*)@@.*@@.*@@[^#]*##.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@.*@@.*@@.*@@.*@@(.*)@@.*@@[^#]*##.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@.*@@.*@@.*@@.*@@.*@@(.*)@@[^#]*##.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@.*@@.*@@.*@@.*@@.*@@.*@@([^#]*)##.*--end%', '%msg:R,ERE,1,DFLT:.*@@.*@@(.*)@@.*@@.*@@.*@@.*@@.*@@[^#]*##.*--end%', '%msg:R,ERE,1,DFLT:.*@#(.*)--end%', '%msg:R,ERE,1,DFLT:.*@@(.*)@@.*@@.*--end%' )",stdsql | |
# Filtering by content | |
# Process : | |
# We first store the data in the database, then we drop it to prevent | |
# it from reaching local storage in .log files. | |
# The report format is @@Policy@@State@@RuleId@@DirectiveId@@VersionId@@Component@@Key@@ExecutionTimeStamp##NodeId@#HumanReadableMessage | |
# | |
# 1 - Send every matching report in the database... | |
:msg, ereregex, "R: @@[ a-zA-Z0-9_\-]+?@@[a-zA-Z0-9_\-]{1,64}?@@[a-zA-Z0-9\-]+@@[a-zA-Z0-9\-]+?@@[0-9]+?@@.*?@@.*?@@[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{1,2}:[0-9]{2}##[a-zA-Z0-9\-]+?@#.*" :ompgsql:localhost,rudder,rudder,${p.psql_password[2]};RudderReportsFormat | |
# 2 - Drop the remaining rudder logs to prevent local storage cluttering | |
## Syslog messages from "rudder" | |
:programname, contains, "rudder" ~ | |
## Syslog messages from "rudder" forwarded from AIX | |
:msg, ereregex, "from .*: rudder:" ~ | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Rsyslog Rudder configuration | |
# Provides TCP syslog reception | |
$ModLoad imtcp | |
$InputTCPServerRun &SYSLOGPORT& | |
# Provide udp for snare and compatibility with older syslog | |
$ModLoad imudp | |
$UDPServerRun &SYSLOGPORT& | |
# for Snare client | |
$EscapeControlCharactersOnReceive off | |
# Log everything | |
*.* /var/log/rudder/reports/all.log | |
# Direct to DB | |
$ActionQueueType Direct | |
$ActionQueueSaveOnShutdown on | |
# Filtering by content | |
# Process : | |
# We first forward the data to the root server, then we drop it to prevent | |
# it from reaching local storage in .log files. | |
# The report format is @@Policy@@State@@RuleId@@DirectiveId@@VersionId@@Component@@Key@@ExecutionTimeStamp##NodeId@#HumanReadableMessage | |
# | |
# 1 - Send every matching report to the root server | |
:msg, ereregex, "R: @@[ a-zA-Z0-9_\-]+?@@[a-zA-Z0-9_\-]{1,64}?@@[a-zA-Z0-9\-]+@@[a-zA-Z0-9\-]+?@@[0-9]+?@@.*?@@.*?@@[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}[+-][0-9]{1,2}:[0-9]{2}##[a-zA-Z0-9\-]+?@#.*" @@${server_info.cfserved}:&SYSLOGPORT& | |
# 2 - Drop the remaining rudder logs to prevent local storage cluttering | |
## Syslog messages from "rudder" | |
:programname, contains, "rudder" ~ | |
## Syslog messages from "rudder" forwarded from AIX | |
:msg, ereregex, "from .*: rudder:" ~ | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Path of the promises files on the machine | |
&CLIENTSFOLDERS;separator=":"& | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent root_integrity_check | |
{ | |
files: | |
root_server:: | |
"${g.rudder_configuration_repository}" | |
create => "true", | |
action => WarnOnly, | |
classes => if_else("rudder_integrity_ok", "rudder_integrity_failed"); | |
"${g.rudder_configuration_repository}/.git/index.lock" | |
delete => tidy, | |
file_select => rudder_common_minutes_old("5"), | |
classes => rudder_common_classes("rudder_git_lock"), | |
comment => "Delete the git locking file in the configuration-repository if older than 5 minutes"; | |
reports: | |
root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check configuration-repository folder@@None@@${g.execRun}##${g.uuid}@#The ${g.rudder_configuration_repository} directory is present" | |
ifvarclass => "rudder_integrity_ok.!rudder_integrity_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check configuration-repository folder@@None@@${g.execRun}##${g.uuid}@#EMERGENCY: THE ${g.rudder_configuration_repository} DIRECTORY IS *ABSENT*. THIS ORCHESTRATOR WILL *NOT* OPERATE CORRECTLY." | |
ifvarclass => "!rudder_integrity_ok|rudder_integrity_failed"; | |
root_server.!rudder_git_lock_repaired.!rudder_git_lock_failed:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check configuration-repository GIT lock@@None@@${g.execRun}##${g.uuid}@#The ${g.rudder_configuration_repository} GIT lock file is not present or not older than 5 minutes"; | |
root_server.rudder_git_lock_repaired.!rudder_git_lock_failed:: | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check configuration-repository GIT lock@@None@@${g.execRun}##${g.uuid}@#WARNING: THE ${g.rudder_configuration_repository} GIT LOCK FILE WAS OLDER THAN 5 MINUTES AND HAS BEEN DELETED"; | |
root_server.rudder_git_lock_failed:: | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check configuration-repository GIT lock@@None@@${g.execRun}##${g.uuid}@#TheEMERGENCY: THE ${g.rudder_configuration_repository} GIT LOCK FILE IS OLDER THAN 5 MINUTES AND COULD NOT BE DELETED. THIS ORCHESTRATOR WILL *NOT* OPERATE CORRECTLY."; | |
policy_server.!root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check configuration-repository folder@@None@@${g.execRun}##${g.uuid}@#Nothing to check about the configuration repository on relay servers"; | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check configuration-repository GIT lock@@None@@${g.execRun}##${g.uuid}@#Nothing to check about configuration repository GIT locking on relay servers"; | |
} | |
##################################################################################### | |
# Copyright 2012 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle common p | |
{ | |
vars: | |
root_server:: | |
"no" int => getfields("RUDDER_PSQL_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","psql_password"); | |
"no2" int => getfields("RUDDER_OPENLDAP_BIND_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","ldap_password"); | |
"properties_files" slist => { "${g.rudder_base}/etc/rudder-web.properties", "${g.rudder_base}/etc/inventory-web.properties" }; | |
"managed_files" slist => { "@{properties_files}", "/root/.pgpass", "${g.rudder_base}/etc/openldap/slapd.conf" }; | |
} | |
bundle agent root_password_check_disclaimer | |
{ | |
vars: | |
"disclaim" slist => { "@{p.managed_files}" }; | |
files: | |
root_server:: | |
"${disclaim}" | |
edit_line => insert_rudder_disclaimer, | |
comment => "Insert a disclaimer into Rudder"; | |
} | |
bundle agent root_password_check_file | |
{ | |
vars: | |
"pgpass[1]" string => "localhost"; | |
"pgpass[2]" string => "5432"; | |
"pgpass[3]" string => "rudder"; | |
"pgpass[4]" string => "rudder"; | |
"pgpass[5]" string => "${p.psql_password[2]}"; | |
files: | |
root_server:: | |
"${g.rudder_base}/etc/rudder-passwords.conf" | |
perms => mog("600", "root", "root"), | |
classes => kept_if_else("file_ok", "file_repaired", "file_error"); | |
"/root/.pgpass" | |
create => "true", | |
edit_line => root_password_check_file_pgpass("root_password_check_file.pgpass"); | |
reports: | |
root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check rudder-passwords.conf and pgpass files@@None@@${g.execRun}##${g.uuid}@#The Rudder passwords file is present and secure" | |
ifvarclass => "file_ok.!file_repaired.!file_error"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check rudder-passwords.conf and pgpass files@@None@@${g.execRun}##${g.uuid}@#The Rudder passwords file permissions were fixed" | |
ifvarclass => "file_repaired.!file_error"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check rudder-passwords.conf and pgpass files@@None@@${g.execRun}##${g.uuid}@#EMERGENCY: THE ${g.rudder_base}/etc/rudder-passwords.conf FILE IS *ABSENT*. THIS RUDDER SERVER WILL *NOT* OPERATE CORRECTLY." | |
ifvarclass => "file_error"; | |
policy_server.!root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check rudder-passwords.conf and pgpass files@@None@@${g.execRun}##${g.uuid}@#The Rudder passwords file does not need to be checked on relay servers. Skipping..."; | |
} | |
bundle agent root_password_check_ldap | |
{ | |
vars: | |
# Build an array using ldap configuration values | |
"rudder[ldap.authpw]" string => "${p.ldap_password[2]}"; | |
"slapd[rootpw]" string => "${p.ldap_password[2]}"; # Looks like a bug, I can not use execresult("/opt/rudder/sbin/slappasswd -s ${p.ldap_password[2]}","noshell"); | |
"prop_edit" slist => { "@{p.properties_files}" }; | |
files: | |
root_server:: | |
"${prop_edit}" | |
edit_line => set_variable_values("root_password_check_ldap.rudder"), | |
classes => kept_if_else("rudder_web_password_integrity_ok", "rudder_web_password_integrity_changed", "rudder_web_password_integrity_failed"), | |
comment => "Verifying the Rudder Webapp properties file passwords and users"; | |
"${g.rudder_base}/etc/openldap/slapd.conf" | |
edit_line => update_slapd("root_password_check_ldap.slapd"), | |
classes => kept_if_else("rudder_ldap_password_integrity_ok", "rudder_ldap_password_integrity_changed", "rudder_ldap_password_integrity_failed"), | |
comment => "Verifying the Rudder LDAP file password and user"; | |
commands: | |
rudder_ldap_password_integrity_changed:: | |
"/etc/init.d/rudder-slapd restart" | |
contain => in_shell, | |
classes => if_else("slapd_restarted", "slapd_restart_failed"); | |
reports: | |
root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check LDAP in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files are OK (checked LDAP password)" | |
ifvarclass => "rudder_web_password_integrity_ok.!rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check LDAP in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files were updated with a new LDAP password" | |
ifvarclass => "rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check LDAP in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files could not be updated to set the LDAP password" | |
ifvarclass => "rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check LDAP credentials@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file is OK (checked rootdn password)" | |
ifvarclass => "rudder_ldap_password_integrity_ok.!rudder_ldap_password_integrity_changed.!rudder_ldap_password_integrity_failed"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check LDAP credentials@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file was updated with a new rootdn password" | |
ifvarclass => "rudder_ldap_password_integrity_changed.!rudder_ldap_password_integrity_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check LDAP credentials@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file could not be updated to set the rootdn password" | |
ifvarclass => "rudder_ldap_password_integrity_failed"; | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Check rudder-passwords.conf file@@None@@${g.execRun}##${g.uuid}@#rudder-slapd has been restarted" | |
ifvarclass => "slapd_restarted"; | |
policy_server.!root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check LDAP in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files do not need to be checked on relay servers. Skipping..."; | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check LDAP credentials@@None@@${g.execRun}##${g.uuid}@#The OpenLDAP configuration file do not need to be checked on relay servers. Skipping..."; | |
} | |
bundle agent root_password_check_psql | |
{ | |
vars: | |
root_server:: | |
"no" int => getfields("RUDDER_PSQL_PASSWORD:.*","/opt/rudder/etc/rudder-passwords.conf",":","psql_pass"); | |
# Build an array using PSQL configuration values | |
"rudder[rudder.jdbc.password]" string => "${p.psql_password[2]}"; | |
classes: | |
root_server:: | |
"psql_cant_connect" not => returnszero("/usr/bin/psql --host localhost --username rudder --dbname rudder --quiet --output /dev/null --command 'select 1' 2> /dev/null","useshell"); | |
files: | |
root_server:: | |
"${g.rudder_base}/etc/rudder-web.properties" | |
edit_line => set_variable_values("root_password_check_psql.rudder"), | |
classes => kept_if_else("rudder_web_password_integrity_ok", "rudder_web_password_integrity_changed", "rudder_web_password_integrity_failed"), | |
comment => "Verifying the Rudder Webapp properties file passwords and users"; | |
commands: | |
psql_cant_connect:: | |
"/usr/bin/psql -q -c \"ALTER USER rudder WITH PASSWORD '${p.psql_password[2]}'\"" | |
contain => setuid_sh("postgres"), | |
classes => if_else("postgres_updated", "postgres_update_failed"); | |
reports: | |
root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check SQL in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files are OK (checked SQL password)" | |
ifvarclass => "rudder_web_password_integrity_ok.!rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check SQL in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files were updated with a new SQL password" | |
ifvarclass => "rudder_web_password_integrity_changed.!rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check SQL in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files could not be updated to set the SQL password" | |
ifvarclass => "rudder_web_password_integrity_failed"; | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check SQL credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password is correct and works" | |
ifvarclass => "!psql_cant_connect"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check SQL credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password has been changed" | |
ifvarclass => "postgres_updated"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check SQL credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's password could not be changed!" | |
ifvarclass => "postgres_update_failed"; | |
policy_server.!root_server:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check SQL in rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#The Rudder Webapp configuration files do not need to be checked on relay servers. Skipping..."; | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check SQL credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder PostgreSQL user account's do not need to be checked on relay servers. Skipping..."; | |
} | |
bundle agent root_password_restart_jetty | |
{ | |
commands: | |
rudder_web_password_integrity_changed:: | |
"/etc/init.d/rudder-jetty restart </dev/null >/dev/null 2>/dev/null" | |
contain => in_shell, | |
classes => if_else("jetty_restarted", "jetty_restart_failed"); | |
reports: | |
"@@DistributePolicy@@log_info@@&TRACKINGKEY&@@Check rudder-webapp.properties@@None@@${g.execRun}##${g.uuid}@#Jetty has been restarted" | |
ifvarclass => "jetty_restarted"; | |
} | |
bundle agent root_password_check_dav | |
{ | |
vars: | |
debian:: | |
"webdav_check_wwwgroup" string => "www-data"; | |
redhat:: | |
"webdav_check_wwwgroup" string => "apache"; | |
!debian.!redhat:: | |
"webdav_check_wwwgroup" string => "www"; | |
SuSE:: | |
"htpasswd_bin" string => "/usr/bin/htpasswd2"; | |
!SuSE:: | |
"htpasswd_bin" string => "/usr/bin/htpasswd"; | |
classes: | |
"dav_cant_connect" not => returnszero("/usr/bin/curl -s -f -u ${g.davuser}:${g.davpw} -T /etc/motd http://localhost/inventory-updates/motd","noshell"); | |
files: | |
"${g.rudder_base}/etc/htpasswd-webdav" | |
create => "true", | |
perms => mog("640", "root", "${webdav_check_wwwgroup}"); | |
commands: | |
dav_cant_connect:: | |
# Apache reads this file when it's changed, no need to restart or reload it after it's changed | |
"${htpasswd_bin}" | |
args => "-b ${g.rudder_base}/etc/htpasswd-webdav ${g.davuser} ${g.davpw}", | |
classes => kept_if_else("rudder_apache_davpassword_ok", "rudder_apache_davpassword_changed", "rudder_apache_davpassword_failed"), | |
comment => "Repairing the Rudder WebDAV user and password"; | |
reports: | |
cfengine:: | |
"@@DistributePolicy@@result_success@@&TRACKINGKEY&@@Check WebDAV credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password are OK" | |
ifvarclass => "!dav_cant_connect"; | |
"@@DistributePolicy@@result_repaired@@&TRACKINGKEY&@@Check WebDAV credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password were updated" | |
ifvarclass => "rudder_apache_davpassword_changed.!rudder_apache_davpassword_failed"; | |
"@@DistributePolicy@@result_error@@&TRACKINGKEY&@@Check WebDAV credentials@@None@@${g.execRun}##${g.uuid}@#The Rudder WebDAV user and password could not be updated" | |
ifvarclass => "rudder_apache_davpassword_failed"; | |
} | |
bundle edit_line update_slapd(tab) | |
{ | |
vars: | |
"index" slist => getindices("${tab}"); | |
delete_lines: | |
"${index}.*"; | |
insert_lines: | |
"${index} ${${tab}[${index}]}" location => after("^rootdn.*"); | |
} | |
bundle edit_line root_password_check_file_pgpass(parameter) | |
{ | |
vars: | |
"indices" slist => getindices(${parameter}); | |
field_edits: | |
"localhost:5432:rudder:.*" | |
# Set field of the file to parameter | |
edit_field => col(":","${indices}","${${parameter}[${indices}]}","set"); | |
insert_lines: | |
"localhost:5432:rudder:${${parameter}[4]}:${${parameter}[5]}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################ | |
# Fetch PERL and Curl | |
############################################################ | |
bundle agent fetchFusionTools | |
{ | |
packages: | |
debian:: | |
"curl" | |
package_policy => "add", | |
package_method => apt, | |
classes => rudder_common_classes("fetchFusionTools_install_curl"), | |
comment => "Installing curl using apt"; | |
redhat:: | |
"curl" | |
package_policy => "add", | |
package_method => rudder_yum, | |
classes => rudder_common_classes("fetchFusionTools_install_curl"), | |
comment => "Installing curl using yum"; | |
reports: | |
fetchFusionTools_install_curl_error:: | |
"@@Inventory@@result_error@@inventory-all@@inventory-all@@00@@tools@@None@@${g.execRun}##${g.uuid}@#Installing 'curl' failed. Inventory registration will fail if curl is unavailable"; | |
} | |
body perms myperms | |
{ | |
mode => "0700"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Definition of variables and classes usefull for all the VM part | |
# Detect the existence of installed VM containenr on the computer | |
bundle common virtualMachines | |
{ | |
vars: | |
# Files names for the installed VM lists | |
"VBoxListFile" string => "${g.rudder_var_tmp}/VBoxList.list"; | |
"VMWareListFile" string => "${g.rudder_var_tmp}/VMWareList.list"; | |
"VMWareScript_ServerLocation" string => "${g.rudder_tools}/vmware_info.sh"; | |
# Attribut name for the VM tag in the inventory file | |
"VBoxAttr" string => "VBox"; | |
"VMWareAttr" string => "VMWare"; | |
# Tools for fetching data | |
"VMWareScript" string => "${g.inventory_directory}/vmware_info.sh"; | |
&if(NOVA)& | |
windows.!cygwin:: | |
"virtual_box_install_path" string => execresult("${sys.winsysdir}\cmd.exe /c \"echo %VBOX_INSTALL_PATH%\"", "noshell"), | |
comment => "Looking for VirtualBox environment variables"; | |
&endif& | |
cygwin:: | |
"virtual_box_install_path" string => execresult("/usr/bin/echo $VBOX_INSTALL_PATH | /usr/bin/sed ''s/\\\/\//g'' ", "useshell"), | |
comment => "Looking for VirtualBox environment variables"; | |
classes: | |
!windows:: | |
"VirtualBoxInstalled" expression => fileexists("/usr/bin/VBoxManage"), | |
comment => "Checking installation of VirtualBox"; | |
"VMWareInstalled" expression => fileexists("/usr/bin/wmrun"), | |
comment => "Checking installation of VMWare"; | |
&if(NOVA)& | |
windows:: | |
"VirtualBoxInstalled" not => regcmp("", "${virtual_box_install_path}"); | |
&endif& | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# This file launch a fusion-inventory agent | |
# inventory in local. | |
# If fusion agent is not installed, | |
# the installation is done | |
# | |
# Then the inventory file is improved with external informations (UUID, cf-key, VMs) | |
bundle agent doInventory | |
{ | |
vars: | |
# If curl is available, use it | |
!windows.curl_installed:: | |
"download_command" string => "${g.rudder_curl} -s -f --proxy '' -o \"${g.rudder_var_tmp}/uuid.txt\" http://${server_info.cfserved}/uuid"; | |
# If not, use minicurl instead | |
!windows.!curl_installed:: | |
"download_command" string => "${g.minicurl} --get --file \"${g.rudder_var_tmp}/uuid.txt\" --url http://${server_info.cfserved}/uuid"; | |
&if(NOVA)& | |
# On windows, always use curl | |
windows:: | |
"download_command" string => "\"${g.rudder_base_sbin}\curl\curl.exe\" -s -f --noproxy '${server_info.cfserved}' -o \"${g.rudder_var_tmp}\uuid.txt\" http://${server_info.cfserved}/uuid"; | |
&endif& | |
uuid_succesfully_downloaded:: | |
"policy_server_uuid" string => readfile("${g.rudder_var_tmp}/uuid.txt", 50); | |
classes: | |
"splaying" expression => splayclass("${sys.host}${sys.ipv4}","hourly"); | |
# The force_inventory class may be specified by the user at runtime, or defined here | |
"force_inventory" expression => fileexists("${g.rudder_base}/etc/force_inventory"); | |
uuid_succesfully_downloaded:: | |
"uuid_valid" expression => regcmp("[a-z0-9-]+","${policy_server_uuid}"); | |
"uuid_validity_checked" | |
expression => "any", | |
comment => "This dummy class is just used for ordering the report using !uuid_valid below"; | |
methods: | |
uuid_valid.force_inventory:: | |
"any" usebundle => fusionAgent; | |
"any" usebundle => listInstalledVM; | |
"any" usebundle => generateExtraInformations; | |
"any" usebundle => turnUsersToUnicode; | |
"any" usebundle => addInformationsToInventory; | |
"any" usebundle => moveInventoryToFinalDestination; | |
"any" usebundle => sendInventory; | |
"any" usebundle => cleanForceInventoryFlagFile; | |
# Workaround the wrong class expansion | |
uuid_valid.Night.splaying.!inventory_sent:: | |
"any" usebundle => fusionAgent; | |
"any" usebundle => listInstalledVM; | |
"any" usebundle => generateExtraInformations; | |
"any" usebundle => turnUsersToUnicode; | |
"any" usebundle => addInformationsToInventory; | |
"any" usebundle => moveInventoryToFinalDestination; | |
"any" usebundle => sendInventory; | |
commands: | |
"${download_command}" | |
comment => "Getting the uuid from the server", | |
classes => if_else("uuid_succesfully_downloaded","could_not_download_uuid"); | |
reports: | |
could_not_download_uuid:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not retrieve the UUID of the policy server"; | |
uuid_succesfully_downloaded.uuid_validity_checked.!uuid_valid:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not retrieve a valid UUID from the policy server"; | |
# Send reports to confirm this PT's success even if we don't need to send an inventory | |
inventory_sent:: | |
"@@Inventory@@log_info@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#An inventory was already sent less than 8 hours ago"; | |
!(Night.splaying).!force_inventory:: | |
"@@Inventory@@result_success@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Next inventory scheduled between 00:00 and 06:00"; | |
} | |
bundle common inventory | |
{ | |
vars: | |
&if(NOVA)& | |
windows:: | |
# Files names | |
"UserListFile_cp" string => "\"${g.rudder_var_tmp}\UserList.tmp\""; | |
"UserListFile" string => "\"${g.rudder_var_tmp}\UserList.list\""; | |
"cpuid_tool" string => "\"${g.rudder_tools}\cpuid-windows-V1.0.vbs\""; | |
&endif& | |
android:: | |
"cpuid_tool" string => "${g.rudder_tools}/cpuid-android-V1.0.sh"; | |
!aix.!windows.!android:: | |
"cpuid_tool" string => "${g.rudder_tools}/cpuid-linux-V1.0.sh"; | |
any:: | |
"CPUIDFile" string => "${g.rudder_var_tmp}/cpuid.arc"; | |
classes: | |
windows:: | |
"rudder_inventory_userlist_tool_present" expression => fileexists("${g.rudder_tools}\userlist.bat"); | |
any:: | |
"rudder_inventory_cpuid_tool_present" expression => fileexists("${cpuid_tool}"); | |
} | |
bundle agent fusionAgent | |
{ | |
vars: | |
SuSE.xen_dom0:: | |
"xen_tools_package" string => "xen-tools"; | |
SuSE.xen_domu_pv:: | |
"xen_tools_package" string => "xen-tools-domU"; | |
debian:: | |
"xen_tools_package" string => "xenstore-utils"; | |
!debian.!SuSE:: | |
"xen_tools_package" string => "xen"; | |
files: | |
!windows|cygwin:: | |
"${g.rudder_var_tmp}/inventory/." | |
create => "true", | |
comment => "Creating inventory directory", | |
classes => if_ok("inventoryfoldercreated"); | |
"${g.rudder_var_reports}/." | |
create => "true"; | |
&if(NOVA)& | |
windows.!cygwin:: | |
"${g.rudder_var_tmp}\inventory\." | |
create => "true", | |
comment => "Creating inventory directory", | |
classes => if_ok("inventoryfoldercreated"); | |
"${g.rudder_var_reports}\." | |
create => "true"; | |
&endif& | |
packages: | |
xen.!redhat:: | |
"${xen_tools_package}" | |
package_policy => "add", | |
package_method => generic, | |
classes => cf2_if_else("xen_installed", "cant_install_xen"), | |
comment => "Installing xen package for extended data"; | |
xen.redhat:: | |
"${xen_tools_package}" | |
package_policy => "add", | |
package_method => rudder_yum, | |
classes => cf2_if_else("xen_installed", "cant_install_xen"), | |
comment => "Installing xen package for extended data"; | |
commands: | |
!windows.inventoryfoldercreated:: | |
"${g.rudder_base}/bin/run-inventory --local=${g.rudder_var_tmp}/inventory --scan-homedirs" | |
classes => cf2_if_else("run_inventory", "inventory_failed"), | |
comment => "Generating inventory, in the temporary folder"; | |
&if(NOVA)& | |
windows:: | |
"\"C:\Program Files\Rudder\sbin\run-inventory.bat\"" | |
args => "--local=\"${g.rudder_var_tmp}\inventory\" --scan-homedirs 2>nul", | |
contain => in_shell, | |
classes => cf2_if_else("run_inventory", "inventory_failed"), | |
comment => "Generating inventory"; | |
&endif& | |
reports: | |
run_inventory:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Running inventory"; | |
inventory_failed:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not execute the inventory"; | |
cant_install_curl:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install curl"; | |
cant_install_ocs:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install ocs"; | |
cant_install_xen:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not install xen utils on xen systems"; | |
xen_installed:: | |
"@@Inventory@@log_info@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Xen utils installed"; | |
curl_installed:: | |
"@@Inventory@@log_info@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Curl installed"; | |
} | |
# List all installed VM on the machine (based on VirtualBox) | |
# CAUTION : Issue with path containing a whitespace, it's not working with windows | |
bundle agent listInstalledVM | |
{ | |
files: | |
VirtualBoxInstalled:: | |
"${virtualMachines.VBoxListFile}" | |
create => "true", | |
edit_line => xmlify(${virtualMachines.VBoxAttr}), | |
comment => "Converting file into pseudo XML"; | |
VMWareInstalled:: | |
"${virtualMachines.VMWareListFile}" | |
create => "true", | |
edit_line => xmlify(${virtualMachines.VMWareAttr}), | |
comment => "Converting file into pseudo XML"; | |
commands: | |
!windows.VirtualBoxInstalled:: | |
"/usr/bin/VBoxManage" | |
args => "-q list vms > ${virtualMachines.VBoxListFile}", | |
contain => outputable, | |
classes => cf2_if_else("vb_listed", "cant_list_vb"), | |
comment => "Generating file with list of VM"; | |
&if(NOVA)& | |
windows.VirtualBoxInstalled:: | |
"\"${virtualMachines.virtual_box_install_path}VBoxManage.exe\"" | |
args => "-q list vms > ${virtualMachines.VBoxListFile}", | |
contain => outputable, | |
classes => cf2_if_else("vb_listed", "cant_list_vb"), | |
comment => "Generating file with list of VM"; | |
&endif& | |
!windows.VMWareInstalled:: | |
"${virtualMachines.VMWareScript}" | |
contain => outputable, | |
args => " > ${virtualMachines.VMWareListFile}", | |
classes => cf2_if_else("vm_listed", "cant_list_vm"), | |
comment => "Generating file with list of VM"; | |
&if(NOVA)& | |
windows.VMWareInstalled:: | |
"${virtualMachines.VMWareScript}" | |
contain => outputable, | |
args => " > ${virtualMachines.VMWareListFile}", | |
classes => cf2_if_else("vm_listed", "cant_list_vm"), | |
comment => "Generating file with list of VM"; | |
&endif& | |
reports: | |
cant_list_vm:: | |
"@@Inventory@@log_warn@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not list installed VMWare machines"; | |
cant_list_vb:: | |
"@@Inventory@@log_warn@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not list installed VirtualBox machines"; | |
} | |
bundle agent generateExtraInformations | |
{ | |
commands: | |
&if(NOVA)& | |
windows.rudder_inventory_userlist_tool_present:: | |
"\"${g.rudder_tools}\userlist.bat\"" | |
args => " > ${inventory.UserListFile_cp} ", | |
contain => outputable, | |
classes => cf2_if_else("userlist", "userlist_fail"), | |
comment => "Generating file with list of users"; | |
windows.rudder_inventory_cpuid_tool_present:: | |
"${sys.winsysdir}\cscript.exe" | |
args => "/Nologo \"${g.rudder_tools}/cpuid-windows-V1.0.vbs\" > \"${inventory.CPUIDFile}\"", | |
contain => outputable, | |
classes => cf2_if_else("cpuid", "cpuid_fail"), | |
comment => "Generating file with CPUID information"; | |
&endif& | |
!windows.rudder_inventory_cpuid_tool_present:: | |
"${inventory.cpuid_tool}" | |
args => " > ${inventory.CPUIDFile}", | |
contain => outputable, | |
classes => cf2_if_else("cpuid", "cpuid_fail"), | |
comment => "Generating file with CPUID information"; | |
reports: | |
userlist:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Generated the userlist"; | |
cpuid:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Generated the CPUID"; | |
userlist_fail:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not generate the user list"; | |
cpuid_fail:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not generate the cpuid"; | |
!rudder_inventory_userlist_tool_present:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#The user list generation tool is not present yet. Skipping..."; | |
!rudder_inventory_cpuid_tool_present:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#The CPUID generation tool is not present yet. Skipping..."; | |
} | |
bundle agent turnUsersToUnicode | |
{ | |
&if(NOVA)& | |
commands: | |
windows:: | |
"\"${g.rudder_tools}\iconv.exe\"" | |
args => " -f CP850 -t UTF-8 ${inventory.UserListFile_cp} > ${inventory.UserListFile} ", | |
contain => outputable_dir("${g.rudder_tools}"), | |
classes => cf2_if_else("userlist", "userlist_fail"), | |
comment => "Generating file with list of users in UTF"; | |
&endif& | |
reports: | |
windows:: | |
"@@Inventory@@log_debug@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#This is a windows machine. User list has been converted to Unicode"; | |
} | |
# adding data to the inventory : | |
# UUID and CFKey in <DEVICEID>, | |
# list of VM in <CONTENT> | |
bundle agent addInformationsToInventory | |
{ | |
vars: | |
&if(NOVA)& | |
windows.!cygwin:: | |
"CFKEY_cmd" string => "${sys.winsysdir}\cmd.exe /c \"type \"${sys.workdir}\ppkeys\localhost.pub\"\""; | |
"USER" string => getenv("USERNAME", 40); | |
"RUDDERUUID_cmd" string => "${sys.winsysdir}\cscript.exe /Nologo \"${g.rudder_tools}/uuid.vbs\""; | |
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}\uuid.txt" , "50" ); | |
# Somehow, using the variable rather than the path fails with readstringlist | |
"users" slist => { readstringlist("C:\Program Files\Rudder\var\tmp\UserList.list","#.*","[\n| |\r]",50,4000) }; | |
&endif& | |
cygwin:: | |
"mywinpath" string => execresult("/usr/bin/echo $WINDIR ", "useshell"); | |
"CFKEY_cmd" string => "/usr/bin/cat ${sys.workdir}/ppkeys/localhost.pub"; | |
"USER_cmd" string => "/usr/bin/whoami"; | |
"RUDDERUUID_cmd" string => "${sys.winsysdir}\cscript.exe /Nologo ${g.rudder_tools}/uuid.vbs"; | |
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}/uuid.txt" , "50" ); | |
"users" slist => { readstringlist("${inventory.UserListFile}","#.*","[\n| |\r]",10,4000) }; | |
xen.SuSE.xen_domu_pv:: | |
"VMRUDDERUUID_cmd" string => "/bin/xenstore-read vm"; | |
xen.(centos|redhat|(SuSE.xen_dom0)):: | |
"VMRUDDERUUID_cmd" string => "/usr/bin/xenstore-read vm"; | |
xen.(!SuSE.!centos.!redhat):: | |
"VMRUDDERUUID_cmd" string => "/usr/sbin/xenstore-read vm"; | |
xen:: | |
"VMRUDDERUUID" string => execresult("${VMRUDDERUUID_cmd}", "noshell"); | |
xen.xenrudderuuid:: | |
"RUDDERUUID" string => "${vmarray[1]}"; | |
!windows:: | |
"polserv_uuid" string => readfile( "${g.rudder_var_tmp}/uuid.txt" , "50" ); | |
android:: | |
"RUDDERUUID_cmd" string => "/system/xbin/sqlite3 /data/data/com.android.providers.settings/databases/settings.db \"select value from secure where name = 'android_id'\""; | |
"CFKEY_cmd" string => "/system/bin/cat ${sys.workdir}/ppkeys/localhost.pub"; | |
"USER_cmd" string => "/system/xbin/whoami"; | |
"usersnumber" int => "1"; | |
"users" slist => {"root"}; | |
"android_kernelname" string => "linux"; | |
"android_kernelversion" string => execresult("/system/xbin/uname -r", "noshell"); | |
"android_name" string => "Android"; | |
"android_version" string => execresult("/system/bin/getprop ro.build.version.release", "noshell"); | |
"android_fullname" string => "Android ${android_version}"; | |
"logdate" string => execresult("/system/bin/date '+%Y-%m-%d %H:%M:%S'", "noshell"); | |
linux.!xen:: | |
"RUDDERUUID_cmd" string => "/usr/sbin/dmidecode -s system-uuid"; | |
aix:: | |
"RUDDERUUID_cmd" string => "/usr/bin/uname -f"; | |
!windows.!android:: | |
"CFKEY_cmd" string => "/bin/cat ${sys.workdir}/ppkeys/localhost.pub"; | |
"USER_cmd" string => "/usr/bin/whoami"; | |
"usersnumber" int => readstringarray("userslist","/etc/passwd","#[^\n]*",":",50,16000); | |
"users" slist => getindices("userslist"); | |
any:: | |
"CFKEY" string => execresult("${CFKEY_cmd}", "noshell"); | |
"USER" string => execresult("${USER_cmd}", "noshell"); | |
!xen:: | |
"RUDDERUUID" string => execresult("${RUDDERUUID_cmd}", "noshell"); | |
classes: | |
xen:: | |
"xenrudderuuid" expression => regextract("/vm/(.*)", "${VMRUDDERUUID}", "vmarray"); | |
any:: | |
"uuiddefined" expression => isvariable("RUDDERUUID"); | |
files: | |
&if(NOVA)& | |
windows:: | |
"C:/Progra~1/Rudder/var/tmp/inventory/.*.ocs" | |
edit_line => add_information_to_inventory(${RUDDERUUID}, ${CFKEY}, ${USER}, ${polserv_uuid}), | |
edit_defaults => def_no_backup; | |
"C:/Progra~1/Rudder/var/tmp/inventory/.*.ocs" | |
edit_line => add_users_information_to_inventory(@{addInformationsToInventory.users}), | |
edit_defaults => def_no_backup; | |
&endif& | |
!windows.uuiddefined:: | |
"${g.rudder_var_tmp}/inventory/.*.ocs" | |
edit_line => add_information_to_inventory(${RUDDERUUID}, ${CFKEY}, ${USER}, ${polserv_uuid}), | |
edit_defaults => def_no_backup; | |
"${g.rudder_var_tmp}/inventory/.*.ocs" | |
edit_line => add_users_information_to_inventory(@{addInformationsToInventory.users}), | |
edit_defaults => def_no_backup; | |
android:: | |
"${g.rudder_var_tmp}/inventory/.*.ocs" | |
edit_line => add_information_to_android_inventory(${android_fullname}, ${android_kernelname}, ${android_kernelversion}, ${android_name}, ${android_version}), | |
edit_defaults => def_no_backup; | |
"${g.rudder_var_tmp}/inventory/.*.ocs" | |
edit_line => add_accesslog_to_android_inventory(${logdate}), | |
edit_defaults => def_no_backup; | |
} | |
# Move the inventory file in the shared directory | |
bundle agent moveInventoryToFinalDestination | |
{ | |
files: | |
"${g.rudder_inventories}" | |
copy_from => copy("${g.rudder_var_tmp}/inventory"), | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
comment => "Moving inventory files to the final location"; | |
} | |
# Send the file to the promises server | |
bundle agent sendInventory | |
{ | |
vars: | |
"download_endpoint" string => "http://${server_info.cfserved}/inventory-updates/"; | |
# If curl is available, use it | |
!windows.curl_installed:: | |
"download_command_prefix" string => "${g.rudder_curl} -f -s --proxy '' --user ${g.davuser}:${g.davpw} -T"; | |
"download_command_suffix" string => "${download_endpoint}"; | |
# If not, use minicurl instead | |
!windows.!curl_installed:: | |
"download_command_prefix" string => "${g.minicurl} --put --authentication ${g.davuser}:${g.davpw} --file"; | |
"download_command_suffix" string => "--url ${download_endpoint}"; | |
&if(NOVA)& | |
# On windows, always use curl | |
windows:: | |
"download_command_prefix" string => "${g.rudder_curl} -f -s --noproxy '${server_info.cfserved}' --user ${g.davuser}:${g.davpw} -T"; | |
"download_command_suffix" string => "${download_endpoint}"; | |
&endif& | |
files: | |
!windows:: | |
"${g.rudder_inventories}" | |
transformer => "${download_command_prefix} ${this.promiser} ${download_command_suffix}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => persistant_class("inventory_sent", "cant_send_inventory", 480), | |
comment => "Sending the inventory to the server"; | |
&if(NOVA)& | |
# On windows, the this.promiser variable is not evaluated the same way. We are forced to duplicate this block | |
windows:: | |
"${g.rudder_inventories}" | |
transformer => "${download_command_prefix} \"${this.promiser}\" ${download_command_suffix}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => persistant_class("inventory_sent", "cant_send_inventory", 480), | |
comment => "Sending the inventory to the server"; | |
&endif& | |
# Once we've successfully sent all inventories, remove them | |
!windows.inventory_sent.!cant_send_inventory:: | |
"${g.rudder_inventories}" | |
transformer => "${g.rudder_rm} -f ${this.promiser}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => if_else("inventory_file_deleted", "cant_delete_inventory_file"), | |
comment => "Cleaning up inventory files already sent to the server"; | |
"${g.rudder_var_tmp}/inventory" | |
transformer => "${g.rudder_rm} -f ${this.promiser}", | |
depth_search => recurse_visible(1), | |
file_select => inventory_files, | |
classes => if_else("inventory_file_deleted", "cant_delete_inventory_file"), | |
comment => "Cleaning up inventory files already sent to the server"; | |
reports: | |
inventory_sent:: | |
"@@Inventory@@result_success@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#The inventory has been successfully sent"; | |
cant_send_inventory:: | |
"@@Inventory@@result_error@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not send the inventory"; | |
cant_delete_inventory_file:: | |
"@@Inventory@@log_warn@@&TRACKINGKEY&@@inventory@@None@@${g.execRun}##${g.uuid}@#Could not delete inventory file after sending to server"; | |
} | |
##################################################### | |
#Adding the list of Virtual Machines into the report | |
#Adding the ids in the report | |
##################################################### | |
bundle edit_line add_information_to_inventory(RUDDERUUID, CFKEY, USER, POLSRVUUID) | |
{ | |
insert_lines: | |
"<UUID>${g.uuid}</UUID>${const.n}<USER>${USER}</USER>${const.n}<AGENTSNAME>${const.n}</AGENTSNAME>${const.n}<MACHINEID>${RUDDERUUID}</MACHINEID>${const.n}<CFKEY>${CFKEY}</CFKEY>${const.n}<HOSTNAME>${sys.fqhost}</HOSTNAME>${const.n}<POLICY_SERVER>${POLSRVUUID}</POLICY_SERVER>${const.n}" | |
location => after_deviceid, | |
insert_type => "preserve_block", | |
comment => "Add the UUID and CFKEY tags in the inventory file"; | |
any:: | |
"<VMS>${const.n}</VMS>${const.n}<USERSLIST>${const.n}</USERSLIST>" | |
insert_type => "preserve_block", | |
location => after_content; | |
rudder_inventory_cpuid_tool_present:: | |
"${inventory.CPUIDFile}" | |
insert_type => "file", | |
location => after_location("<HOSTNAME>"), | |
comment => "Adding the CPUID data in the inventory file"; | |
nova_edition:: | |
"<AGENTNAME>Nova</AGENTNAME>" | |
location => after_location("<AGENTSNAME>"), | |
comment => "Adding the agent data in the inventory file"; | |
community_edition:: | |
"<AGENTNAME>Community</AGENTNAME>" | |
location => after_location("<AGENTSNAME>"), | |
comment => "Adding the agent data in the inventory file"; | |
VirtualBoxInstalled:: | |
"${virtualMachines.VBoxListFile}" | |
insert_type => "file", | |
location => after_location("<VMS>"), | |
comment => "Adding the list of VM in the inventory file"; | |
VMWareInstalled:: | |
"${virtualMachines.VMWareListFile}" | |
insert_type => "file", | |
location => after_vm, | |
comment => "Adding the list of VM in the inventory file"; | |
} | |
bundle edit_line add_information_to_android_inventory(fullname, kernelname, kernelversion, name, version) | |
{ | |
insert_lines: | |
android:: | |
"<OPERATINGSYSTEM>${const.n}<FULL_NAME>${fullname}</FULL_NAME>${const.n}<KERNEL_NAME>${kernelname}</KERNEL_NAME>${const.n}<KERNEL_VERSION>${kernelversion}</KERNEL_VERSION>${const.n}<NAME>${name}</NAME>${const.n}<VERSION>${version}</VERSION>${const.n}</OPERATINGSYSTEM>" | |
location => after_location("<CONTENT>"), | |
insert_type => "preserve_block", | |
comment => "Adding the list of OPERATINGSYSTEM part"; | |
} | |
#this bundle is necessary for OCSInventory (but not for fusioninventory) | |
bundle edit_line add_accesslog_to_android_inventory(logdate) | |
{ | |
insert_lines: | |
android:: | |
"<ACCESSLOG><LOGDATE>${logdate}</LOGDATE></ACCESSLOG>" | |
location => after_location("</OPERATINGSYSTEM>"), | |
comment => "Adding log date"; | |
} | |
bundle edit_line add_users_information_to_inventory(userlist) | |
{ | |
insert_lines: | |
(windows.rudder_inventory_userlist_tool_present)|!windows:: | |
"<USER>${userlist}</USER>${const.n}" location => after_users, | |
comment => "Add the UUID and CFKEY tags in the inventory file"; | |
} | |
#Locators | |
body location after_location(pos) | |
{ | |
select_line_matching => ".*${pos}.*"; | |
before_after => "after"; | |
} | |
body location after_deviceid | |
{ | |
select_line_matching => ".*<DEVICEID>.*"; | |
before_after => "after"; | |
} | |
body location after_content | |
{ | |
select_line_matching => ".*<CONTENT>.*"; | |
before_after => "after"; | |
} | |
body location after_vm | |
{ | |
select_line_matching => ".*<VMS>.*"; | |
before_after => "after"; | |
} | |
body location after_users | |
{ | |
select_line_matching => ".*<USERSLIST>.*"; | |
before_after => "after"; | |
} | |
############### | |
# Editors | |
############## | |
# Convert a simple list in <VM TYPe="vmtype"><NAME>machine_name</NAME><UUID>value<UUID></VM> | |
bundle edit_line xmlify(ATTR) | |
{ | |
replace_patterns: | |
"\"(.*)\" \{(.*)\}" | |
replace_with=> xmled(${ATTR}); | |
} | |
body replace_with xmled(attribute) | |
{ | |
replace_value => "<VM TYPE=\"${attribute}\"><NAME>${match.1}</NAME><UUID>${match.2}</UUID></VM>"; | |
} | |
# select the inventory files that has the right extension | |
#I'd like to select also those older than 4 hours (ctime => irange(ago(0,0,0,4,0,0),now);) not working... | |
# (for some reason, ocs duplicated files over time) | |
body file_select inventory_files | |
{ | |
any:: | |
leaf_name => { ".*.ocs" }; | |
file_result => "leaf_name"; | |
&if(NOVA)& | |
#windows:: | |
# leaf_name => { ".*.xml" }; | |
# file_result => "leaf_name"; | |
&endif& | |
} | |
body perms inventory_perms | |
{ | |
mode => "0700"; | |
} | |
body file_select one_day_age | |
# | |
# we can build old "include", "exclude", and "ignore" | |
# from these as standard patterns - these bodies can | |
# form a library of standard patterns | |
# | |
{ | |
mtime => irange(ago(1,0,0,0,0,0),ago(0,0,1,0,0,0)); | |
file_result => "mtime"; | |
} | |
bundle agent cleanForceInventoryFlagFile | |
{ | |
files: | |
"${g.rudder_base}/etc/force_inventory" | |
delete => tidy, | |
ifvarclass => "inventory_sent"; # if the force inventory file was present, and we successfully sent an inventory, clean up the flag file | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
###################################################### | |
# Configure the ntp | |
# If ntp is not installed, install it (linux) | |
# Change the server configuration, and restart the daemon | |
# if the configuration changed | |
# Caution : a missing feature in cfe prevents from adding ,0x1 at the end of the domain name | |
# so it's only safe to use with ips for now | |
bundle agent check_clock_configuration | |
{ | |
vars: | |
"ntpServers" slist => {&CLOCK_NTPSERVERS: { "&it&"};separator=", "&}; | |
windows:: | |
# For windows, we must extract both ip and domain name values | |
#"ipv4" slist => grep("(?:\\d{1,3}\.){3}\\d{1,3}","ntpServers"); | |
#domain slist => not one of the above | |
# check that list aren't empty using reglist | |
&if(CLOCK_FQDNNTP)& | |
"keytemp" string => join("\,0x1 ", ntpServers); | |
"serverskey" string => "${keytemp}\,0x1"; | |
&else& | |
"serverskey" string => join(" ", ntpServers); | |
&endif& | |
"current_timezone" string => execresult("\"${sys.winsysdir}\tzutil.exe\" /g", "useshell"); | |
clock_set_france:: | |
"linux_timezone" string => "Europe/Paris"; | |
"windows_timezone" string => "Romance Standard Time"; | |
clock_set_uk:: | |
"linux_timezone" string => "Europe/London"; | |
"windows_timezone" string => "GMT Standard Time"; | |
clock_set_germany:: | |
"linux_timezone" string => "Europe/Berlin"; | |
"windows_timezone" string => "W. Europe Standard Time"; | |
clock_set_spain:: | |
"linux_timezone" string => "Europe/Madrid"; | |
"windows_timezone" string => "Romance Standard Time"; | |
clock_set_italy:: | |
"linux_timezone" string => "Europe/Rome"; | |
"windows_timezone" string => "W. Europe Standard Time"; | |
clock_set_us_pacific:: | |
"linux_timezone" string => "US/Pacific"; | |
"windows_timezone" string => "Pacific Standard Time"; | |
clock_set_us_mountain:: | |
"linux_timezone" string => "US/Mountain"; | |
"windows_timezone" string => "Mountain Standard Time"; | |
clock_set_us_central:: | |
"linux_timezone" string => "US/Central"; | |
"windows_timezone" string => "Central Standard Time"; | |
clock_set_eastern:: | |
"linux_timezone" string => "US/Eastern"; | |
"windows_timezone" string => "Eastern Standard Time"; | |
clock_set_canada:: | |
"linux_timezone" string => "America/Canada"; | |
"windows_timezone" string => "Atlantic Standard Time"; | |
clock_set_belgium:: | |
"linux_timezone" string => "Europe/Brussels"; | |
"windows_timezone" string => "Romance Standard Time"; | |
clock_set_luxembourg:: | |
"linux_timezone" string => "Europe/Luxembourg"; | |
"windows_timezone" string => "Romance Standard Time"; | |
clock_set_netherlands:: | |
"linux_timezone" string => "Europe/Amsterdam"; | |
"windows_timezone" string => "W. Europe Standard Time"; | |
clock_set_norway:: | |
"linux_timezone" string => "Europe/Oslo"; | |
"windows_timezone" string => "Romance Standard Time"; | |
clock_set_beijing:: | |
"linux_timezone" string => "Europe/Paris"; | |
"windows_timezone" string => "China Standard Time"; | |
classes: | |
"clock_vardef" expression => isvariable("linux_timezone"); | |
"clock_timezone_noedit" expression => strcmp("&CLOCK_TIMEZONE&","dontchange"); | |
"clock_set_france" expression => strcmp("&CLOCK_TIMEZONE&","france"); | |
"clock_set_uk" expression => strcmp("&CLOCK_TIMEZONE&","uk"); | |
"clock_set_germany" expression => strcmp("&CLOCK_TIMEZONE&","germany"); | |
"clock_set_spain" expression => strcmp("&CLOCK_TIMEZONE&","spain"); | |
"clock_set_italy" expression => strcmp("&CLOCK_TIMEZONE&","italy"); | |
"clock_set_us_pacific" expression => strcmp("&CLOCK_TIMEZONE&","us-pacific"); | |
"clock_set_us_mountain" expression => strcmp("&CLOCK_TIMEZONE&","us-mountain"); | |
"clock_set_us_central" expression => strcmp("&CLOCK_TIMEZONE&","us-central"); | |
"clock_set_us_eastern" expression => strcmp("&CLOCK_TIMEZONE&","us-eastern"); | |
"clock_set_canada" expression => strcmp("&CLOCK_TIMEZONE&","canada"); | |
"clock_set_belgium" expression => strcmp("&CLOCK_TIMEZONE&","belgium"); | |
"clock_set_luxembourg" expression => strcmp("&CLOCK_TIMEZONE&","luxembourg"); | |
"clock_set_netherlands" expression => strcmp("&CLOCK_TIMEZONE&","netherlands"); | |
"clock_set_norway" expression => strcmp("&CLOCK_TIMEZONE&","norway"); | |
"clock_set_beijing" expression => strcmp("&CLOCK_TIMEZONE&","beijing"); | |
"ntp_config_file_exists" expression => fileexists("/etc/ntp.conf"); | |
clock_vardef.windows:: | |
# check if we need to change the windows timezone | |
"need_to_change_timezone" not => strcmp("${windows_timezone}", "${current_timezone}"); | |
files: | |
# Adjust ntp.conf (Add the servers) | |
!windows.(ntp_config_file_exists|ntp_installed):: | |
"/etc/ntp.conf" | |
edit_line => setNtpServer("@{this.ntpServers}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("ntpconf_kept", "repaired_ntpconf", "not_repaired_ntpconf"); | |
# Copy the correct localtime file (distro independant) | |
!clock_timezone_noedit.!windows.clock_vardef:: | |
"/etc/localtime" | |
copy_from => digest_cp("/usr/share/zoneinfo/${linux_timezone}"), | |
comment => "Updating the /etc/localtime file", | |
classes => kept_if_else("localtime_kept", "repaired_localtime", "not_repaired_localtime"); | |
# Edit the distro dependant files to set the TZ on boot | |
(redhat.!clock_timezone_noedit).clock_vardef:: | |
"/etc/sysconfig/clock" | |
edit_line => EditCentOSTimezone("${linux_timezone}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("redhattz_kept", "repaired_redhattz", "not_repaired_redhattz"); | |
(SuSE.!clock_timezone_noedit).clock_vardef:: | |
"/etc/sysconfig/clock" | |
edit_line => EditSuSETimezone("${linux_timezone}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("susetz_kept", "repaired_susetz", "not_repaired_susetz"); | |
(debian.!clock_timezone_noedit).clock_vardef:: | |
"/etc/timezone" | |
edit_defaults => empty_backup, | |
edit_line => EditDebianTimezone("${linux_timezone}"), | |
classes => kept_if_else("debiantz_kept", "repaired_debiantz", "not_repaired_debiantz"); | |
# Install the NTP package | |
packages: | |
linux.!SuSE_10.!SuSE_11:: | |
"ntp" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("ntp_install_kept", "ntp_installed", "cant_install_ntp"), | |
comment => "Installing ntp"; | |
SuSE_11:: | |
"ntp" | |
package_policy => "add", | |
package_method => zypper, | |
classes => kept_if_else("ntp_install_kept", "ntp_installed", "cant_install_ntp"), | |
comment => "Installing ntp using zypper"; | |
SuSE_10:: | |
"xntp" | |
package_policy => "add", | |
package_method => rudder_rug, | |
classes => kept_if_else("ntp_install_kept", "ntp_installed", "cant_install_ntp"), | |
comment => "Installing xntp using rug"; | |
processes: | |
# If NTP is down, define its restart class | |
"ntpd" | |
restart_class => "ntpd_down"; | |
commands: | |
# Restart commands | |
!windows.!redhat.(repaired_ntpconf|repaired_localtime|repaired_debiantz|repaired_susetz|ntpd_down):: | |
"/etc/init.d/ntp" | |
args => "restart", | |
classes => cf2_if_else("ntp_restarted", "cant_restart_ntp"), | |
comment => "restarting ntp"; | |
redhat.(repaired_ntpconf|repaired_localtime|repaired_redhattz|ntpd_down):: | |
"/etc/init.d/ntpd" | |
args => "restart", | |
classes => cf2_if_else("ntp_restarted", "cant_restart_ntp"), | |
comment => "restarting ntp"; | |
(windows.!clock_timezone_noedit).clock_vardef.need_to_change_timezone:: | |
"\"${sys.winsysdir}\tzutil.exe\"" | |
args => "/s \"${windows_timezone}\"", | |
contain => in_shell, | |
classes => rudder_common_classes("timezone_change"), | |
comment => "set the windows time zone"; | |
(windows.!clock_timezone_noedit).ntp_regset:: | |
"\"${sys.winsysdir}\net.exe\"" | |
args => "stop W32Time", | |
contain => in_shell, | |
classes => cf2_if_else("ntp_winsvcstop", "ntp_winsvcstop"), | |
comment => "Restart the windows NTP service"; | |
(windows.!clock_timezone_noedit).ntp_winsvcstop:: | |
"\"${sys.winsysdir}\net.exe\"" | |
args => "start W32Time", | |
contain => in_shell, | |
classes => cf2_if_else("ntp_win32time_started", "ntp_win32time_error"), | |
comment => "Restart the windows NTP service"; | |
# HW clock sync command | |
!windows:: | |
"/sbin/hwclock" | |
args => "--systohc", | |
action => if_elapsed("&CLOCK_SYNCSCHED&"), | |
classes => cf2_if_else("ntp_hwclock_synced", "ntp_hwclock_sync_error"), | |
comment => "synchronizing hardware clock"; | |
&if(NOVA)& | |
databases: | |
windows:: | |
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters" | |
database_operation => "create", | |
database_rows => { "Type,REG_SZ,NTP", "NtpServer,REG_SZ,${serverskey}"}, | |
database_type => "ms_registry", | |
comment => "Editing the windows registry to set the required NTP entries", | |
classes => kept_if_else("ntp_regkept", "ntp_regset", "ntp_regfail"); | |
&endif& | |
reports: | |
# Global report for the "Time synchronization (NTP)" component - Linux | |
(ntp_install_kept|(!linux.!windows)).ntpconf_kept.!ntpd_down:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntp daemon installed, configured and running"; | |
ntp_installed|repaired_ntpconf|ntp_restarted:: | |
"@@ntpConfiguration@@result_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntp service (package, configuration and/or process) repaired"; | |
# Global report for the "Time synchronization (NTP)" component - Windows | |
ntp_regkept:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service configured and running"; | |
ntp_regset.ntp_win32time_started:: | |
"@@ntpConfiguration@@result_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service repaired, it is now configured and running"; | |
# Individual reports for the "Time synchronization (NTP)" component's parts | |
cant_install_ntp:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntp package could not be installed"; | |
ntp_installed:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntp package installed"; | |
ntp_install_kept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntp package already installed"; | |
!linux.!windows:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#Support to check if ntp is installed not available on this platform"; | |
repaired_ntpconf:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntpd configuration updated"; | |
not_repaired_ntpconf:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntpd configuration could not be changed"; | |
ntpd_down:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntpd process was not running"; | |
ntp_restarted:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntpd process restarted"; | |
cant_restart_ntp:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#ntpd process could not be restarted"; | |
ntp_regset:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service configured in the Windows registry. W32Time will restart"; | |
ntp_regfail:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service could not be configured in the Windows registry"; | |
ntp_regkept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service was already configured in the Windows registry"; | |
ntp_win32time_started:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time synchronization (NTP)@@None@@${g.execRun}##${g.uuid}@#NTP service (W32Time) restarted"; | |
# Global reports for the "Time zone" component's parts | |
repaired_localtime|repaired_redhattz|repaired_debiantz|repaired_susetz:: | |
"@@ntpConfiguration@@result_repaired@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone was reset"; | |
localtime_kept.((redhat.redhattz_kept)|(debian.debiantz_kept)|(SuSE.susetz_kept)):: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone was already correctly configured"; | |
clock_timezone_noedit:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone edition disabled"; | |
# Individual reports for the "Time zone" component's parts | |
(windows.!clock_timezone_noedit).clock_vardef.!need_to_change_timezone:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone was already correctly configured"; | |
timezone_change_repaired|repaired_localtime:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone was reset (localtime file changed)"; | |
not_repaired_localtime|timezone_change_failed:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone could not be set (localtime file could not be changed)"; | |
localtime_kept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Time zone was already set (localtime file didn't need changing)"; | |
repaired_redhattz:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Red Hat-style specific time zone parameters updated (/etc/sysconfig/clock)"; | |
not_repaired_redhattz:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Could not update Red Hat-style time zone parameters (/etc/sysconfig/clock)"; | |
redhattz_kept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Red Hat-style time zone parameters already correct (/etc/sysconfig/clock)"; | |
repaired_debiantz:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Debian-style time zone parameters updated (/etc/timezone)"; | |
not_repaired_debiantz:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Could not update Debian-style time zone parameters (/etc/timezone)"; | |
debiantz_kept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Debian-style time zone parameters already correct (/etc/timezone)"; | |
repaired_susetz:: | |
"@@ntpConfiguration@@log_repaired@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#SuSE-style time zone parameters updated (/etc/sysconfig/clock)"; | |
not_repaired_susetz:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#Could not update SuSE-style time zone parameters (/etc/sysconfig/clock)"; | |
susetz_kept:: | |
"@@ntpConfiguration@@log_info@@&TRACKINGKEY&@@Time zone@@None@@${g.execRun}##${g.uuid}@#SuSE-style time zone parameters already correct (/etc/sysconfig/clock)"; | |
# Global reports for the "Hardware clock (RTC)" component | |
(!windows.!ntp_hwclock_sync_error.!ntp_hwclock_synced):: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Hardware clock (RTC)@@None@@${g.execRun}##${g.uuid}@#It is not yet time to synchronize the hardware clock with the NTP time. Skipping..."; | |
ntp_hwclock_synced:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Hardware clock (RTC)@@None@@${g.execRun}##${g.uuid}@#The hardware clock has been synchronized with the NTP time"; | |
ntp_hwclock_sync_error:: | |
"@@ntpConfiguration@@result_error@@&TRACKINGKEY&@@Hardware clock (RTC)@@None@@${g.execRun}##${g.uuid}@#The hardware clock could not be synchronized with the NTP time"; | |
windows:: | |
"@@ntpConfiguration@@result_success@@&TRACKINGKEY&@@Hardware clock (RTC)@@None@@${g.execRun}##${g.uuid}@#The hardware clock is automatically synchronized with the NTP time on Windows"; | |
} | |
bundle edit_line setNtpServer(serverlist) | |
{ | |
delete_lines: | |
"server.*"; | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
"server ${serverlist}"; | |
} | |
bundle edit_line EditCentOSTimezone(tz) | |
{ | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
replace_patterns: | |
# Ensure the ZONE is correct | |
"^[# ]*ZONE\=(?!${tz}).*$" | |
replace_with => value("ZONE=${tz}"); | |
# Change UTC | |
"^[# ]*UTC=\+.*$" | |
replace_with => value("UTC=false"); | |
# Change ARC | |
"^[# ]*ARC\s+.*$" | |
replace_with => value("ARC=false"); | |
} | |
bundle edit_line EditSuSETimezone(tz) | |
{ | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
replace_patterns: | |
# Ensure the TIMEZONE is correct | |
"^[# ]*TIMEZONE\=(?!\"${tz}\").*$" | |
replace_with => value("TIMEZONE=\"${tz}\""); | |
# Ensure the DEFAULT_TIMEZONE is correct | |
"^[# ]*DEFAULT_TIMEZONE\=(?!\"${tz}\").*$" | |
replace_with => value("DEFAULT_TIMEZONE=\"${tz}\""); | |
# Ensure the SYSTOHC is correct | |
"^[# ]*SYSTOHC\=(?!\"yes\").*$" | |
replace_with => value("SYSTOHC=\"yes\""); | |
} | |
bundle edit_line EditDebianTimezone(tz) | |
{ | |
insert_lines: | |
# Ensure the ZONE is correct | |
"${tz}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle common generic_cmd_var_def { | |
vars: | |
&GENERIC_COMMAND_VARIABLE_NAME, GENERIC_COMMAND_VARIABLE_BINARY, GENERIC_COMMAND_VARIABLE_SHELL:{name, binary, shell |"&name&" string => execresult("&binary&", "&shell&"); | |
}& | |
} | |
bundle agent generic_cmd_var_def_report { | |
vars: | |
&TRACKINGKEY:{directiveId |"generic_command_name_uuid[&i&]" string => "&directiveId&"; | |
}& | |
&GENERIC_COMMAND_VARIABLE_NAME:{name |"generic_cmd_variable_name[&i&]" string => "&name&"; | |
}& | |
"generic_cmd_variable_name_index" slist => getindices("generic_command_name_uuid"); | |
reports: | |
cfengine_3:: | |
"@@genericCommandVariableDefinition@@result_success@@${generic_command_name_uuid[${generic_cmd_variable_name_index}]}@@Variable command definition@@${generic_cmd_variable_name[${generic_cmd_variable_name_index}]}@@${g.execRun}##${g.uuid}@#A generic command variable definition is set for variable ${generic_cmd_variable_name[${generic_cmd_variable_name_index}]}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle common generic_variable_definition | |
{ | |
vars: | |
&GENERIC_VARIABLE_NAME, GENERIC_VARIABLE_CONTENT:{name, content |"&name&" string => "&content&", | |
policy => "overridable"; | |
}& | |
} | |
bundle agent generic_variable_def_report | |
{ | |
vars: | |
&TRACKINGKEY:{directiveId |"generic_name_uuid[&i&]" string => "&directiveId&"; | |
}& | |
&GENERIC_VARIABLE_NAME:{name |"generic_variable_name[&i&]" string => "&name&"; | |
}& | |
"generic_variable_name_index" slist => getindices("generic_name_uuid"); | |
reports: | |
(linux|!linux):: | |
"@@genericVariableDefinition@@result_success@@${generic_name_uuid[${generic_variable_name_index}]}@@Variable definition@@${generic_variable_name[${generic_variable_name_index}]}@@${g.execRun}##${g.uuid}@#A generic variable definition is set for variable ${generic_variable_name[${generic_variable_name_index}]}"; | |
} | |
##################################################################################### | |
# Copyright 2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################### | |
# Monitor partition and optionnaly execute command if threshold is reached | |
# | |
# Take a partition mount point and check free space | |
# Execute a command if threshold is reached | |
# | |
bundle agent monitor_partition_size { | |
vars: | |
&PARTITION_SIZE_MONITORING_PATH:{path |"partition[&i&][path]" string => "&path&"; | |
}& | |
&PARTITION_SIZE_MONITORING_FREE_SIZE:{freesize |"partition[&i&][freesize]" string => "&freesize&"; | |
}& | |
&PARTITION_SIZE_MONITORING_CMD_EXEC_REPAIRED_COMMAND:{repaired_cmd |"partition[&i&][repaired_cmd]" string => "&repaired_cmd&"; | |
}& | |
&TRACKINGKEY:{directiveId |"partition[&i&][uuid]" string => "&directiveId&"; | |
}& | |
"index" slist => getindices("partition"); | |
classes: | |
# Set classes to define when to run command executions | |
&PARTITION_SIZE_MONITORING_CMD_EXEC_REPAIRED_RUN:{repaired_cmd_run |"monitorPartitionSize_repaired_cmd_run_&i&" expression => strcmp("&repaired_cmd_run&", "true"); | |
}& | |
commands: | |
"${partition[${index}][repaired_cmd]}" | |
classes => rudder_common_classes("monitorPartitionSize_repaired_cmd_${index}"), | |
contain => in_shell, | |
ifvarclass => "monitorPartitionSize_repaired_cmd_run_${index}.monitorPartitionSize_partition_${index}_full"; | |
storage: | |
"${partition[${index}][path]}" | |
volume => freespacecheck("${partition[${index}][freesize]}"), | |
classes => if_notkept("monitorPartitionSize_partition_${index}_full"), | |
comment => "Check free space available on ${partition[${index}][path]}"; | |
reports: | |
cfengine:: | |
# Partition status reporting | |
# Success | |
"@@monitorPartitionSize@@result_success@@${partition[${index}][uuid]}@@Partition@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#The partition ${partition[${index}][path]} has enough free space" | |
ifvarclass => "!monitorPartitionSize_partition_${index}_full"; | |
# Error | |
"@@monitorPartitionSize@@result_error@@${partition[${index}][uuid]}@@Partition@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#The partition ${partition[${index}][path]} has not enough free space" | |
ifvarclass => "monitorPartitionSize_partition_${index}_full"; | |
# Repaired command execution reporting | |
# Success not set | |
"@@monitorPartitionSize@@result_success@@${partition[${index}][uuid]}@@Command execution on threshold@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#Under threshold command execution was not set" | |
ifvarclass => "!monitorPartitionSize_repaired_cmd_run_${index}"; | |
# Success not needed | |
"@@monitorPartitionSize@@result_success@@${partition[${index}][uuid]}@@Command execution on threshold@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#Under threshold command execution was not needed" | |
ifvarclass => "monitorPartitionSize_repaired_cmd_run_${index}.!monitorPartitionSize_partition_${index}_full"; | |
# Repaired | |
"@@monitorPartitionSize@@result_repaired@@${partition[${index}][uuid]}@@Command execution on threshold@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#Under threshold command executed - ${partition[${index}][repaired_cmd]}" | |
ifvarclass => "monitorPartitionSize_repaired_cmd_run_${index}.monitorPartitionSize_repaired_cmd_${index}_repaired"; | |
# Error | |
"@@monitorPartitionSize@@result_error@@${partition[${index}][uuid]}@@Command execution on threshold@@${partition[${index}][path]}@@${g.execRun}##${g.uuid}@#Under threshold command failed to execute" | |
ifvarclass => "monitorPartitionSize_repaired_cmd_run_${index}.monitorPartitionSize_repaired_cmd_${index}_error"; | |
} | |
body volume freespacecheck(threshold) { | |
freespace => "${threshold}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
#Check the dns configuration, and correct it if required | |
#CAUTION : the loop for windows does not work well, a bug is opened (#82) | |
bundle agent check_dns_configuration | |
{ | |
vars: | |
"resolvers" slist => {&DNS_RESOLVERS: { "&it&" };separator=", "&}; | |
"searchlist" slist => {&DNS_SEARCHLIST: { "&it&" };separator=", "&}; | |
"options" slist => {&DNS_OPTIONS: { "&it&" };separator=", "&}; | |
"spaced_searchlist" string => join(" ", "searchlist"); | |
"spaced_options" string => join(" ", "options"); | |
&if(NOVA)& | |
windows:: | |
"searchkey" string => join("\,", searchlist); | |
"resolvkey" string => join("\,", resolvers); | |
"adapters" string => execresult("\"${g.rudder_sbin}\registrydns.bat\"", "noshell"), | |
comment => "Fetching all the adapter"; | |
"adapterslist" slist => splitstring("${adapters}", ";", "15"); | |
&endif& | |
classes: | |
# DNS Resolver edition ? | |
"dns_resolver_edit" not => strcmp("&DNS_RESOLVERS_EDIT&","false"); | |
# DNS Search suffix edition ? | |
"dns_searchlist_edit" not => strcmp("&DNS_SEARCHLIST_EDIT&","false"); | |
# DNS options edition ? | |
"dns_options_edit" not => strcmp("&DNS_OPTIONS_EDIT&","false"); | |
files: | |
!windows:: | |
"${sys.resolv}" | |
create => "true", | |
edit_line => resolv_edition("${this.spaced_searchlist}", "@{this.resolvers}", "${this.spaced_options}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("dns_kept", "dns_repaired", "cant_repair_dns"); | |
&if(NOVA)& | |
methods: | |
windows.dns_resolver_edit:: | |
"any" usebundle => checkDNS(${adapterslist}, ${resolvkey}); | |
databases: | |
windows.dns_resolver_edit:: | |
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" | |
database_operation => "verify", | |
database_type => "ms_registry", | |
database_rows => { "NameServer,REG_SZ,${resolvkey}"}, | |
comment => "Set the top level resolver", | |
classes => kept_if_else("dns_resolver_kept", "dns_repaired_resolver", "cant_repair_dns_resolver"); | |
windows.dns_searchlist_edit:: | |
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" | |
database_operation => "verify", | |
database_type => "ms_registry", | |
database_rows => { "SearchList,REG_SZ,${searchkey}"}, | |
comment => "Set the search list", | |
classes => kept_if_else("dns_searchlist_kept", "dns_repaired_searchlist", "cant_repair_dns_searchlist"); | |
&endif& | |
reports: | |
dns_resolver_edit:: | |
"@@ConfigureDNS@@log_debug@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Settings are to edit DNS resolvers"; | |
dns_searchlist_edit:: | |
"@@ConfigureDNS@@log_debug@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Settings are to edit DNS searchlist"; | |
(!windows.dns_repaired):: | |
"@@ConfigureDNS@@result_repaired@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#DNS settings were updated"; | |
windows.((dns_repaired_resolver.!cant_repair_dns_resolver.dns_resolver_edit)|(dns_repaired_searchlist.!cant_repair_dns_searchlist.dns_searchlist_edit)):: | |
"@@ConfigureDNS@@result_repaired@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#DNS settings were updated"; | |
cant_repair_dns:: | |
"@@ConfigureDNS@@result_error@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Could not edit the ${sys.resolv} configuration file"; | |
cant_repair_dns_searchlist:: | |
"@@ConfigureDNS@@result_error@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Could not set DNS search list in the Windows registry"; | |
cant_repair_dns_resolver:: | |
"@@ConfigureDNS@@result_error@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Could not set DNS resolver list in the Windows registry"; | |
!windows.dns_kept.!dns_repaired.!cant_repair_dns:: | |
"@@ConfigureDNS@@result_success@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#The DNS is correctly configured"; | |
&if(NOVA)& | |
#windows and something to do | |
windows.((dns_resolver_edit.dns_resolver_kept.!dns_repaired_resolver)|!dns_resolver_edit).((dns_searchlist_edit.dns_searchlist_kept.!dns_repaired_searchlist)|!dns_searchlist_edit):: | |
"@@ConfigureDNS@@result_success@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#The DNS is correctly configured"; | |
&endif& | |
&if(COMMUNITY)& | |
windows:: | |
"@@ConfigureDNS@@result_error@@&TRACKINGKEY&@@dnsConfiguration@@None@@${g.execRun}##${g.uuid}@#Can't repair the dns configuration on a Windows with community edition"; | |
&endif& | |
} | |
&if(NOVA)& | |
###################################################### | |
# For each adapter passed in arguement, add the value | |
# NameServer, regKey | |
###################################################### | |
bundle agent checkDNS(adapter, regKey) | |
{ | |
classes: | |
"valid" expression => regcmp("{.*","${adapter}"), | |
comment => "A valid adapter starts with {"; | |
databases: | |
valid:: | |
"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\${adapter}" | |
database_operation => "verify", | |
database_type => "ms_registry", | |
database_rows => { "NameServer,REG_SZ,${regKey}"}, | |
classes => kept_if_else("dns_resolver_kept", "dns_repaired_resolver", "cant_repair_dns_resolver"); | |
} | |
&endif& | |
####################################################### | |
# Add lines in the file, formated for resolv.conf file | |
bundle edit_line resolv_edition(search, list, options) | |
{ | |
classes: | |
# DNS Resolver edition ? | |
"dns_resolver_edit" not => strcmp("&DNS_RESOLVERS_EDIT&","false"); | |
# DNS Search suffix edition ? | |
"dns_searchlist_edit" not => strcmp("&DNS_SEARCHLIST_EDIT&","false"); | |
# DNS options edition ? | |
"dns_options_edit" not => strcmp("&DNS_OPTIONS_EDIT&","false"); | |
delete_lines: | |
dns_searchlist_edit:: | |
"search.*"; | |
dns_resolver_edit:: | |
"nameserver.*"; | |
dns_options_edit:: | |
"options.*"; | |
insert_lines: | |
"${rudder_parameters.rudder_file_edit_header}" | |
location => start, | |
insert_type => "preserve_block"; | |
dns_options_edit:: | |
"options ${options}"; | |
dns_searchlist_edit:: | |
"search ${search}"; | |
dns_resolver_edit:: | |
"nameserver ${list}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# (C) Normation 2011 | |
# | |
# NOTE : I permitted the creation of the hosts file if absent, but on a purely | |
# functionnal side, its absence means a severe breakage of your IP stack. Be | |
# aware of this if a file creation is reported ! | |
# | |
bundle agent check_hosts_configuration | |
{ | |
vars: | |
&HOSTS_HOST:{host |"hosts_host[&i&]" string => "&host&"; | |
}& | |
&HOSTS_IP:{ip |"hosts_ip[&i&]" string => "&ip&"; | |
}& | |
"hosts_base_template" string => "&HOSTS_BASE_TEMPLATE&"; | |
files: | |
!windows:: | |
"/etc/hosts" | |
create => "true", | |
perms => m("644"), | |
&if (HOSTS_ENFORCE)& | |
edit_defaults => empty_backup, | |
&else& | |
edit_defaults => noempty_backup, | |
&endif& | |
edit_line => set_hosts_values("check_hosts_configuration.hosts_host", "check_hosts_configuration.hosts_ip", "${hosts_base_template}"), | |
classes => kept_if_else("hosts_edition_kept", "hosts_edition_done", "hosts_edition_failed"); | |
windows:: | |
"${sys.winsysdir}\drivers\etc\hosts" | |
create => "true", | |
# perms => m("644"), | |
&if (HOSTS_ENFORCE)& | |
edit_defaults => empty_backup, | |
&else& | |
edit_defaults => noempty_backup, | |
&endif& | |
edit_line => set_hosts_values("check_hosts_configuration.hosts_host", "check_hosts_configuration.hosts_ip"), | |
classes => kept_if_else("hosts_edition_kept", "hosts_edition_done", "hosts_edition_failed"); | |
reports: | |
cfengine:: | |
&if (HOSTS_ENFORCE)& | |
"@@hostsConfiguration@@log_debug@@&TRACKINGKEY&@@hostsConfiguration@@None@@${g.execRun}##${g.uuid}@#Hosts file content enforcement requested"; | |
&endif& | |
hosts_edition_done:: | |
"@@hostsConfiguration@@result_repaired@@&TRACKINGKEY&@@hostsConfiguration@@None@@${g.execRun}##${g.uuid}@#Hosts file was updated"; | |
hosts_edition_kept.!hosts_edition_done:: | |
"@@hostsConfiguration@@result_success@@&TRACKINGKEY&@@hostsConfiguration@@None@@${g.execRun}##${g.uuid}@#Hosts file already OK"; | |
hosts_edition_failed:: | |
"@@hostsConfiguration@@result_error@@&TRACKINGKEY&@@hostsConfiguration@@None@@${g.execRun}##${g.uuid}@#Hosts file could not be edited"; | |
} | |
bundle edit_line set_hosts_values(hosts, ips, base_tmpl) | |
{ | |
vars: | |
"hosts_index" slist => getindices("${hosts}"); | |
delete_lines: | |
"${${ips}[${hosts_index}]}.*"; | |
insert_lines: | |
&if (HOSTS_ENFORCE)& | |
"${base_tmpl}" | |
insert_type => "preserve_block"; | |
&endif& | |
"${${ips}[${hosts_index}]} ${${hosts}[${hosts_index}]}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# (C) Normation 2011 | |
bundle agent check_nfs_client_configuration | |
{ | |
vars: | |
&NFS_CLIENT_REMOTE_PATH:{remote_path |"nfs_client_remote_path[&i&]" string => "&remote_path&"; | |
}& | |
&NFS_CLIENT_REMOTE_SERVER:{remote_server |"nfs_client_remote_server[&i&]" string => "&remote_server&"; | |
}& | |
&NFS_CLIENT_LOCAL_PATH:{local_path |"nfs_client_local_path[&i&]" string => "&local_path&"; | |
}& | |
&NFS_CLIENT_REMOTE_TYPE:{remote_type |"nfs_client_remote_type[&i&]" string => "&remote_type&"; | |
}& | |
&NFS_CLIENT_ADDFSTAB:{addfstab |"nfs_client_addfstab[&i&]" string => "&addfstab&"; | |
}& | |
&NFS_CLIENT_UMOUNT:{umount |"nfs_client_umount[&i&]" string => "&umount&"; | |
}& | |
&TRACKINGKEY:{uuid |"nfs_client_uuid[&i&]" string => "&uuid&"; | |
}& | |
"nfs_client_index" slist => getindices("nfs_client_remote_path"); | |
classes: | |
"begin_evaluation" expression => isvariable("nfs_client_index"); | |
begin_evaluation:: | |
"index_${nfs_client_index}_add" expression => strcmp("${nfs_client_umount[${nfs_client_index}]}", "no"); | |
"index_${nfs_client_index}_remove" expression => strcmp("${nfs_client_umount[${nfs_client_index}]}", "yes"); | |
storage: | |
!windows:: | |
"${nfs_client_local_path[${nfs_client_index}]}" | |
mount => rudder_nfs("${nfs_client_remote_server[${nfs_client_index}]}","${nfs_client_remote_path[${nfs_client_index}]}", "${nfs_client_remote_type[${nfs_client_index}]}", "${nfs_client_addfstab[${nfs_client_index}]}"), | |
classes => kept_if_else("${nfs_client_index}_operation_kept", "${nfs_client_index}_operation_ok", "${nfs_client_index}_operation_failed"), | |
ifvarclass => "index_${nfs_client_index}_add"; | |
"${nfs_client_local_path[${nfs_client_index}]}" | |
mount => unmount, | |
classes => kept_if_else("${nfs_client_index}_operation_kept", "${nfs_client_index}_operation_ok", "${nfs_client_index}_operation_failed"), | |
ifvarclass => "index_${nfs_client_index}_remove"; | |
reports: | |
!windows:: | |
"@@nfsClient@@result_repaired@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was successfully mounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}" | |
ifvarclass => "${nfs_client_index}_operation_ok.index_${nfs_client_index}_add"; | |
"@@nfsClient@@result_repaired@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was successfully unmounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}" | |
ifvarclass => "${nfs_client_index}_operation_ok.index_${nfs_client_index}_remove"; | |
"@@nfsClient@@result_success@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was already mounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}" | |
ifvarclass => "${nfs_client_index}_operation_kept.index_${nfs_client_index}_add"; | |
"@@nfsClient@@result_success@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was not mounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}" | |
ifvarclass => "${nfs_client_index}_operation_kept.index_${nfs_client_index}_remove"; | |
"@@nfsClient@@result_error@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was NOT mounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}. This could be an error in the mount definition or an nfs failure" | |
ifvarclass => "${nfs_client_index}_operation_failed.!${nfs_client_index}_operation_ok.index_${nfs_client_index}_add"; | |
"@@nfsClient@@result_error@@${nfs_client_uuid[${nfs_client_index}]}@@NFS mountpoint@@${nfs_client_local_path[${nfs_client_index}]}@@${g.execRun}##${g.uuid}@#The path ${nfs_client_local_path[${nfs_client_index}]} was NOT unmounted on ${nfs_client_remote_server[${nfs_client_index}]}:${nfs_client_remote_path[${nfs_client_index}]}. This could be an error in the mount definition or an nfs failure" | |
ifvarclass => "${nfs_client_index}_operation_failed.!${nfs_client_index}_operation_ok.index_${nfs_client_index}_remove"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################### | |
# Installs the NFS client | |
bundle agent check_nfs_client_installation | |
{ | |
packages: | |
linux.!redhat.!SuSE:: | |
"nfs-common" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("nfs_client_here", "nfs_client_installed", "cant_install_nfs_client"), | |
comment => "Installing NFS client using generic interface"; | |
redhat:: | |
"nfs-utils" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("nfs_client_here", "nfs_client_installed", "cant_install_nfs_client"), | |
comment => "Installing NFS client using generic interface"; | |
SuSE:: | |
"nfs-client" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("nfs_client_here", "nfs_client_installed", "cant_install_nfs_client"), | |
comment => "Installing NFS client using generic interface"; | |
reports: | |
nfs_client_here:: | |
"@@nfsClient@@result_success@@&TRACKINGKEY&@@NFS Client package install@@None@@${g.execRun}##${g.uuid}@#NFS client already installed"; | |
nfs_client_installed:: | |
"@@nfsClient@@result_repaired@@&TRACKINGKEY&@@NFS Client package install@@None@@${g.execRun}##${g.uuid}@#NFS client installed"; | |
cant_install_nfs_client:: | |
"@@nfsClient@@result_error@@&TRACKINGKEY&@@NFS Client package install@@None@@${g.execRun}##${g.uuid}@#Can't install the NFS client package"; | |
!linux:: | |
"@@nfsClient@@result_success@@&TRACKINGKEY&@@NFS Client package install@@None@@${g.execRun}##${g.uuid}@#Support to check if NFS client is installed not available on this platform"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# (C) Normation 2011 | |
bundle agent check_nfs_server_configuration | |
{ | |
vars: | |
&NFS_SERVER_PATH:{path |"nfs_server_path[&i&]" string => "&path&"; | |
}& | |
&NFS_SERVER_NETWORK:{network |"nfs_server_network[&i&]" string => "&network&"; | |
}& | |
&NFS_SERVER_SECURE,NFS_SERVER_READWRITE,NFS_SERVER_SYNC,NFS_SERVER_WDELAY,NFS_SERVER_HIDE,NFS_SERVER_SUBTREECHECK,NFS_SERVER_SECURELOCKS,NFS_SERVER_ACL:{secure, readwrite, sync, wdelay, hide, subtreecheck, securelocks, acl |"nfs_server_options[&i&]" string => "&secure&,&readwrite&,&sync&,&wdelay&,&hide&,&subtreecheck&,&securelocks&,&acl&"; | |
}& | |
&TRACKINGKEY:{uuid |"nfs_server_uuid[&i&]" string => "&uuid&"; | |
}& | |
"nfs_server_index" slist => getindices("nfs_server_path"); | |
files: | |
(debian|redhat|SuSE):: | |
"/etc/rc2.d/S.*nfs.*" | |
create => "true", | |
#depth_search => recurse("0"), | |
#file_select => ssh_startlink, | |
action => WarnOnly, | |
classes => cf2_if_else("nfs_server_bootstarted", "nfs_server_unbootstarted"); | |
!windows:: | |
"/etc/exports" | |
create => "true", | |
perms => m("644"), | |
edit_defaults => noempty_backup, | |
edit_line => set_nfs_server_values("${nfs_server_path[${nfs_server_index}]}", "${nfs_server_network[${nfs_server_index}]}", "${nfs_server_options[${nfs_server_index}]}"), | |
classes => kept_if_else("nfs_server_${nfs_server_index}_kept", "nfs_server_${nfs_server_index}_done", "nfs_server_${nfs_server_index}_failed"); | |
commands: | |
debian:: | |
"/etc/init.d/nfs-kernel-server" | |
args => "restart", | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_done"), | |
classes => cf2_if_else("nfs_server_${nfs_server_index}_restarted", "nfs_server_${nfs_server_index}_not_restarted"), | |
comment => "Restarting the NFS server"; | |
"/usr/sbin/update-rc.d" | |
args => "nfs-kernel-server defaults", | |
ifvarclass => canonify("nfs_server_unbootstarted"), | |
comment => "adding nfs to the startup scripts"; | |
redhat:: | |
"/sbin/chkconfig" | |
args => "--add nfs", | |
ifvarclass => canonify("nfs_server_unbootstarted"), | |
comment => "adding nfs to the startup scripts"; | |
"/sbin/chkconfig" | |
args => "--add nfslock", | |
ifvarclass => canonify("nfs_server_unbootstarted"), | |
comment => "adding nfslock to the startup scripts"; | |
"/sbin/service" | |
args => "nfs restart", | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_done"), | |
classes => cf2_if_else("nfs_server_${nfs_server_index}_restarted", "nfs_server_${nfs_server_index}_not_restarted"), | |
comment => "Restarting the NFS server"; | |
"/sbin/service" | |
args => "nfslock restart", | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_done"), | |
classes => cf2_if_else("nfs_server_${nfs_server_index}_restarted", "nfs_server_${nfs_server_index}_not_restarted"), | |
comment => "Restarting the NFS lock server"; | |
SuSE:: | |
"/sbin/chkconfig" | |
args => "--add nfsserver", | |
ifvarclass => canonify("nfs_server_unbootstarted"), | |
comment => "adding nfs to the startup scripts"; | |
"/sbin/service" | |
args => "nfsserver restart", | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_done"), | |
classes => cf2_if_else("nfs_server_${nfs_server_index}_restarted", "nfs_server_${nfs_server_index}_not_restarted"), | |
comment => "Restarting the NFS server"; | |
reports: | |
!windows:: | |
"@@nfsServer@@result_repaired@@${nfs_server_uuid[${nfs_server_index}]}@@NFS server settings@@${nfs_server_path[${nfs_server_index}]}@@${g.execRun}##${g.uuid}@#The export ${nfs_server_path[${nfs_server_index}]} was successfully added" | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_done"); | |
"@@nfsServer@@result_success@@${nfs_server_uuid[${nfs_server_index}]}@@NFS server settings@@${nfs_server_path[${nfs_server_index}]}@@${g.execRun}##${g.uuid}@#The export ${nfs_server_path[${nfs_server_index}]} is already present" | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_kept"); | |
"@@nfsServer@@result_error@@${nfs_server_uuid[${nfs_server_index}]}@@NFS server settings@@${nfs_server_path[${nfs_server_index}]}@@${g.execRun}##${g.uuid}@#The export ${nfs_server_path[${nfs_server_index}]} could not be added" | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_failed"); | |
(debian|redhat|SuSE):: | |
"@@nfsServer@@log_repaired@@${nfs_server_uuid[${nfs_server_index}]}@@NFS server settings@@${nfs_server_path[${nfs_server_index}]}@@${g.execRun}##${g.uuid}@#Restarted the NFS server because of the export ${nfs_server_path[${nfs_server_index}]}" | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_restarted"); | |
"@@nfsServer@@result_error@@${nfs_server_uuid[${nfs_server_index}]}@@NFS server settings@@${nfs_server_path[${nfs_server_index}]}@@${g.execRun}##${g.uuid}@#Could not restart the NFS server because of the export ${nfs_server_path[${nfs_server_index}]}" | |
ifvarclass => canonify("nfs_server_${nfs_server_index}_not_restarted"); | |
} | |
bundle edit_line set_nfs_server_values(export, network, options) | |
{ | |
delete_lines: | |
"${export}.*"; | |
insert_lines: | |
"${export} ${network}(${options})"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################### | |
# Installs the NFS server | |
bundle agent check_nfs_server_installation | |
{ | |
packages: | |
linux.!redhat:: | |
"nfs-kernel-server" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("nfs_server_here", "nfs_server_installed", "cant_install_nfs_server"), | |
comment => "Installing NFS server using generic interface"; | |
redhat:: | |
"nfs-utils" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("nfs_server_here", "nfs_server_installed", "cant_install_nfs_server"), | |
comment => "Installing NFS server using generic interface"; | |
reports: | |
nfs_server_here:: | |
"@@nfsServer@@result_success@@&TRACKINGKEY&@@NFS server package install@@None@@${g.execRun}##${g.uuid}@#NFS server package already installed"; | |
nfs_server_installed:: | |
"@@nfsServer@@result_repaired@@&TRACKINGKEY&@@NFS server package install@@None@@${g.execRun}##${g.uuid}@#NFS server package installed"; | |
cant_install_nfs_server:: | |
"@@nfsServer@@result_error@@&TRACKINGKEY&@@NFS server package install@@None@@${g.execRun}##${g.uuid}@#Can't install NFS server package"; | |
!linux:: | |
"@@nfsServer@@result_success@@&TRACKINGKEY&@@NFS server package install@@None@@${g.execRun}##${g.uuid}@#Support to check if NFS server is installed not available on this platform"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Routing management PT # | |
# # | |
# Objective: Check the routing parameters according to the given ones # | |
# and take the required actions (check or require) # | |
########################################################################## | |
bundle agent check_routing_parameters | |
{ | |
vars: | |
&ROUTING_FOUR_DESTINATION:{destination |"route[&i&]" string => "&destination&"; | |
}& | |
&ROUTING_FOUR_GATEWAY:{gateway |"gateway[&i&]" string => "&gateway&"; | |
}& | |
&ROUTING_FOUR_NETMASK:{netmask |"mask[&i&]" string => "&netmask&"; | |
}& | |
&ROUTING_FOUR_ACTION:{action |"action[&i&]" string => "&action&"; | |
}& | |
&TRACKINGKEY:{directiveId |"routing_directive_id[&i&]" string => "&directiveId&"; | |
}& | |
"routing_index" slist => getindices("route"); | |
"displayName[${routing_index}]" string => "${route[${routing_index}]} / ${mask[${routing_index}]} to ${gateway[${routing_index}]}"; | |
classes: | |
"checkroute_present" expression => fileexists("${g.rudder_tools}/checkroute.pl"); | |
commands: | |
!windows.checkroute_present:: | |
"${g.rudder_tools}/checkroute.pl ${route[${routing_index}]} ${mask[${routing_index}]} ${gateway[${routing_index}]} ${routing_index} ${action[${routing_index}]} linux" | |
contain => in_shell, | |
module => "true", | |
comment => "Analysing routes"; | |
"/sbin/route add -net ${route[${routing_index}]} netmask ${mask[${routing_index}]} gw ${gateway[${routing_index}]}" | |
contain => in_shell, | |
ifvarclass => canonify("route_${routing_index}_add"), | |
classes => cf2_if_else("route_${routing_index}_added", "route_${routing_index}_add_failed"); | |
"/sbin/route del -net ${route[${routing_index}]} netmask ${mask[${routing_index}]} gw ${gateway[${routing_index}]}" | |
contain => in_shell, | |
ifvarclass => canonify("route_${routing_index}_delete"), | |
classes => cf2_if_else("route_${routing_index}_deleted", "route_${routing_index}_delete_failed"); | |
windows.checkroute_present:: | |
"\"${g.rudder_base_sbin}\perl\bin\perl.exe\"" | |
args => "\"${g.rudder_tools}\checkroute.pl\" ${route[${routing_index}]} ${mask[${routing_index}]} ${gateway[${routing_index}]} ${routing_index} ${action[${routing_index}]} windows", | |
contain => in_shell, | |
module => "true", | |
comment => "Analysing routes"; | |
"\"${sys.winsysdir}\route.exe\"" | |
args => "ADD ${route[${routing_index}]} MASK ${mask[${routing_index}]} ${gateway[${routing_index}]}", | |
contain => in_shell, | |
ifvarclass => canonify("route_${routing_index}_add"), | |
classes => cf2_if_else("route_${routing_index}_added", "route_${routing_index}_add_failed"); | |
"\"${sys.winsysdir}\route.exe\"" | |
args => "DELETE ${route[${routing_index}]}", | |
contain => in_shell, | |
ifvarclass => canonify("route_${routing_index}_delete"), | |
classes => cf2_if_else("route_${routing_index}_deleted", "route_${routing_index}_delete_failed"); | |
reports: | |
checkroute_present:: | |
"@@routingManagement@@result_success@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} found, as expected." | |
ifvarclass => canonify("route_${routing_index}_found"); | |
# This should be a log_warn, when it's supported | |
"@@routingManagement@@result_error@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} found, and policy is: Check absence!" | |
ifvarclass => canonify("route_${routing_index}_found_warn"); | |
"@@routingManagement@@result_success@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} not found, as expected" | |
ifvarclass => canonify("route_${routing_index}_notfound"); | |
# This should be a log_warn, when it's supported | |
"@@routingManagement@@result_error@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} not found , and policy is: Check presence!" | |
ifvarclass => canonify("route_${routing_index}_notfound_warn"); | |
"@@routingManagement@@log_info@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} not found, attempting to add route..." | |
ifvarclass => canonify("route_${routing_index}_add"); | |
"@@routingManagement@@result_repaired@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} added successfully!" | |
ifvarclass => canonify("route_${routing_index}_added"); | |
"@@routingManagement@@result_error@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Could not add route ${displayName[${routing_index}]}!" | |
ifvarclass => canonify("route_${routing_index}_add_failed"); | |
"@@routingManagement@@result_repaired@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Route ${displayName[${routing_index}]} deleted successfully!" | |
ifvarclass => canonify("route_${routing_index}_deleted"); | |
"@@routingManagement@@result_error@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Could not delete route ${displayName[${routing_index}]}!" | |
ifvarclass => canonify("route_${routing_index}_delete_failed"); | |
!checkroute_present:: | |
"@@routingManagement@@result_error@@${routing_directive_id[${routing_index}]}@@IPv4 routing parameters@@${route[${routing_index}]}@@${g.execRun}##${g.uuid}@#Could not add route ${displayName[${routing_index}]}: helper program checkroute.pl not found!"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Enforce the defined process parameters | |
bundle agent process_management | |
{ | |
vars: | |
"dim_array" int => readstringarray("file","${sys.workdir}/inputs/processManagement/proclist","#[^\n]*",",",15,4000); | |
"procList" slist => getindices("file"); | |
methods: | |
"any" usebundle => check_process("${file[${procList}][0]}", | |
"${file[${procList}][1]}", | |
"${file[${procList}][2]}", | |
"${file[${procList}][3]}", | |
"${file[${procList}][4]}", | |
"${file[${procList}][5]}"); | |
} | |
bundle agent check_process(directiveId, name, maxInst, minInst, command, args) | |
{ | |
classes: | |
"${name}_command_empty" expression => strcmp("command",""); | |
"${name}_arg_empty" expression => strcmp("args",""); | |
processes: | |
"${name}" | |
restart_class => "${name}_restart", | |
comment => "Verifying process presence"; | |
"${name}" | |
process_count => check_process_count("${name}", "${maxInst}","${minInst}"), | |
classes => kept_if_else("${name}_ok", "${name}_anomaly", "${name}_error"), | |
comment => "Verifying process count"; | |
commands: | |
"${command}" | |
args => "${args}", | |
classes => kept_if_else("${name}_restart_ok", "${name}_restart_ok", "${name}_restart_error"), | |
ifvarclass => and( canonify("${name}_restart"), not(canonify("${name}_command_empty")), not(canonify("${name}_arg_empty")) ); | |
"${command}" | |
classes => kept_if_else("${name}_restart_ok", "${name}_restart_ok", "${name}_restart_error"), | |
ifvarclass => and( canonify("${name}_restart"), not(canonify("${name}_command_empty")), canonify("${name}_arg_empty") ); | |
"/etc/init.d/${name}" | |
args => "restart", | |
classes => kept_if_else("${name}_restart_ok", "${name}_restart_ok", "${name}_restart_error"), | |
ifvarclass => and( canonify("${name}_restart"), canonify("${name}_command_empty") ); | |
reports: | |
cfengine_3:: | |
"@@ProcessManagement@@result_error@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process count could't be checked" | |
ifvarclass => canonify("${name}_error"); | |
"@@ProcessManagement@@log_info@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process instance count is out of the permitted range" | |
ifvarclass => canonify("${name}_anomaly"); | |
"@@ProcessManagement@@log_info@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process will be restarted" | |
ifvarclass => canonify("${name}_restart"); | |
"@@ProcessManagement@@result_success@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process was in range (${minInst}-${maxInst})" | |
ifvarclass => canonify("${name}_ok"); | |
"@@ProcessManagement@@result_repaired@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process has been restarted" | |
ifvarclass => canonify("${name}_restart_ok"); | |
"@@ProcessManagement@@result_error@@${directiveId}@@Process@@${name}@@${g.execRun}##${g.uuid}@#${name}: the process could not be restarted" | |
ifvarclass => canonify("${name}_restart_error"); | |
} | |
body process_count check_process_count(name, max, min) | |
{ | |
match_range => irange("${min}","${max}"); | |
out_of_range_define => { "${name}_anomaly" }; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# List of the process parameters to enforce | |
# Format of the file : | |
# policyIsntanceId, name:maximum_instances:minimum_instances | |
&TRACKINGKEY, PROCESS_NAME, PROCESS_MIN_INSTANCES, PROCESS_MAX_INSTANCES, PROCESS_COMMAND, PROCESS_MAX_ARGS:{directiveId, name, maxInst, minInst, command, args | &directiveId&,&name&,&maxInst&,&minInst&,&command&,&args& | |
}& | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Enforce the defined services parameters | |
bundle agent services_management | |
{ | |
vars: | |
&SERVICE_MANAGED_NAME:{name |"service[&i&][name]" string => "&name&"; | |
}& | |
&SERVICE_MANAGED_NAME:{name |"service[&i&][canon_name]" string => canonify("&name&"); | |
}& | |
&PROCESS_MANAGED_NAME:{process |"service[&i&][process]" string => "&process&"; | |
}& | |
&PROCESS_MANAGED_RUNNING:{running |"service[&i&][running]" string => "&running&"; | |
}& | |
&PROCESS_MANAGED_KILLING_METHOD:{kill |"service[&i&][killMethod]" string => "&kill&"; | |
}& | |
&PROCESS_MANAGED_MIN_INSTANCES:{min_instance |"service[&i&][min_instance]" string => "&min_instance&"; | |
}& | |
&PROCESS_MANAGED_MAX_INSTANCES:{max_instance |"service[&i&][max_instance]" string => "&max_instance&"; | |
}& | |
&TRACKINGKEY:{piuuid |"service[&i&][uuid]" string => "&piuuid&"; | |
}& | |
"index" slist => getindices("service"); | |
SuSE:: | |
"service_check_boot_status_cmd_${index}" string => "/sbin/chkconfig --check ${service[${index}][name]}"; | |
"service_add_boot_cmd_${index}" string => "/sbin/insserv -d ${service[${index}][name]}"; | |
"service_remove_boot_cmd_${index}" string => "/sbin/insserv -rd ${service[${index}][name]}"; | |
redhat:: | |
"service_check_boot_status_cmd_${index}" string => "/sbin/chkconfig ${service[${index}][name]}"; | |
"service_add_boot_cmd_${index}" string => "/sbin/chkconfig ${service[${index}][name]} on"; | |
"service_remove_boot_cmd_${index}" string => "/sbin/chkconfig ${service[${index}][name]} off"; | |
debian:: | |
"service_add_boot_cmd_${index}" string => "/usr/sbin/update-rc.d ${service[${index}][name]} remove \&\& /usr/sbin/update-rc.d ${service[${index}][name]} defaults"; | |
"service_remove_boot_cmd_${index}" string => "/usr/sbin/update-rc.d -f ${service[${index}][name]} remove \&\& /usr/sbin/update-rc.d ${service[${index}][name]} stop 20 2 3 4 5 ."; | |
classes: | |
&PROCESS_MANAGED_NAME:{name |"defined_process_name_&i&" not => strcmp("&name&", ""); | |
}& | |
&PROCESS_MANAGED_CHECK_RANGE:{check |"check_process_range_&i&" expression => strcmp("&check&", "true"); | |
}& | |
&PROCESS_MANAGED_RUNNING:{running |"start_process_&i&" expression => strcmp("&running&", "true"); | |
}& | |
&PROCESS_MANAGED_RUNNING:{running |"stop_process_&i&" expression => strcmp("&running&", "false"); | |
}& | |
&PROCESS_MANAGED_KILLING_METHOD:{kill |"graceful_stop_process_&i&" expression => strcmp("&kill&", "graceful"); | |
}& | |
&PROCESS_MANAGED_KILLING_METHOD:{kill |"term_stop_process_&i&" expression => strcmp("&kill&", "term"); | |
}& | |
&PROCESS_MANAGED_KILLING_METHOD:{kill |"kill_stop_process_&i&" expression => strcmp("&kill&", "kill"); | |
}& | |
&PROCESS_MANAGED_BOOTSTART:{bootstart |"bootstart_process_&i&" expression => strcmp("&bootstart&", "true"); | |
}& | |
&PROCESS_MANAGED_BOOTSTART:{bootstart |"bootstart_prevent_process_&i&" expression => strcmp("&bootstart&", "false"); | |
}& | |
files: | |
debian:: | |
"/etc/rc2.d/S.*${service[${index}][name]}.*" | |
create => "true", | |
action => WarnOnly, | |
classes => if_else("service_${index}_bootstarted", "service_${index}_unbootstarted"); | |
processes: | |
# check the service status | |
"${service[${index}][process]}" | |
comment => "Check the process status", | |
restart_class => "process_${index}_restart", | |
classes => kept_if_else("service_${index}_running", "service_${index}_anomaly", "service_${index}_error"), | |
ifvarclass => "defined_process_name_${index}.(start_process_${index}|(stop_process_${index}.graceful_stop_process_${index}))"; | |
# enforce that the process is stopped gracefully | |
# Should be using process stop, but du to https://cfengine.com/bugtracker/view.php?id=758, it does not work now | |
#"${service[${index}][process]}" | |
# comment => "Stop gracefully the process", | |
# process_stop => "/etc/init.d/${service[${index}][name]} stop", | |
# classes => kept_if_else("service_${index}_already_stopped", "service_${index}_stopped", "service_${index}_error"), | |
# ifvarclass => "defined_process_name_${index}.stop_process_${index}.graceful_stop_process_${index}"; | |
# enforce that the process is stopped not so gracefully | |
"${service[${index}][process]}" | |
comment => "Stop not so gracefully the process", | |
signals => { "${service[${index}][killMethod]}" }, | |
classes => kept_if_else("service_${index}_already_stopped", "service_${index}_stopped", "service_${index}_error"), | |
ifvarclass => "defined_process_name_${index}.stop_process_${index}.(term_stop_process_${index}|kill_stop_process_${index})"; | |
# check the range | |
"${service[${index}][process]}" | |
comment => "Check the range of process", | |
process_count => check_range("${service[${index}][name]}", "${service[${index}][min_instance]}", "${service[${index}][max_instance]}"), | |
ifvarclass => "defined_process_name_${index}.check_process_range_${index}"; | |
commands: | |
"/etc/init.d/${service[${index}][name]}" | |
args => "start", | |
classes => kept_if_else("process_${index}_restart_ok", "process_${index}_restart_ok", "process_${index}_restart_error"), | |
ifvarclass => "process_${index}_restart.start_process_${index}"; | |
"/etc/init.d/${service[${index}][name]}" | |
args => "stop", | |
classes => kept_if_else("process_${index}_stopped_ok", "process_${index}_stopped_ok", "process_${index}_stop_error"), | |
ifvarclass => "!process_${index}_restart.stop_process_${index}"; | |
"/etc/init.d/${service[${index}][name]}" | |
args => "restart", | |
classes => kept_if_else("process_${index}_out_of_range_restart_ok", "process_${index}_out_of_range_restart_ok", "process_${index}_out_of_range_restart_error"), | |
ifvarclass => canonify("${service[${index}][name]}_out_of_range"); | |
# Check whether the service is already configured to start on boot | |
!debian:: # Debian uses a files promise for this, see above | |
"${service_check_boot_status_cmd_${index}}" | |
classes => if_else("service_${index}_bootstarted", "service_${index}_unbootstarted"), | |
ifvarclass => "bootstart_process_${index}|bootstart_prevent_process_${index}", | |
comment => "Check if the service ${service[${index}][name]} is started on boot"; | |
any:: | |
"${service_add_boot_cmd_${index}}" | |
contain => in_shell, | |
classes => if_else("service_${index}_bootstarted_ok", "service_${index}_bootstarted_fail"), | |
ifvarclass => "service_${index}_unbootstarted.bootstart_process_${index}", | |
comment => "Set the service ${service[${index}][name]} to start on boot"; | |
"${service_remove_boot_cmd_${index}}" | |
contain => in_shell, | |
classes => if_else("service_${index}_unbootstarted_ok", "service_${index}_unbootstarted_fail"), | |
ifvarclass => "service_${index}_bootstarted.bootstart_prevent_process_${index}", | |
comment => "Set the service ${service[${index}][name]} to not be started on boot"; | |
reports: | |
cfengine:: | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} didn't need to have its process checked" | |
ifvarclass => "!start_process_${index}.!stop_process_${index}"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Cannot check the status of ${service[${index}][name]}: the process name is not filed" | |
ifvarclass => "!defined_process_name_${index}.(start_process_${index}|stop_process_${index})"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was indeed running" | |
ifvarclass => "service_${index}_running.!service_${index}_anomaly.!process_${index}_restart.start_process_${index}"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was not running and has been restarted" | |
ifvarclass => "process_${index}_restart.process_${index}_restart_ok.start_process_${index}"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]}: the process couldn't be started" | |
ifvarclass => "process_${index}_restart_error"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was indeed not running" | |
ifvarclass => "stop_process_${index}.process_${index}_restart.graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was stopped" | |
ifvarclass => "stop_process_${index}.!process_${index}_restart.process_${index}_stopped_ok.graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]}: the process could't be stopped" | |
ifvarclass => "stop_process_${index}.!process_${index}_restart.process_${index}_stop_error.graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was indeed not running" | |
ifvarclass => "stop_process_${index}.service_${index}_already_stopped.!service_${index}_stopped.!graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Process of ${service[${index}][name]} was stopped" | |
ifvarclass => "stop_process_${index}.service_${index}_stopped.!graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Process@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]}: the process count could't be stopped" | |
ifvarclass => "stop_process_${index}.service_${index}_error.!graceful_stop_process_${index}"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Advanced options@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#The process range is not to be checked for service ${service[${index}][name]}" | |
ifvarclass => "!check_process_range_${index}"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Advanced options@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#The process range for service ${service[${index}][name]} cannot to be checked, for the process name is not set" | |
ifvarclass => "check_process_range_${index}.!defined_process_name_${index}"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Advanced options@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#The process range for service ${service[${index}][name]} is correct" | |
ifvarclass => "check_process_range_${index}.defined_process_name_${index}.!${service[${index}][canon_name]}_out_of_range"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Advanced options@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#The process range for service ${service[${index}][name]} was not correct, but was repaired" | |
ifvarclass => "check_process_range_${index}.defined_process_name_${index}.${service[${index}][canon_name]}_out_of_range.process_${index}_out_of_range_restart_ok"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Advanced options@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#The process range for service ${service[${index}][name]} was not correct, but was repaired" | |
ifvarclass => "check_process_range_${index}.defined_process_name_${index}.${service[${index}][canon_name]}_out_of_range.process_${index}_out_of_range_restart_error"; | |
# Service boot starting parameters | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} starting parameters check not required" | |
ifvarclass => "!bootstart_process_${index}.!bootstart_prevent_process_${index}"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} is started on boot as required" | |
ifvarclass => "bootstart_process_${index}.service_${index}_bootstarted"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} has been set to start on boot" | |
ifvarclass => "bootstart_process_${index}.service_${index}_bootstarted_ok"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Could not set ${service[${index}][name]} to start on boot!" | |
ifvarclass => "bootstart_process_${index}.service_${index}_bootstarted_fail"; | |
"@@ServicesManagement@@result_success@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} is not started on boot as required" | |
ifvarclass => "!bootstart_process_${index}.bootstart_prevent_process_${index}"; | |
"@@ServicesManagement@@result_repaired@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#${service[${index}][name]} has been prevented to start on boot" | |
ifvarclass => "bootstart_prevent_process_${index}.service_${index}_unbootstarted_ok"; | |
"@@ServicesManagement@@result_error@@${service[${index}][uuid]}@@Service starting parameters@@${service[${index}][name]}@@${g.execRun}##${g.uuid}@#Could not prevent ${service[${index}][name]} to start on boot!" | |
ifvarclass => "bootstart_prevent_process_${index}.service_${index}_unbootstarted_fail"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# | |
# Configure the port numbers in the OpenSSH configuration file | |
# The argument can be either a string or a slist | |
# | |
bundle edit_line rudder_openssh_server_port_configuration(portlist) | |
{ | |
delete_lines: | |
"Port.*"; | |
insert_lines: | |
"Port ${portlist}"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################### | |
# Installs SSH, and checks wether it is started on boot or not. | |
############################################################### | |
bundle agent rudder_openssh_server_installation(class_prefix, service_name, params) | |
{ | |
vars: | |
linux.!SuSE:: | |
"rudder_openssh_server_package_name" | |
string => "openssh-server"; | |
SuSE:: | |
"rudder_openssh_server_package_name" | |
string => "openssh"; | |
packages: | |
# Install OpenSSH if needed, using generic installation. | |
linux:: | |
"${rudder_openssh_server_package_name}" | |
package_policy => "add", | |
package_method => generic, | |
classes => rudder_common_classes("${class_prefix}_package"), | |
comment => "Installing ${service_name} using the generic package manager method"; | |
} | |
bundle agent rudder_openssh_server_installation_reporting(class_prefix, service_name, params) | |
{ | |
methods: | |
"any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_package", "${${params}[report]}", "SSH installation", "None", "The ${service_name} package installation"); | |
!linux:: | |
"any" usebundle => rudder_common_report("${service_name}", "result_success", "${${params}[report]}", "SSH installation", "None", "Support to check if ${service_name} is installed not available on this platform"); | |
} | |
# This bundle is common because it defines a class that we reuse in the configuration part, | |
# when configuring the service, to not configure the service if the binary is not there | |
bundle common rudder_openssh_server_check_ssh_installation | |
{ | |
classes: | |
# Security : if not there, SSH too, so do not bother anymore | |
# I cannot use the class_prefix in the class definition, because it is a bundle common | |
# and for some reason, CFEngine complains about it not being canonified | |
"rudder_openssh_server_binary_present" | |
expression => fileexists("/usr/sbin/sshd"); | |
} | |
bundle agent rudder_openssh_server_check_ssh_installation_reporting(class_prefix, service_name, params) | |
{ | |
methods: | |
# Make a report about the lack of proper sshd binary | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_error", "${${params}[report]}", "SSH installation", "None", "The ${service_name} is not installed, although it should have been"), | |
ifvarclass => "!${class_prefix}_binary_present"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
##################################################################################### | |
# This Technique installs and configures OpenSSH. See metadata.xml for more details. | |
##################################################################################### | |
bundle agent rudder_openssh_server | |
{ | |
vars: | |
"rudder_openssh_server_service_name" | |
string => "OpenSSH server"; | |
# Prefix for all the defined classes | |
"rudder_class_prefix" | |
string => "rudder_openssh_server"; | |
# This is the file to edit | |
"rudder_openssh_server_config[sshd_config_file]" | |
string => "&OPENSSH_SERVER_CONFFILE&"; | |
"rudder_openssh_server_config[sshd_config_ports]" | |
slist => {&OPENSSH_SERVER_PORTS: { "&it&" };separator=", "&}; | |
# This is the reporting information to be added | |
"rudder_openssh_server_config[report]" | |
string => "&TRACKINGKEY&"; | |
# Variable that holds if we want to edit ports | |
"rudder_openssh_server_config[edit_ports]" | |
string => "&OPENSSH_SERVER_PORTSEDIT&"; | |
# Class specific parameters | |
rudder_openssh_server_address_family_edit.!(debian_3|redhat_3|redhat_4|centos_3|centos_4):: | |
"rudder_openssh_server_config[config][AddressFamily]" | |
string => "&OPENSSH_SERVER_ADDRESSFAMILY&"; | |
rudder_openssh_server_protocol_edit:: | |
"rudder_openssh_server_config[config][Protocol]" | |
string => "&OPENSSH_SERVER_PROTOCOL&"; | |
rudder_openssh_server_max_sessions_edit.!(redhat|SuSE|debian_3|debian_4):: | |
"rudder_openssh_server_config[config][MaxSessions]" | |
string => "&OPENSSH_SERVER_MAXSESSIONS&"; | |
rudder_openssh_server_challenge_response_authentication_edit:: | |
"rudder_openssh_server_config[config][ChallengeResponseAuthentication]" | |
string => "&OPENSSH_SERVER_CHALLENGERESPONSEAUTHENTICATION&"; | |
rudder_openssh_server_password_authentication_edit:: | |
"rudder_openssh_server_config[config][PasswordAuthentication]" | |
string => "&OPENSSH_SERVER_PASSWORDAUTHENTICATION&"; | |
rudder_openssh_server_pubkey_authentication_edit:: | |
"rudder_openssh_server_config[config][PubkeyAuthentication]" | |
string => "&OPENSSH_SERVER_PUBKEYAUTHENTICATION&"; | |
rudder_openssh_server_permit_empty_passwords_edit:: | |
"rudder_openssh_server_config[config][PermitEmptyPasswords]" | |
string => "&OPENSSH_SERVER_PERMITEMPTYPASSWORDS&"; | |
rudder_openssh_server_permit_root_login_edit:: | |
"rudder_openssh_server_config[config][PermitRootLogin]" | |
string => "&OPENSSH_SERVER_PERMITROOTLOGIN&"; | |
rudder_openssh_server_max_auth_tries_edit.!(debian_3|redhat_3|centos_3):: | |
"rudder_openssh_server_config[config][MaxAuthTries]" | |
string => "&OPENSSH_SERVER_MAXAUTHTRIES&"; | |
rudder_openssh_server_login_grace_time_edit:: | |
"rudder_openssh_server_config[config][LoginGraceTime]" | |
string => "&OPENSSH_SERVER_LOGINGRACETIME&"; | |
rudder_openssh_server_use_privilege_separation_edit:: | |
"rudder_openssh_server_config[config][UsePrivilegeSeparation]" | |
string => "&OPENSSH_SERVER_USEPRIVILEGESEPARATION&"; | |
rudder_openssh_server_strict_modes_edit:: | |
"rudder_openssh_server_config[config][StrictModes]" | |
string => "&OPENSSH_SERVER_STRICTMODES&"; | |
rudder_openssh_server_allow_agent_forwarding_edit.!(redhat|SuSE|debian_3|debian_4):: | |
"rudder_openssh_server_config[config][AllowAgentForwarding]" | |
string => "&OPENSSH_SERVER_ALLOWAGENTFORWARDING&"; | |
rudder_openssh_server_allow_tcp_forwarding_edit:: | |
"rudder_openssh_server_config[config][AllowTcpForwarding]" | |
string => "&OPENSSH_SERVER_ALLOWTCPFORWARDING&"; | |
rudder_openssh_server_permit_tunnel_edit.!(SuSE|debian_3|redhat_3|redhat_4|centos_3|centos_4):: | |
"rudder_openssh_server_config[config][PermitTunnel]" | |
string => "&OPENSSH_SERVER_PERMITTUNNEL&"; | |
rudder_openssh_server_permit_user_environment_edit:: | |
"rudder_openssh_server_config[config][PermitUserEnvironment]" | |
string => "&OPENSSH_SERVER_PERMITUSERENVIRONMENT&"; | |
rudder_openssh_server_x11_forwarding_edit:: | |
"rudder_openssh_server_config[config][X11Forwarding]" | |
string => "&OPENSSH_SERVER_X11FORWARDING&"; | |
rudder_openssh_server_print_lastlog_edit:: | |
"rudder_openssh_server_config[config][PrintLastLog]" | |
string => "&OPENSSH_SERVER_PRINTLASTLOG&"; | |
rudder_openssh_server_printmotd_edit:: | |
"rudder_openssh_server_config[config][PrintMotd]" | |
string => "&OPENSSH_SERVER_PRINTMOTD&"; | |
rudder_openssh_server_tcp_keepalive_edit.!(redhat_3|centos_3):: | |
"rudder_openssh_server_config[config][TCPKeepAlive]" | |
string => "&OPENSSH_SERVER_TCPKEEPALIVE&"; | |
rudder_openssh_server_log_level_edit:: | |
"rudder_openssh_server_config[config][LogLevel]" | |
string => "&OPENSSH_SERVER_LOGLEVEL&"; | |
rudder_openssh_server_syslog_facility_edit:: | |
"rudder_openssh_server_config[config][SyslogFacility]" | |
string => "&OPENSSH_SERVER_SYSLOGFACILITY&"; | |
classes: | |
# AddressFamily edition ? | |
"rudder_openssh_server_address_family_edit" | |
not => strcmp("&OPENSSH_SERVER_ADDRESSFAMILY&","dontchange"); | |
# Protocol edition ? | |
"rudder_openssh_server_protocol_edit" | |
not => strcmp("&OPENSSH_SERVER_PROTOCOL&","dontchange"); | |
# MaxSessions edition ? | |
"rudder_openssh_server_max_sessions_edit" | |
not => strcmp("&OPENSSH_SERVER_MAXSESSIONS&","dontchange"); | |
# ChallengeResponseAuthentication edition ? | |
"rudder_openssh_server_challenge_response_authentication_edit" | |
not => strcmp("&OPENSSH_SERVER_CHALLENGERESPONSEAUTHENTICATION&","dontchange"); | |
# PasswordAuthentication edition ? | |
"rudder_openssh_server_password_authentication_edit" | |
not => strcmp("&OPENSSH_SERVER_PASSWORDAUTHENTICATION&","dontchange"); | |
# PubkeyAuthentication edition ? | |
"rudder_openssh_server_pubkey_authentication_edit" | |
not => strcmp("&OPENSSH_SERVER_PUBKEYAUTHENTICATION&","dontchange"); | |
# PermitEmptyPasswords edition ? | |
"rudder_openssh_server_permit_empty_passwords_edit" | |
not => strcmp("&OPENSSH_SERVER_PERMITEMPTYPASSWORDS&","dontchange"); | |
# PermitRootLogin edition ? | |
"rudder_openssh_server_permit_root_login_edit" | |
not => strcmp("&OPENSSH_SERVER_PERMITROOTLOGIN&","dontchange"); | |
# MaxAuthTries edition ? | |
"rudder_openssh_server_max_auth_tries_edit" | |
not => strcmp("&OPENSSH_SERVER_MAXAUTHTRIES&","dontchange"); | |
# LoginGraceTime edition ? | |
"rudder_openssh_server_login_grace_time_edit" | |
not => strcmp("&OPENSSH_SERVER_LOGINGRACETIME&","dontchange"); | |
# UsePrivilegeSeparation edition ? | |
"rudder_openssh_server_use_privilege_separation_edit" | |
not => strcmp("&OPENSSH_SERVER_USEPRIVILEGESEPARATION&","dontchange"); | |
# StrictModes edition ? | |
"rudder_openssh_server_strict_modes_edit" | |
not => strcmp("&OPENSSH_SERVER_STRICTMODES&","dontchange"); | |
# AllowAgentForwarding edition ? | |
"rudder_openssh_server_allow_agent_forwarding_edit" | |
not => strcmp("&OPENSSH_SERVER_ALLOWAGENTFORWARDING&","dontchange"); | |
# AllowTcpForwarding edition ? | |
"rudder_openssh_server_allow_tcp_forwarding_edit" | |
not => strcmp("&OPENSSH_SERVER_ALLOWTCPFORWARDING&","dontchange"); | |
# PermitTunnel edition ? | |
"rudder_openssh_server_permit_tunnel_edit" | |
not => strcmp("&OPENSSH_SERVER_PERMITTUNNEL&","dontchange"); | |
# PermitUserEnvironment edition ? | |
"rudder_openssh_server_permit_user_environment_edit" | |
not => strcmp("&OPENSSH_SERVER_PERMITUSERENVIRONMENT&","dontchange"); | |
# X11Forwarding edition ? | |
"rudder_openssh_server_x11_forwarding_edit" | |
not => strcmp("&OPENSSH_SERVER_X11FORWARDING&","dontchange"); | |
# PrintLastLog edition ? | |
"rudder_openssh_server_print_lastlog_edit" | |
not => strcmp("&OPENSSH_SERVER_PRINTLASTLOG&","dontchange"); | |
# PrintMotd edition ? | |
"rudder_openssh_server_printmotd_edit" | |
not => strcmp("&OPENSSH_SERVER_PRINTMOTD&","dontchange"); | |
# TCPKeepAlive edition ? | |
"rudder_openssh_server_tcp_keepalive_edit" | |
not => strcmp("&OPENSSH_SERVER_TCPKEEPALIVE&","dontchange"); | |
# LogLevel edition ? | |
"rudder_openssh_server_log_level_edit" | |
not => strcmp("&OPENSSH_SERVER_LOGLEVEL&","dontchange"); | |
# SyslogFacility edition ? | |
"rudder_openssh_server_syslog_facility_edit" | |
not => strcmp("&OPENSSH_SERVER_SYSLOGFACILITY&","dontchange"); | |
# Defines a class to describe we are at the second iteration | |
# When iteration_2 is defined, it means all the variable are defined | |
"iteration_2" | |
expression => "iteration_1"; | |
"iteration_1" | |
expression => "any"; | |
methods: | |
# Note: | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
"any" usebundle => rudder_openssh_server_installation("${rudder_class_prefix}", "${rudder_openssh_server_service_name}", "rudder_openssh_server.rudder_openssh_server_config"); | |
"any" usebundle => rudder_openssh_server_installation_reporting("${rudder_class_prefix}", "${rudder_openssh_server_service_name}", "rudder_openssh_server.rudder_openssh_server_config"); | |
"any" usebundle => rudder_openssh_server_check_ssh_installation(); | |
"any" usebundle => rudder_openssh_server_check_ssh_installation_reporting("${rudder_class_prefix}", "${rudder_openssh_server_service_name}", "rudder_openssh_server.rudder_openssh_server_config"); | |
iteration_2:: | |
"any" usebundle => rudder_openssh_server_configuration("${rudder_class_prefix}", "${rudder_openssh_server_service_name}", "rudder_openssh_server.rudder_openssh_server_config"); | |
"any" usebundle => rudder_openssh_server_configuration_reporting("${rudder_class_prefix}", "${rudder_openssh_server_service_name}", "rudder_openssh_server.rudder_openssh_server_config"); | |
# Warn about features that are not implemented on all platforms | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"address family\" isn't implemented on Red Hat/CentOS/SuSE/Debian 3 and 4"), | |
ifvarclass => "rudder_openssh_server_address_family_edit.(debian_3|redhat_3|redhat_4|centos_3|centos_4)"; | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"maximum authentication attemps per connection\" isn't implemented on Red Hat/CentOS"), | |
ifvarclass => "rudder_openssh_server_max_auth_tries_edit.(redhat_3|centos_3|debian_3)"; | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"agent forwarding\" isn't implemented on Red Hat/CentOS/SuSE/Debian 3 and 4"), | |
ifvarclass => "rudder_openssh_server_allow_agent_forwarding_edit.(redhat|SuSE|debian_3|debian_4)"; | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"max sessions\" isn't implemented on Red Hat/CentOS/SuSE/Debian 3 and 4"), | |
ifvarclass => "rudder_openssh_server_max_sessions_edit.(redhat|SuSE|debian_3|debian_4)"; | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"permit tunnel\" isn't implemented on SuSE/Debian 3/Redhat/CentOS3 and 4"), | |
ifvarclass => "rudder_openssh_server_permit_tunnel_edit.(SuSE|debian_3|redhat_3|redhat_4|centos_3|centos_4)"; | |
"any" | |
usebundle => rudder_common_report("${rudder_openssh_server_service_name}", "log_warn", "&TRACKINGKEY&", "SSH configuration", "None", "The ${rudder_openssh_server_service_name} parameter \"TCP Keep Alive (Time before disconnect)\" isn't implemented on Red Hat/CentOS 3"), | |
ifvarclass => "rudder_openssh_server_tcp_keepalive_edit.(redhat_3|centos_3)"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
##################################################################################### | |
# Configure the OpenSSH server | |
##################################################################################### | |
# If ssh is not installed, install it (linux) | |
# Change the server configuration, and restart the daemon | |
# if the configuration changed | |
# WARNING : You may inadvertently create conflict with processManagement ! | |
# This promise restarts sshd if not there, which could be done by processManagement too. | |
# dontchange is a generic value to prohibit the edition of the value | |
##################################################################################### | |
bundle agent rudder_openssh_server_configuration(class_prefix, service_name, params) { | |
vars: | |
# OS Specific parameters | |
debian:: | |
"rudder_openssh_server_startup_command" | |
string => "/etc/init.d/ssh restart"; | |
"rudder_openssh_server_startup_activation_command" | |
string => "/usr/sbin/update-rc.d -f ssh remove \&\& /usr/sbin/update-rc.d ssh defaults"; | |
SuSE:: | |
"rudder_openssh_server_startup_script_regex" | |
string => "/etc/init.d/rc3.d/S.*ssh.*"; | |
(debian|redhat):: | |
"rudder_openssh_server_startup_script_regex" | |
string => "/etc/rc2.d/S.*ssh.*"; | |
(SuSE|redhat):: | |
"rudder_openssh_server_startup_command" | |
string => "/etc/init.d/sshd restart"; | |
"rudder_openssh_server_startup_activation_command" | |
string => "/sbin/chkconfig --del sshd \&\& /sbin/chkconfig --add sshd"; | |
aix:: | |
"rudder_openssh_server_startup_command" | |
string => "/usr/bin/startsrc -s sshd"; | |
# Here are the details about the arguments given to mkssys: | |
## -p: Specifies the absolute path to the subsystem executable program. | |
## -s: Specifies a name that uniquely identifies the subsystem. | |
## -G: Specifies that the subsystem belongs to the Group specified. | |
## -u: Specifies the user ID for the subsystem. | |
## -S: Specifies that the subsystem uses the signals communication method. | |
## -f: Specifies the signal sent to the subsystem when a forced stop of the subsystem is requested. | |
## -n: Specifies the signal sent to the subsystem when a normal stop of the subsystem is requested. | |
## -a: Specifies any arguments that must be passed to the command, started as the subsystem. | |
## -R: Specifies that the subsystem is restarted if the subsystem stops abnormally. | |
## -Q: Specifies that multiple instances of the subsystem are not allowed to run at the same time. | |
"rudder_openssh_server_startup_activation_command" | |
string => "/usr/bin/mkssys -p /usr/sbin/sshd -s sshd -G ssh -u 0 -S -f 9 -n 15 -a '-D' -R -Q >/dev/null ; /usr/sbin/mkitab 'sshd:2:once:/usr/bin/startsrc -s sshd'"; | |
any:: | |
# Copy the list of Ports in the local bundle | |
# This is mandatory because we cannot use remote slist in CFEngine 3.2 | |
"rudder_openssh_server_config_ports" | |
slist => { "@{${params}[sshd_config_ports]}" }; | |
classes: | |
"rudder_openssh_server_ports_edit" | |
not => strcmp("${${params}[edit_ports]}","false"); | |
aix:: | |
# lssrc is clever, and kept in a cache the entry if the daemon is still running, so grepping | |
# /etc/inittab instead, to be sure that service is defined at boot | |
# Adding scope namespace so that the class is available for the reporting also | |
"${class_prefix}_activated_on_boot_kept" | |
expression => returnszero("/usr/bin/grep -q -E ^sshd: /etc/inittab", "useshell"), | |
scope => "namespace"; | |
files: | |
"${${params}[sshd_config_file]}" | |
edit_line => rudder_common_disclaimer, | |
comment => "Insert the standard Rudder disclaimer in the OpenSSHd configuration file"; | |
(debian|redhat|SuSE):: | |
# This promise will detect if there is a startup script for OpenSSH enabled on the system, | |
# and set a class if there is one indeed. | |
"${rudder_openssh_server_startup_script_regex}" | |
create => "true", | |
action => WarnOnly, | |
classes => if_else("${class_prefix}_activated_on_boot_kept", "${class_prefix}_activation_detection_failed"); | |
rudder_openssh_server_ports_edit:: | |
"${${params}[sshd_config_file]}" | |
edit_line => rudder_openssh_server_port_configuration("@{this.rudder_openssh_server_config_ports}"), | |
classes => rudder_common_classes("${class_prefix}_ports"), | |
comment => "Edit the OpenSSH listening ports in the configuration file"; | |
any:: | |
"${${params}[sshd_config_file]}" | |
edit_line => set_config_values("${params}[config]"), | |
classes => rudder_common_classes("${class_prefix}_configuration"), | |
comment => "Edit the OpenSSH configuration file"; | |
processes: | |
any:: | |
"/usr/sbin/sshd" | |
restart_class => "${class_prefix}_down", | |
comment => "Checking whether OpenSSH is up or not"; | |
commands: | |
debian|redhat|SuSE|aix:: | |
"${rudder_openssh_server_startup_command}" | |
classes => cf2_if_else("${class_prefix}_daemon_restart_repaired", "${class_prefix}_daemon_restart_error"), | |
ifvarclass => "${class_prefix}_ports_repaired|${class_prefix}_configuration_repaired|${class_prefix}_down", | |
comment => "Restarting the OpenSSH server daemon"; | |
debian|redhat|SuSE|aix:: | |
"${rudder_openssh_server_startup_activation_command}" | |
contain => in_shell, | |
classes => cf2_if_else("${class_prefix}_activated_on_boot_repaired", "${class_prefix}_activated_on_boot_error"), | |
ifvarclass => "(!${class_prefix}_activated_on_boot_kept).${class_prefix}_binary_present", | |
comment => "Adding the OpenSSH daemon to the startup scripts"; | |
} | |
bundle agent rudder_openssh_server_configuration_reporting(class_prefix, service_name, params) | |
{ | |
methods: | |
# Port edition defined | |
"any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_ports", "${${params}[report]}", "SSH port configuration", "None", "The ${service_name} port configuration"), | |
ifvarclass => "${class_prefix}_ports_edit"; | |
# When no port edition is defined | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_success", "${${params}[report]}", "SSH port configuration", "None", "The ${service_name} port configuration is not set to be edited"), | |
ifvarclass => "!${class_prefix}_ports_edit"; | |
# SSH configuration | |
"any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_configuration", "${${params}[report]}", "SSH configuration", "None", "The ${service_name} configuration"); | |
# SSH start on boot | |
"any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_activated_on_boot", "${${params}[report]}", "SSH start at boot", "None", "The ${service_name} boot starting configuration"); | |
"any" | |
usebundle => rudder_common_report("${service_name}", "log_repaired", "${${params}[report]}", "SSH process", "None", "The ${service_name} was not running, trying to restart..."), | |
ifvarclass => "${class_prefix}_down"; | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_success", "${${params}[report]}", "SSH process", "None", "The ${service_name} service is running"), | |
ifvarclass => "!${class_prefix}_down.!${class_prefix}_daemon_restart_repaired.!${class_prefix}_daemon_restart_error"; | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_repaired", "${${params}[report]}", "SSH process", "None", "Restarted the ${service_name}"), | |
ifvarclass => "${class_prefix}_daemon_restart_repaired.!${class_prefix}_daemon_restart_error"; | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_error", "${${params}[report]}", "SSH process", "None", "Could not restart the ${service_name}"), | |
ifvarclass => "${class_prefix}_daemon_restart_error"; | |
"any" | |
usebundle => rudder_common_report("${service_name}", "log_info", "${${params}[report]}", "SSH start at boot", "None", "Error checking if the ${service_name} is set to be started on boot"), | |
ifvarclass => "${class_prefix}_activation_detection_failed"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
# Copyright (C) Normation | |
bundle agent check_ssh_key_distribution | |
{ | |
vars: | |
any:: | |
"technique_name" string => "sshKeyDistribution"; | |
"component_name" string => "SSH key"; | |
"config_basename" string => "authorized_keys"; | |
&SSH_KEY_DISTRIBUTION_TAG:{key_tag |"sshkey_distribution_tag[&i&]" string => "&key_tag&"; | |
}& | |
&SSH_KEY_DISTRIBUTION_NAME:{distribution_name |"sshkey_distribution_name[&i&]" string => "&distribution_name&"; | |
}& | |
&SSH_KEY_DISTRIBUTION_KEY:{distribution_key |"sshkey_distribution_key[&i&]" string => "&distribution_key&"; | |
}& | |
&SSH_KEY_DISTRIBUTION_EDIT_TYPE:{distribution_edit_type |"sshkey_distribution_edit_type[&i&]" string => "&distribution_edit_type&"; | |
}& | |
&TRACKINGKEY:{uuid |"sshkey_distribution_uuid[&i&]" string => "&uuid&"; | |
}& | |
"sshkey_distribution_index" | |
slist => getindices("sshkey_distribution_name"); | |
"no_${sshkey_distribution_index}" | |
int => parsestringarray("userarray_${sshkey_distribution_index}", "${userdata_${sshkey_distribution_index}}", "", ":", "1000", "200000" ); | |
"key_class_prefix[${sshkey_distribution_index}]" | |
string => canonify("${sshkey_distribution_tag[${sshkey_distribution_index}]}_${sshkey_distribution_uuid[${sshkey_distribution_index}]}"); | |
"homedir[${sshkey_distribution_index}]" | |
string => "${userarray_${sshkey_distribution_index}[${sshkey_distribution_name[${sshkey_distribution_index}]}][5]}"; | |
# Only Linuxes (not Slackware), Solaris and FreeBSD support PAM/getent | |
(linux.!slackware)|solaris|freebsd:: | |
"userdata_${sshkey_distribution_index}" | |
string => execresult("/usr/bin/getent passwd ${sshkey_distribution_name[${sshkey_distribution_index}]}", "noshell"); | |
# On systems without PAM, directly read entries from /etc/passwd instead (compatibility) | |
!((linux.!slackware)|solaris|freebsd):: | |
"userdata_${sshkey_distribution_index}" | |
string => execresult("/usr/bin/grep ^${sshkey_distribution_name[${sshkey_distribution_index}]}: /etc/passwd", "noshell"); | |
any:: | |
"gid[${sshkey_distribution_index}]" | |
string => "${userarray_${sshkey_distribution_index}[${sshkey_distribution_name[${sshkey_distribution_index}]}][3]}"; | |
classes: | |
"begin_evaluation" expression => isvariable("sshkey_distribution_index"); | |
begin_evaluation:: | |
"user_${sshkey_distribution_index}_exists" expression => userexists("${sshkey_distribution_name[${sshkey_distribution_index}]}"); | |
files: | |
!windows:: | |
"${homedir[${sshkey_distribution_index}]}/.ssh/." | |
create => "true", | |
ifvarclass => canonify("user_${sshkey_distribution_index}_exists"), | |
perms => mog("700", "${sshkey_distribution_name[${sshkey_distribution_index}]}", "${gid[${sshkey_distribution_index}]}"); | |
"${homedir[${sshkey_distribution_index}]}/.ssh/${config_basename}" | |
create => "true", | |
edit_defaults => rudder_empty_select("${sshkey_distribution_edit_type[${sshkey_distribution_index}]}"), | |
perms => mog("600", "${sshkey_distribution_name[${sshkey_distribution_index}]}", "${gid[${sshkey_distribution_index}]}"), | |
edit_line => append_or_replace_ssh_key("${sshkey_distribution_key[${sshkey_distribution_index}]}", "${sshkey_distribution_index}"), | |
ifvarclass => canonify("user_${sshkey_distribution_index}_exists"), | |
classes => rudder_common_classes("${key_class_prefix[${sshkey_distribution_index}]}"); | |
methods: | |
!windows:: | |
"SSH Key Report" | |
ifvarclass => "user_${sshkey_distribution_index}_exists", | |
usebundle => rudder_common_reports_generic( | |
"${technique_name}", "${key_class_prefix[${sshkey_distribution_index}]}", | |
"${sshkey_distribution_uuid[${sshkey_distribution_index}]}", "${component_name}", "${sshkey_distribution_tag[${sshkey_distribution_index}]}", | |
"SSH key \"${sshkey_distribution_tag[${sshkey_distribution_index}]}\" for user ${sshkey_distribution_name[${sshkey_distribution_index}]}" | |
); | |
"No User Exist Report" | |
ifvarclass => "!user_${sshkey_distribution_index}_exists", | |
usebundle => rudder_common_report( | |
"${technique_name}", "result_error", | |
"${sshkey_distribution_uuid[${sshkey_distribution_index}]}", "${component_name}", "${sshkey_distribution_tag[${sshkey_distribution_index}]}", | |
"The user ${sshkey_distribution_name[${sshkey_distribution_index}]} does NOT exist on this machine, not adding SSH key" | |
); | |
windows:: | |
"No Windows Support Report" | |
usebundle => rudder_common_report( | |
"${technique_name}", "result_error", | |
"${sshkey_distribution_uuid[${sshkey_distribution_index}]}", "${component_name}", "${sshkey_distribution_tag[${sshkey_distribution_index}]}", | |
"Unable to add a SSH key for ${sshkey_distribution_name[${sshkey_distribution_index}]}: This Technique does not support Windows" | |
); | |
} | |
# authorized_keys file contains one line per key, in the following format: | |
# (optional-options\s)(<keytype>)\s(the_key=)(\soptional-comment) | |
# where | |
# - keytype is one of ssh-rsa or ssh-dss | |
# - key value ends with "=" | |
# - no spaces are allowed in options, except in double-quoted strings | |
# | |
bundle edit_line append_or_replace_ssh_key(keyspec, index) | |
{ | |
vars: | |
any:: | |
"eline" | |
comment => "An escaped version of the keyspec - \Q..\E do not escape everything", | |
string => escape("${keyspec}"); | |
key_parsed:: | |
"ckey" string => canonify("${keybits[3]}"); | |
"ekey" string => escape("${keybits[3]}"); | |
classes: | |
"key_parsed" | |
# If the key hash happens to exceed 1000 chars $keybits[3] is going to be undefined because | |
# of some weird cfengine bugs, probably this one: https://cfengine.com/dev/issues/1258 | |
# Therefore we limit the regex to extract as much of the hash as possible to make it unique enough | |
# without exceeding 1000 charachter limit. | |
# The hashes of that length apparently correspond to DSS 2048 bits keys, generated i.e. on rhel 4, | |
# with openssh v3.9p1-redhat. I believe that since openssh v4 DSS bitlengh is limited to 1024, | |
# as required by FIPS. | |
expression => regextract("(.*\s+)?(ssh-rsa|ssh-dss)\s+(\S{1,1000})\S*(\s+.+)?\Z", "${keyspec}", "keybits" ); | |
insert_lines: | |
"${keyspec}" | |
# NOTE: this is only to ensure that insert is attempted *after* the replace, | |
# as normally insert step precedes the replace, see | |
# (https://cfengine.com/docs/3.5/manuals-language-concepts-normal-ordering.html) | |
ifvarclass => canonify("ssh_key_distribution_replace_step_attempted_${index}"); | |
replace_patterns: | |
"^(?!${eline}$)(.*${ekey}.*)$" | |
comment => "Replace a key here", | |
replace_with => value("${keyspec}"), | |
ifvarclass => "key_parsed", | |
classes => always("ssh_key_distribution_replace_step_attempted_${index}"); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent file_alteration_monitor | |
{ | |
vars: | |
&MONITOR_ENTITY_NAME:{name |"monitor_entity[&i&][name]" string => "&name&"; | |
}& | |
&TRACKINGKEY:{uuid |"monitor_entity[&i&][uuid]" string => "&uuid&"; | |
}& | |
"index" slist => getindices("monitor_entity"); | |
classes: | |
"isfile_${index}" expression => isplain("${monitor_entity[${index}][name]}"); | |
"isdir_${index}" expression => isdir("${monitor_entity[${index}][name]}"); | |
files: | |
"${monitor_entity[${index}][name]}" | |
ifvarclass => "isdir_${index}", | |
changes => detect_all_change, | |
classes => kept_if_else("${index}_kept", "${index}_changed", "${index}_error"), | |
depth_search => recurse("inf"); | |
"${monitor_entity[${index}][name]}" | |
ifvarclass => "isfile_${index}", | |
changes => detect_all_change, | |
classes => kept_if_else("${index}_kept", "${index}_changed", "${index}_error"); | |
reports: | |
cfengine:: | |
"@@fileAlterationMonitoring@@result_success@@${monitor_entity[${index}][uuid]}@@File or directory to monitor@@${monitor_entity[${index}][name]}@@${g.execRun}##${g.uuid}@#The content of ${monitor_entity[${index}][name]} is consistent" | |
ifvarclass => "${index}_kept"; | |
"@@fileAlterationMonitoring@@result_repaired@@${monitor_entity[${index}][uuid]}@@File or directory to monitor@@${monitor_entity[${index}][name]}@@${g.execRun}##${g.uuid}@#The content of ${monitor_entity[${index}][name]} is INCONSISTENT: Either the file has changed or one of the elements in the directory has" | |
ifvarclass => "${index}_changed"; | |
"@@fileAlterationMonitoring@@result_error@@${monitor_entity[${index}][uuid]}@@File or directory to monitor@@${monitor_entity[${index}][name]}@@${g.execRun}##${g.uuid}@#The content of ${monitor_entity[${index}][name]} could not be checked" | |
ifvarclass => "${index}_error"; | |
"@@fileAlterationMonitoring@@result_error@@${monitor_entity[${index}][uuid]}@@File or directory to monitor@@${monitor_entity[${index}][name]}@@${g.execRun}##${g.uuid}@#The entity ${monitor_entity[${index}][name]} does not exist: alteration monitoring impossible" | |
ifvarclass => "!isdir_${index}.!isfile_${index}"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# Author : Matthieu CERDA | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
bundle agent check_cron_configuration | |
{ | |
vars: | |
&CRON_NAME:{cron_name |"cron_name[&i&]" string => "&cron_name&"; | |
}& | |
&CRON_COMMAND:{cron_command |"cron_command[&i&]" string => "&cron_command&"; | |
}& | |
&CRON_USER:{cron_user |"cron_user[&i&]" string => "&cron_user&"; | |
}& | |
&CRON_FREQUENCY:{cron_frequency |"cron_frequency[&i&]" string => "&cron_frequency&"; | |
}& | |
&CRON_MANUAL:{cron_manual |"cron_manual[&i&]" string => "&cron_manual&"; | |
}& | |
&TRACKINGKEY:{uuid |"cron_uuid[&i&]" string => "&uuid&"; | |
}& | |
"cron_index" slist => getindices("cron_name"); | |
"normalorderingtwist" string => "done"; | |
redhat:: | |
"cron_bin" string => "crond$"; | |
"cron_restartcmd" string => "/etc/init.d/crond restart"; | |
ubuntu:: | |
"cron_bin" string => "cron$"; | |
"cron_restartcmd" string => "/etc/init.d/cron restart"; | |
!(redhat|ubuntu):: | |
"cron_bin" string => "/usr/sbin/cron$"; | |
"cron_restartcmd" string => "/etc/init.d/cron restart"; | |
classes: | |
"crontab_absent" not => fileexists("/etc/crontab"); | |
"normalorderingtwist" expression => strcmp("${normalorderingtwist}", "done"); | |
normalorderingtwist:: | |
"${cron_index}_manual" expression => strcmp("${cron_frequency[${cron_index}]}", "d"); | |
"showtime" expression => strcmp("true", "true"); | |
files: | |
showtime:: | |
"/etc/cron.d/${cron_name[${cron_index}]}" | |
create => "true", | |
edit_defaults => empty_backup, | |
perms => mog("644", "root", "root"), | |
edit_line => insert_lines("${cron_manual[${cron_index}]} ${cron_user[${cron_index}]} ${cron_command[${cron_index}]}"), | |
ifvarclass => "${cron_index}_manual", | |
classes => kept_if_else("cron_file_${cron_index}_kept", "cron_file_${cron_index}_edited", "cron_file_${cron_index}_failed"); | |
"/etc/cron.${cron_frequency[${cron_index}]}/${cron_name[${cron_index}]}" | |
create => "true", | |
edit_defaults => empty_backup, | |
perms => mog("755", "root", "root"), | |
edit_line => insert_lines("${cron_command[${cron_index}]}"), | |
ifvarclass => "!${cron_index}_manual", | |
classes => kept_if_else("cron_file_${cron_index}_kept", "cron_file_${cron_index}_edited", "cron_file_${cron_index}_failed"); | |
processes: | |
"${cron_bin}" | |
restart_class => "cron_restart"; | |
commands: | |
cron_restart:: | |
"${cron_restartcmd}" | |
args => "restart", | |
classes => kept_if_else("cron_kept", "cron_restarted", "could_not_restart_cron"), | |
comment => "Restart the cron daemon"; | |
reports: | |
!windows:: | |
# Reports about the creation of the cron entries | |
"@@cronConfiguration@@result_success@@${cron_uuid[${cron_index}]}@@Cron entry@@${cron_name[${cron_index}]}@@${g.execRun}##${g.uuid}@#The cron file ${cron_name[${cron_index}]} was present. Skipping..." | |
ifvarclass => "cron_file_${cron_index}_kept.!cron_file_${cron_index}_edited"; | |
"@@cronConfiguration@@result_repaired@@${cron_uuid[${cron_index}]}@@Cron entry@@${cron_name[${cron_index}]}@@${g.execRun}##${g.uuid}@#The cron file ${cron_name[${cron_index}]} was created successfully" | |
ifvarclass => "cron_file_${cron_index}_edited"; | |
"@@cronConfiguration@@result_error@@${cron_uuid[${cron_index}]}@@Cron entry@@${cron_name[${cron_index}]}@@${g.execRun}##${g.uuid}@#Could not create the cron file ${cron_name[${cron_index}]}" | |
ifvarclass => "cron_file_${cron_index}_failed"; | |
# Reports about the cron process presence | |
!cron_restart:: | |
"@@cronConfiguration@@result_success@@${cron_uuid[${cron_index}]}@@Cron process@@None@@${g.execRun}##${g.uuid}@#The cron process is running. Skipping..."; | |
cron_restarted:: | |
"@@cronConfiguration@@result_repaired@@${cron_uuid[${cron_index}]}@@Cron process@@None@@${g.execRun}##${g.uuid}@#The cron process has been restarted"; | |
could_not_restart_cron:: | |
"@@cronConfiguration@@result_success@@${cron_uuid[${cron_index}]}@@Cron process@@None@@${g.execRun}##${g.uuid}@#Could not restart the cron process!"; | |
!windows.cron_absent:: | |
"@@cronConfiguration@@log_warn@@${cron_uuid[${cron_index}]}@@cronConfiguration@@None@@${g.execRun}##${g.uuid}@#The crontab is absent"; | |
windows:: | |
"@@cronConfiguration@@result_error@@${cron_uuid[${cron_index}]}@@cronConfiguration@@None@@${g.execRun}##${g.uuid}@#This is a Windows machine. This Technique currently incompatible with it"; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Fstab configuration PT # | |
# ---------------------------------------------------------------------- # | |
# Objective : Configure /etc/fstab according to the given parameters # | |
########################################################################## | |
bundle agent check_fstab_configuration | |
{ | |
vars: | |
&FSTAB_ORIGIN:{origin |"fstab[&i&][origin]" string => "&origin&"; | |
}& | |
&FSTAB_MOUNT_SELECTOR:{selector |"fstab[&i&][selector]" string => "&selector&"; | |
}& | |
&FSTAB_DESTINATION:{destination |"fstab[&i&][destination]" string => "&destination&"; | |
}& | |
&FSTAB_FILESYSTEM:{filesystem |"fstab[&i&][filesystem]" string => "&filesystem&"; | |
}& | |
&FSTAB_DEFAULTS, FSTAB_ASYNC, FSTAB_ATIME, FSTAB_NOAUTO, FSTAB_DEV, FSTAB_EXEC, FSTAB_SUID, FSTAB_USER, FSTAB_USERS, FSTAB_GROUP, FSTAB_MAND, FSTAB_NETDEV, FSTAB_OWNER, FSTAB_READWRITE, FSTAB_MISCOPTIONS: {defaults, async, atime, noauto, dev, exec, suid, user, users, group, mand, netdev, owner, readwrite, miscoptions | "fstab_raw_options_&i&" slist => { "&defaults&", "&async&", "&atime&", "&noauto&", "&dev&", "&exec&", "&suid&", "&user&", "&users&", "&group&", "&mand&", "&netdev&", "&owner&", "&readwrite&", "&miscoptions&" }; | |
}& | |
&FSTAB_DUMP:{dump |"fstab[&i&][dump]" string => "&dump&"; | |
}& | |
&FSTAB_FSCKORDER:{fsckorder |"fstab[&i&][fsckorder]" string => "&fsckorder&"; | |
}& | |
&FSTAB_ALTERONLY:{alteronly |"fstab_alteronly[&i&]" string => "&alteronly&"; | |
}& | |
&TRACKINGKEY:{uuid |"fstab[&i&][uuid]" string => "&uuid&"; | |
}& | |
# We create an index of every fstab entry we will add ( this will be 1, 2, 3 ... ) | |
"fstab_index" slist => getindices("fstab"); | |
# We create a clean list of options : we list them, remove the blanks and join them as a plain string | |
"fstab_filtered_options_${fstab_index}" slist => grep(".+","fstab_raw_options_${fstab_index}"); | |
"fstab[${fstab_index}][options]" string => join(",", "fstab_filtered_options_${fstab_index}"); | |
# We prepare an array defining the order of the statements in the files ( required by the edit field as seen below ) | |
"fields[destination]" string => "2"; | |
"fields[filesystem]" string => "3"; | |
"fields[options]" string => "4"; | |
"fields[dump]" string => "5"; | |
"fields[fsckorder]" string => "6"; | |
files: | |
!windows:: | |
"/etc/fstab" | |
edit_line => fstab_add_line("check_fstab_configuration.fstab", "check_fstab_configuration.fields", "check_fstab_configuration.fstab_alteronly"), | |
create => "true", | |
edit_defaults => noempty_backup, | |
perms => mog("0644", "root", "root"), | |
classes => kept_if_else("fstab_kept", "fstab_edited", "fstab_failed"), | |
comment => "Editing the fstab file"; | |
reports: | |
fstab_kept.!fstab_edited:: | |
"@@fstabConfiguration@@log_info@@${fstab[${fstab_index}][uuid]}@@fstabConfiguration@@None@@${g.execRun}##${g.uuid}@#The fstab file was in accordance with the required policy"; | |
fstab_edited:: | |
"@@fstabConfiguration@@log_info@@${fstab[${fstab_index}][uuid]}@@fstabConfiguration@@None@@${g.execRun}##${g.uuid}@#The fstab file was edited by at least one instance of this technique"; | |
fstab_failed:: | |
"@@fstabConfiguration@@log_warn@@${fstab[${fstab_index}][uuid]}@@fstabConfiguration@@None@@${g.execRun}##${g.uuid}@#The fstab file could NOT be edited by at least one instance of this technique!"; | |
&if(NOVA)& | |
windows:: | |
"@@fstabConfiguration@@result_error@@${fstab[${fstab_index}][uuid]}@@fstabConfiguration@@None@@${g.execRun}##${g.uuid}@#The fstabConfiguration Technique is not intended to be run on windows. Skipping."; | |
&endif& | |
} | |
bundle edit_line fstab_add_line(data_array, fields, alteronly) | |
{ | |
vars: | |
"index" slist => getindices("${data_array}"); | |
"indices_fields" slist => getindices("${fields}"); | |
classes: | |
"addentry_${index}" expression => strcmp("${${alteronly}[${index}]}", "false"); | |
"delentry_${index}" expression => strcmp("${${alteronly}[${index}]}", "delete"); | |
"empty_origin_${index}" expression => strcmp("${${data_array}[${index}][origin]}", ""); | |
"use_origin_${index}" expression => strcmp("${${data_array}[${index}][selector]}", "origin"); | |
# Cannot handle an addition without the origin, nor handle a reference on the origin if there aren't any | |
"invalid_${index}" expression => "empty_origin_${index}.(use_origin_${index}|addentry_${index})"; | |
delete_lines: | |
"^${${data_array}[${index}][origin]}[ \t]+.*" | |
ifvarclass => "delentry_${index}.use_origin_${index}.!invalid_${index}", | |
classes => kept_if_else("line_${index}_kept", "line_${index}_handled", "line_${index}_handle_failed"); | |
"^[^#]+[ \t]+${${data_array}[${index}][destination]}[ \t]+.*" | |
ifvarclass => "delentry_${index}.!use_origin_${index}", | |
classes => kept_if_else("line_${index}_kept", "line_${index}_handled", "line_${index}_handle_failed"); | |
field_edits: | |
"^${${data_array}[${index}][origin]}[ \t].*" | |
edit_field => fstab_col("[ \t]+","${${fields}[${indices_fields}]}","${${data_array}[${index}][${indices_fields}]}","set"), | |
classes => kept_if_else("line_${index}_kept", "line_${index}_handled", "line_${index}_handle_failed"), | |
ifvarclass => "use_origin_${index}.!invalid_${index}"; | |
"^[^#]*[ \t]${${data_array}[${index}][destination]}[ \t].*" | |
edit_field => fstab_col("[ \t]+","${${fields}[${indices_fields}]}","${${data_array}[${index}][${indices_fields}]}","set"), | |
classes => kept_if_else("line_${index}_kept", "line_${index}_handled", "line_${index}_handle_failed"), | |
ifvarclass => "!use_origin_${index}"; | |
insert_lines: | |
"${${data_array}[${index}][origin]} ${${data_array}[${index}][destination]} ${${data_array}[${index}][filesystem]} ${${data_array}[${index}][options]} ${${data_array}[${index}][dump]} ${${data_array}[${index}][fsckorder]}" | |
ifvarclass => "addentry_${index}.!line_${index}_handled.!invalid_${index}", | |
classes => kept_if_else("line_${index}_kept", "line_${index}_handled", "line_${index}_handle_failed"); | |
reports: | |
cfengine:: | |
"@@fstabConfiguration@@result_error@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][destination]} is invalid, for it doesn't contain an origin : how can it be updated/inserted/deleted?" | |
ifvarclass => "invalid_${index}"; | |
"@@fstabConfiguration@@result_repaired@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][origin]} to ${${data_array}[${index}][destination]} has been handled" | |
ifvarclass => "line_${index}_handled"; | |
"@@fstabConfiguration@@result_success@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][origin]} to ${${data_array}[${index}][destination]} is already in accordance with the policy" | |
ifvarclass => "line_${index}_kept.!line_${index}_handled.!empty_origin_${index}"; | |
"@@fstabConfiguration@@result_success@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][destination]} contained the proper fields" | |
ifvarclass => "line_${index}_kept.!line_${index}_handled.empty_origin_${index}"; | |
"@@fstabConfiguration@@result_error@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][origin]} to ${${data_array}[${index}][destination]} could not be handled" | |
ifvarclass => "line_${index}_handle_failed"; | |
"@@fstabConfiguration@@result_success@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][origin]} to ${${data_array}[${index}][destination]} was not present but policy required alteration only. This line will be ignored" | |
ifvarclass => "!addentry_${index}.!line_${index}_handled.!line_${index}_kept.!line_${index}_handle_failed.use_origin_${index}"; | |
"@@fstabConfiguration@@result_success@@${${data_array}[${index}][uuid]}@@fstabConfiguration@@${${data_array}[${index}][destination]}@@${g.execRun}##${g.uuid}@#The entry for ${${data_array}[${index}][destination]} was not present but policy required alteration only. This line will be ignored" | |
ifvarclass => "!addentry_${index}.!line_${index}_handled.!line_${index}_kept.!line_${index}_handle_failed.!use_origin_${index}"; | |
} | |
# Workaround for https://dev.cfengine.com/issues/6467 | |
body edit_field fstab_col(split,col,newval,method) | |
{ | |
field_separator => "${split}"; | |
select_field => "${col}"; | |
value_separator => ";"; | |
field_value => "${newval}"; | |
field_operation => "${method}"; | |
extend_fields => "true"; | |
allow_blank_fields => "true"; | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################################## | |
# This Technique configures a machine MOTD. See metadata.xml for more details. | |
############################################################################## | |
bundle agent rudder_motd | |
{ | |
vars: | |
"rudder_motd_service_name" string => "MOTD"; | |
# Prefix for all the defined classes | |
"rudder_motd_class_prefix" string => "rudder_motd"; | |
"rudder_motd_config[payload]" string => "&MOTD&"; | |
"rudder_motd_config[location]" string => "&MOTD_LOCATION&"; | |
"rudder_motd_config[file_empty]" string => "&MOTD_EMPTY&"; | |
"rudder_motd_config[trackingkey]" string => "&TRACKINGKEY&"; | |
methods: | |
# Note: | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
"any" usebundle => rudder_motd_configuration("${rudder_motd_class_prefix}", "${rudder_motd_service_name}", "${rudder_motd_config[trackingkey]}", "rudder_motd.rudder_motd_config"); | |
"any" usebundle => rudder_motd_configuration_reporting("${rudder_motd_class_prefix}", "${rudder_motd_service_name}", "${rudder_motd_config[trackingkey]}"); | |
} | |
##################################################################################### | |
# Copyright 2011-2013 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
############################################################## | |
# Sets the MOTD according to the value given in the Directive. | |
############################################################## | |
bundle agent rudder_motd_configuration(class_prefix, service_name, trackingkey, params) | |
{ | |
vars: | |
"rudder_motd_payload" string => "${${params}[payload]}"; | |
"rudder_motd_location" string => "${${params}[location]}"; | |
"rudder_motd_empty" string => "${${params}[file_empty]}"; | |
debian:: | |
"rudder_motd_file" slist => { "/etc/motd", "/etc/motd.tail" }; | |
!debian:: | |
"rudder_motd_file" slist => { "/etc/motd" }; | |
aix:: | |
"rudder_motd_group" string => "bin"; | |
!aix:: | |
"rudder_motd_group" string => "root"; | |
classes: | |
"rudder_motd_absent" not => fileexists("/etc/motd"); | |
files: | |
# Set every MOTD file to the wanted value | |
!windows:: | |
"${rudder_motd_file}" | |
create => "true", | |
edit_defaults => rudder_empty_select("${rudder_motd_empty}"), | |
perms => mog("644", "root", "${rudder_motd_group}"), | |
edit_line => rudder_line_insertion("${rudder_motd_payload}", "${rudder_motd_location}"), | |
classes => rudder_common_classes("${class_prefix}_file_edition"); | |
methods: | |
# Here, we will define reports for elements which only have a local visibility (like the MOTD file presence detection). | |
!windows.rudder_motd_absent:: | |
"any" | |
usebundle => rudder_common_report("${service_name}", "log_repaired", "${trackingkey}", "MOTD Configuration", "None", "The ${service_name} file was absent, it will be created"); | |
&if(NOVA)& | |
databases: | |
windows:: | |
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" | |
database_operation => "create", | |
database_rows => { "legalnoticecaption,REG_SZ,Notice"}, | |
database_type => "ms_registry", | |
comment => "Editing the windows registry"; | |
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" | |
database_operation => "create", | |
database_rows => { "legalnoticetext,REG_SZ,${rudder_motd_payload}"}, | |
database_type => "ms_registry", | |
comment => "Editing the windows registry", | |
classes => rudder_common_classes("${class_prefix}_file_edition"); | |
&endif& | |
} | |
# The reporting is made on separate bundles to abstract the complexity | |
# inherent to the normal ordering. | |
bundle agent rudder_motd_configuration_reporting(class_prefix, service_name, trackingkey) | |
{ | |
methods: | |
"any" usebundle => rudder_common_reports_generic("${service_name}", "${class_prefix}_file_edition", "${trackingkey}", "MOTD Configuration", "None", "The ${service_name} file"); | |
windows:: | |
"any" | |
usebundle => rudder_common_report("${service_name}", "result_error", "${trackingkey}", "MOTD Configuration", "None", "This is a Windows machine. This Technique currently incompatible with it"); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Group management PT # | |
# # | |
# Objective : Apply group policies on the target host # | |
########################################################################## | |
# I was forced to truncate brutally the name, as on CF3 3.1.4 more than 32 chars on the bundle name leads to arrays corruption | |
bundle agent check_usergroup_grp_parameters { | |
vars: | |
&USERGROUP_GROUP_NAME:{name |"usergroup_group_name[&i&]" string => "&name&"; | |
}& | |
&USERGROUP_GROUP_CREATE:{create |"usergroup_group_create[&i&]" string => "&create&"; | |
}& | |
&USERGROUP_GROUP_SET_GID:{setgid |"usergroup_group_set_gid[&i&]" string => "&setgid&"; | |
}& | |
&USERGROUP_GROUP_GID:{gid |"usergroup_group_gid[&i&]" string => "&gid&"; | |
}& | |
&USERGROUP_GROUP_ENFORCE_CONTENT:{enforce_content |"usergroup_group_enforce_content[&i&]" string => "&enforce_content&"; | |
}& | |
&USERGROUP_GROUP_CONTENT:{content |"usergroup_group_content[&i&]" string => "&content&"; | |
}& | |
&USERGROUP_GROUP_POLICY:{policy |"usergroup_group_policy[&i&]" string => "&policy&"; | |
}& | |
&TRACKINGKEY:{directiveId |"usergroup_group_directive_id[&i&]" string => "&directiveId&"; | |
}& | |
"usergroup_group_index" slist => getindices("usergroup_group_name"); | |
methods: | |
"any" | |
usebundle => check_usergroup_group_parameters_grouphandle("${usergroup_group_name[${usergroup_group_index}]}", "${usergroup_group_create[${usergroup_group_index}]}", "${usergroup_group_set_gid[${usergroup_group_index}]}", "${usergroup_group_gid[${usergroup_group_index}]}","${usergroup_group_enforce_content[${usergroup_group_index}]}", "${usergroup_group_content[${usergroup_group_index}]}", "${usergroup_group_index}", "${usergroup_group_directive_id[${usergroup_group_index}]}"); | |
} | |
bundle agent check_usergroup_group_parameters_grouphandle(name, create, setgid, gid, enforce_content, content, index, directiveId) { | |
vars: | |
"userlist" slist => splitstring("${content}",",","16"); | |
classes: | |
"groupmanagement_group_${index}_absent" not => groupexists("${name}"); | |
"groupmanagement_group_${index}_create" expression => strcmp("${create}", "true"); | |
"groupmanagement_group_${index}_setgid" expression => strcmp("${setgid}", "true"); | |
"groupmanagement_group_${index}_enforce_content" expression => strcmp("${enforce_content}", "true"); | |
files: | |
# Enforce group content on if groupmanagement_group_${index}_enforce_content is set | |
"/etc/group" | |
edit_line => groups_file_append("${name}", "@(check_usergroup_group_parameters_grouphandle.userlist)"), | |
edit_defaults => noempty_backup, | |
classes => rudder_common_classes("groupmanagement_group_add_${index}"), | |
ifvarclass => "groupmanagement_group_${index}_enforce_content.(!groupmanagement_group_${index}_absent|groupmanagement_group_add_${index}_repaired)", | |
comment => "Set users on the group ${name} only if the group is already present"; | |
# Enforce GID if setgid has been set | |
"/etc/group" | |
create => "false", | |
edit_line => set_user_field("${name}", 3, "${gid}"), | |
classes => rudder_common_classes("groupmanagement_group_gid_${index}"), | |
ifvarclass => "!groupmanagement_group_${index}_absent.groupmanagement_group_${index}_setgid"; | |
commands: | |
"/usr/sbin/groupadd" | |
args => "-f \"${name}\"", | |
classes => if_else("groupmanagement_group_add_${index}_repaired", "groupmanagement_group_add_${index}_error"), | |
ifvarclass => "groupmanagement_group_${index}_absent.groupmanagement_group_${index}_create.!groupmanagement_group_${index}_setgid", | |
comment => "Add the group ${name} if it doesn't exists"; | |
"/usr/sbin/groupadd" | |
args => "-f \"${name}\" -g \"${gid}\"", | |
classes => if_else("groupmanagement_group_add_${index}_repaired", "groupmanagement_group_add_${index}_error"), | |
ifvarclass => "groupmanagement_group_${index}_absent.groupmanagement_group_${index}_create.groupmanagement_group_${index}_setgid", | |
comment => "Add the group ${name} with GID ${gid} if it doesn't exists"; | |
reports: | |
cfengine:: | |
"@@groupManagement@@result_success@@${directiveId}@@Groups@@${name}@@${g.execRun}##${g.uuid}@#The group ${name} is already present and compliant with the policy" | |
ifvarclass => "groupmanagement_group_add_${index}_kept.!(groupmanagement_group_add_${index}_repaired|groupmanagement_group_add_${index}_error)"; | |
"@@groupManagement@@result_success@@${directiveId}@@Groups@@${name}@@${g.execRun}##${g.uuid}@#The group ${name} is already present and doesn't require to have its content enforced" | |
ifvarclass => "!groupmanagement_group_${index}_enforce_content.!(groupmanagement_group_add_${index}_kept.groupmanagement_group_add_${index}_repaired|groupmanagement_group_add_${index}_error)"; | |
"@@groupManagement@@result_repaired@@${directiveId}@@Groups@@${name}@@${g.execRun}##${g.uuid}@#The group ${name} has been updated" | |
ifvarclass => "groupmanagement_group_add_${index}_repaired.!(groupmanagement_group_add_${index}_kept|groupmanagement_group_add_${index}_error)"; | |
"@@groupManagement@@result_error@@${directiveId}@@Groups@@${name}@@${g.execRun}##${g.uuid}@#The group ${name} could not be created or updated" | |
ifvarclass => "groupmanagement_group_add_${index}_error"; | |
"@@groupManagement@@result_success@@${directiveId}@@Groups@@${name}@@${g.execRun}##${g.uuid}@#The group ${name} is not present and not set to be created" | |
ifvarclass => "groupmanagement_group_${index}_absent.!groupmanagement_group_${index}_create"; | |
} | |
bundle edit_line groups_file_append(group,userlist) | |
{ | |
vars: | |
"finalgroup" string => join(",","userlist"); | |
field_edits: | |
"${group}:.*" | |
# Set field of the file to parameter | |
# /etc/group entry is: groupname:x:gid:users | |
edit_field => col(":","4","${finalgroup}","set"); | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# Sudo configuration PT # | |
# ---------------------------------------------------------------------- # | |
# Objective : Configure /etc/sudoers according to the given parameters # | |
########################################################################## | |
bundle agent check_sudo_parameters | |
{ | |
vars: | |
&SUDO_TYPE:{type |"sudo_entity_type[&i&]" string => "&type&"; | |
}& | |
&SUDO_NAME:{name |"sudo_entity_name[&i&]" string => "&name&"; | |
}& | |
&SUDO_NOPASSWD:{nopasswd |"sudo_entity_nopasswd[&i&]" string => "&nopasswd&"; | |
}& | |
&SUDO_ALL:{alldo |"sudo_entity_all[&i&]" string => "&alldo&"; | |
}& | |
&SUDO_COMMAND:{command |"sudo_entity_command[&i&]" string => "&command&"; | |
}& | |
&TRACKINGKEY:{directiveId |"sudo_directive_id[&i&]" string => "&directiveId&"; | |
}& | |
"sudo_index" slist => getindices("sudo_entity_type"); | |
pass_1.visudo_use_strict_mode:: | |
"strict_mode" string => "-s "; | |
pass_1.!visudo_use_strict_mode:: | |
"strict_mode" string => ""; | |
classes: | |
"sudoconfiguration_sudoers_present" expression => fileexists("/etc/sudoers"); | |
# Check the version of visudo; if before 1.7 (so 1.6 or less), we need to use strict mode | |
# For version 1.7, bugs in the strict parsing prevent from using safely the strict mode (see http://www.sudo.ws/bugs/show_bug.cgi?id=519 ) | |
# Versions after 1.7 don't need to have Aliases defined before they are used, and strict mode only checks that, so we can safely ignore it | |
# visudo -V can returns several lines, so we need to keep only the visudo version line | |
"visudo_use_strict_mode" expression => returnszero("/usr/sbin/visudo -V | grep 'visudo version' | /bin/sed -e 's/visudo version \([0-9]\+\)\.\([0-9]\+\)\..*/\1 \2/p' | /usr/bin/awk '{ if(($1<1)||($1==1 \&\& $2<=6)) { exit 0 }; exit 1 }'", "useshell"); | |
"pass_1" expression => "any"; | |
"pass_2" expression => isvariable("strict_mode"); | |
files: | |
# Only copy /etc/sudoers if it exists (this is to avoid falling into an | |
# error report below) | |
sudoconfiguration_sudoers_present:: | |
"/etc/sudoers.rudder" | |
copy_from => digest_cp("/etc/sudoers"), | |
perms => mog("0440", "root", "root"), | |
classes => kept_if_else("sudoconfiguration_sudoers_tmp_copy_kept", "sudoconfiguration_sudoers_tmp_copy_repaired", "sudoconfiguration_sudoers_tmp_copy_error"), | |
comment => "Copying sudoers to a temporary file for editing"; | |
# If there is no /etc/sudoers file, remove our local copy before | |
# rebuilding, so that success/repaired reports make sense for the | |
# /etc/sudoers file, not just for our copy of it, and set result classes | |
# as if we had set it up correctly. | |
!sudoconfiguration_sudoers_present:: | |
"/etc/sudoers.rudder" | |
delete => tidy, | |
classes => kept_if_else("sudoconfiguration_sudoers_tmp_copy_kept", "sudoconfiguration_sudoers_tmp_copy_repaired", "sudoconfiguration_sudoers_tmp_copy_error"), | |
comment => "Remove temporary copy of /etc/sudoers that Rudder keeps in /etc/sudoers.rudder"; | |
((sudoconfiguration_sudoers_tmp_copy_kept|sudoconfiguration_sudoers_tmp_copy_repaired).(!sudoconfiguration_sudoers_tmp_copy_error)):: | |
"/etc/sudoers.rudder" | |
edit_line => sudo_add_line("check_sudo_parameters.sudo_entity_type", "check_sudo_parameters.sudo_entity_name", "check_sudo_parameters.sudo_entity_nopasswd", "check_sudo_parameters.sudo_entity_all", "check_sudo_parameters.sudo_entity_command", "check_sudo_parameters.sudo_directive_id", "${sudo_force_content}"), | |
create => "true", | |
edit_defaults => noempty_backup, | |
perms => mog("0440", "root", "root"), | |
classes => kept_if_else("sudoconfiguration_sudoers_tmp_edit_kept", "sudoconfiguration_sudoers_tmp_edit_repair", "sudoconfiguration_sudoers_tmp_edit_error"), | |
comment => "Editing temporary sudoers file"; | |
sudoconfiguration_sudoers_valid:: | |
"/etc/sudoers" | |
copy_from => digest_cp("/etc/sudoers.rudder"), | |
create => "true", | |
perms => mog("0440", "root", "root"), | |
classes => kept_if_else("sudoconfiguration_sudoers_copy_kept", "sudoconfiguration_sudoers_copy_repaired", "sudoconfiguration_sudoers_copy_error"), | |
comment => "Copying sudoers to its final home"; | |
methods: | |
"any" | |
usebundle => check_sudo_installation("${sudo_directive_id[${sudo_index}]}"); | |
commands: | |
(sudoconfiguration_sudoers_tmp_edit_repair|sudoconfiguration_sudoers_tmp_edit_kept).pass_2:: | |
"/usr/sbin/visudo" | |
args => "-c ${strict_mode} -f /etc/sudoers.rudder", | |
classes => cf2_if_else("sudoconfiguration_sudoers_valid", "sudoconfiguration_sudoers_invalid"), | |
comment => "Checking new sudoers validity"; | |
reports: | |
sudoconfiguration_sudoers_copy_kept.!sudoconfiguration_sudoers_copy_repaired:: | |
"@@sudoParameters@@result_success@@${sudo_directive_id[${sudo_index}]}@@sudoersFile@@None@@${g.execRun}##${g.uuid}@#The sudoers file did not require any modification"; | |
sudoconfiguration_sudoers_copy_repaired:: | |
"@@sudoParameters@@result_repaired@@${sudo_directive_id[${sudo_index}]}@@sudoersFile@@None@@${g.execRun}##${g.uuid}@#The sudoers file was fixed and successfully updated"; | |
sudoconfiguration_sudoers_tmp_edit_error|sudoconfiguration_sudoers_copy_error|sudoconfiguration_sudoers_tmp_copy_error:: | |
"@@sudoParameters@@result_error@@${sudo_directive_id[${sudo_index}]}@@sudoersFile@@None@@${g.execRun}##${g.uuid}@#The sudoers file could NOT be edited!"; | |
sudoconfiguration_sudoers_invalid:: | |
"@@sudoParameters@@result_error@@${sudo_directive_id[${sudo_index}]}@@sudoersFile@@None@@${g.execRun}##${g.uuid}@#The generated sudoers file is invalid. Not updating /etc/sudoers. This should not happen."; | |
} | |
bundle edit_line sudo_add_line(type, name, nopasswd, alldo, command, directiveId, force) | |
{ | |
vars: | |
"index" slist => getindices("${type}"); | |
check_sudo_parameters_sudo_add_line_classes_defined:: | |
"lines[${index}]" | |
string => "%${${name}[${index}]} ALL=(ALL) NOPASSWD:ALL", | |
ifvarclass => "(sudo_${index}_isgroup.sudo_${index}_alldo.sudo_${index}_nopasswd).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "%${${name}[${index}]} ALL=(ALL) ALL", | |
ifvarclass => "(sudo_${index}_isgroup.sudo_${index}_alldo.!sudo_${index}_nopasswd).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "%${${name}[${index}]} ALL=(ALL) NOPASSWD:${${command}[${index}]}", | |
ifvarclass => "(sudo_${index}_isgroup.sudo_${index}_nopasswd.!sudo_${index}_alldo).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "%${${name}[${index}]} ALL=(ALL) ${${command}[${index}]}", | |
ifvarclass => "(sudo_${index}_isgroup.!sudo_${index}_nopasswd.!sudo_${index}_alldo).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "${${name}[${index}]} ALL=(ALL) NOPASSWD:ALL", | |
ifvarclass => "(sudo_${index}_isuser.sudo_${index}_alldo.sudo_${index}_nopasswd).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "${${name}[${index}]} ALL=(ALL) ALL", | |
ifvarclass => "(sudo_${index}_isuser.sudo_${index}_alldo.!sudo_${index}_nopasswd).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "${${name}[${index}]} ALL=(ALL) NOPASSWD:${${command}[${index}]}", | |
ifvarclass => "(sudo_${index}_isuser.sudo_${index}_nopasswd.!sudo_${index}_alldo).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"lines[${index}]" string => "${${name}[${index}]} ALL=(ALL) ${${command}[${index}]}", | |
ifvarclass => "(sudo_${index}_isuser.!sudo_${index}_nopasswd.!sudo_${index}_alldo).(sudo_${index}_command_notempty|sudo_${index}_alldo)"; | |
"all_lines" slist => getvalues("lines"); | |
classes: | |
"sudo_force_content" expression => strcmp("true", "${force}"); | |
# Is it a group ? | |
"sudo_${index}_isgroup" expression => strcmp("${${type}[${index}]}","group"); | |
# Is it a user ? | |
"sudo_${index}_isuser" expression => strcmp("${${type}[${index}]}","user"); | |
# Disable password asking ? | |
"sudo_${index}_nopasswd" expression => strcmp("${${nopasswd}[${index}]}","true"); | |
# Should we enable ALL as command ? | |
"sudo_${index}_alldo" expression => strcmp("${${alldo}[${index}]}","true"); | |
# Is command empty ? | |
"sudo_${index}_command_notempty" not => strcmp("${${command}[${index}]}",""); | |
"check_sudo_parameters_sudo_add_line_classes_defined" expression => "any"; | |
"check_sudo_parameters_sudo_add_line_vars_defined" expression => isvariable("lines[${index}]"); | |
"all_lines_defined" expression => isvariable("all_lines"); | |
delete_lines: | |
all_lines_defined.force:: | |
".*" | |
delete_select => sudo_select_nomatch("${all_lines}"), | |
classes => if_repaired("line_deleted"); | |
insert_lines: | |
replace_attempted_env_reset:: | |
"Defaults env_reset"; | |
check_sudo_parameters_sudo_add_line_vars_defined:: | |
"${lines[${index}]}" | |
classes => kept_if_else("line_${index}_kept", "line_${index}_added", "line_${index}_add_failed"); | |
replace_patterns: | |
"^(?!Defaults env_reset$)Defaults\s+env_reset$" | |
comment => "Normalize env_reset setting", | |
replace_with => value("Defaults env_reset"), | |
classes => always("replace_attempted_env_reset"); | |
reports: | |
all_lines_defined:: | |
"@@sudoParameters@@log_warn@@${${directiveId}[${index}]}@@Permissions@@${${name}[${index}]}@@${g.execRun}##${g.uuid}@#Entry for ${${type}[${index}]} ${${name}[${index}]} is invalid (no command given), and has been ignored" | |
ifvarclass => "!sudo_${index}_command_notempty.!sudo_${index}_alldo"; | |
"@@sudoParameters@@result_repaired@@${${directiveId}[${index}]}@@Permissions@@${${name}[${index}]}@@${g.execRun}##${g.uuid}@#The ${${type}[${index}]} ${${name}[${index}]} has been handled" | |
ifvarclass => canonify("line_${index}_added"); | |
"@@sudoParameters@@result_success@@${${directiveId}[${index}]}@@Permissions@@${${name}[${index}]}@@${g.execRun}##${g.uuid}@#The ${${type}[${index}]} ${${name}[${index}]} is already present" | |
ifvarclass => canonify("line_${index}_kept"); | |
"@@sudoParameters@@result_error@@${${directiveId}[${index}]}@@Permissions@@${${name}[${index}]}@@${g.execRun}##${g.uuid}@#The ${${type}[${index}]} ${${name}[${index}]} could not be handled" | |
ifvarclass => canonify("line_${index}_add_failed"); | |
all_lines_defined.force.line_deleted:: | |
"@@sudoParameters@@result_repaired@@sudoersFile@@None@@${g.execRun}##${g.uuid}@#Some lines were deleted from the sudoers file. This implies either a manual edition or an intrusion attempt"; | |
} | |
bundle agent check_sudo_installation(directiveId) | |
{ | |
packages: | |
linux:: | |
"sudo" | |
package_policy => "add", | |
package_method => generic, | |
classes => kept_if_else("sudoconfiguration_sudo_install_kept", "sudoconfiguration_sudo_install_repaired", "sudoconfiguration_sudo_install_error"), | |
comment => "Installing sudo using generic interface"; | |
reports: | |
sudoconfiguration_sudo_install_kept:: | |
"@@sudoParameters@@result_success@@${directiveId}@@Install@@None@@${g.execRun}##${g.uuid}@#sudo already installed"; | |
sudoconfiguration_sudo_install_repaired:: | |
"@@sudoParameters@@result_repaired@@${directiveId}@@Install@@None@@${g.execRun}##${g.uuid}@#sudo has been successfully installed"; | |
sudoconfiguration_sudo_install_error:: | |
"@@sudoParameters@@result_error@@${directiveId}@@Install@@None@@${g.execRun}##${g.uuid}@#Can't install sudo"; | |
!linux:: | |
"@@sudoParameters@@result_success@@${directiveId}@@Install@@None@@${g.execRun}##${g.uuid}@#Support to check if sudo is installed not available on this platform"; | |
} | |
body delete_select sudo_select_nomatch(s) | |
{ | |
delete_if_not_match_from_list => { "Defaults env_reset", @{s} }; | |
} | |
##################################################################################### | |
# Copyright 2011 Normation SAS | |
##################################################################################### | |
# | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, Version 3. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# | |
##################################################################################### | |
########################################################################## | |
# User/Group management PT # | |
# # | |
# Objective : Apply user/group policies on the target host # | |
########################################################################## | |
bundle agent check_usergroup_user_parameters | |
{ | |
vars: | |
&USERGROUP_USER_LOGIN:{login |"usergroup_user_login[&i&]" string => "&login&"; | |
}& | |
&USERGROUP_USER_GROUP:{group |"usergroup_user_groupname[&i&]" string => "&group&"; | |
}& | |
&USERGROUP_USER_NAME:{name |"usergroup_user_fullname[&i&]" string => "&name&"; | |
}& | |
&USERGROUP_USER_PASSWORD:{password |"usergroup_user_password[&i&]" string => "&password&"; | |
}& | |
&USERGROUP_USER_PASSWORD_POLICY:{passwordpol |"usergroup_user_password_policy[&i&]" string => "&passwordpol&"; | |
}& | |
&USERGROUP_USER_ACTION:{action |"usergroup_user_action[&i&]" string => "&action&"; | |
}& | |
&USERGROUP_USER_UID:{uid |"usergroup_user_uid[&i&]" string => "&uid&"; | |
}& | |
&USERGROUP_USER_HOME_PERSONNALIZE:{homeperso |"usergroup_user_home_perso[&i&]" string => "&homeperso&"; | |
}& | |
&USERGROUP_USER_HOME:{home |"usergroup_user_home[&i&]" string => "&home&"; | |
}& | |
&USERGROUP_USER_SHELL:{shell |"usergroup_user_shell[&i&]" string => "&shell&"; | |
}& | |
&TRACKINGKEY:{directiveId |"usergroup_directive_id[&i&]" string => "&directiveId&"; | |
}& | |
"usergroup_user_index" slist => getindices("usergroup_user_login"); | |
any_2nd_pass:: | |
# 1 - Options to use whether Fullname is defined or not | |
"nameopt[${usergroup_user_index}]" | |
string => "", | |
ifvarclass => "usermanagement_user_nameempty_${usergroup_user_index}"; | |
## On UNIX | |
"nameopt[${usergroup_user_index}]" | |
string => "-c \"${usergroup_user_fullname[${usergroup_user_index}]}\"", | |
ifvarclass => "!usermanagement_user_nameempty_${usergroup_user_index}.!windows"; | |
## On Windows | |
"nameopt[${usergroup_user_index}]" | |
string => "/FULLNAME:\"${usergroup_user_fullname[${usergroup_user_index}]}\"", | |
ifvarclass => "!usermanagement_user_nameempty_${usergroup_user_index}.windows"; | |
## Part of reports to return whether Fullname is defined or not | |
"repname[${usergroup_user_index}]" | |
string => "Without any defined full name", | |
ifvarclass => "usermanagement_user_nameempty_${usergroup_user_index}"; | |
"repname[${usergroup_user_index}]" | |
string => "${usergroup_user_fullname[${usergroup_user_index}]}", | |
ifvarclass => "!usermanagement_user_nameempty_${usergroup_user_index}"; | |
# 2 - On UNIX, choose between using no group name or using a custom one | |
"groupopt[${usergroup_user_index}]" | |
string => "", | |
ifvarclass => "usermanagement_user_groupempty_${usergroup_user_index}"; | |
"groupopt[${usergroup_user_index}]" | |
string => "-g ${usergroup_user_groupname[${usergroup_user_index}]}", | |
ifvarclass => "!usermanagement_user_groupempty_${usergroup_user_index}"; | |
# 3 - on UNIX force user id if provided | |
"useropt[${usergroup_user_index}]" | |
string => "", | |
ifvarclass => "usermanagement_user_uid_empty_${usergroup_user_index}"; | |
"useropt[${usergroup_user_index}]" | |
string => "-u ${usergroup_user_uid[${usergroup_user_index}]}", | |
ifvarclass => "!usermanagement_user_uid_empty_${usergroup_user_index}"; | |
classes: | |
# Actions | |
"usermanagement_user_update_${usergroup_user_index}" expression => strcmp("${usergroup_user_action[${usergroup_user_index}]}","add"); | |
"usermanagement_user_remove_${usergroup_user_index}" expression => strcmp("${usergroup_user_action[${usergroup_user_index}]}","remove"); | |
"usermanagement_user_checkpres_${usergroup_user_index}" expression => strcmp("${usergroup_user_action[${usergroup_user_index}]}","checkhere"); | |
"usermanagement_user_checkabs_${usergroup_user_index}" expression => strcmp("${usergroup_user_action[${usergroup_user_index}]}","checknothere"); | |
"usermanagement_user_pershome_${usergroup_user_index}" not => strcmp("${usergroup_user_home_perso[${usergroup_user_index}]}","true"); | |
"usermanagement_user_custom_home_defined_${usergroup_user_index}" expression => isvariable("usergroup_user_home[${usergroup_user_index}]"); | |
"usermanagement_user_exists_${usergroup_user_index}" expression => userexists("${usergroup_user_login[${usergroup_user_index}]}"); | |
"usermanagement_group_exists_${usergroup_user_index}" expression => groupexists("${usergroup_user_groupname[${usergroup_user_index}]}"); | |
"usermanagement_user_pwoneshot_${usergroup_user_index}" expression => strcmp("${usergroup_user_password_policy[${usergroup_user_index}]}","oneshot"); | |
"usermanagement_user_pweverytime_${usergroup_user_index}" expression => strcmp("${usergroup_user_password_policy[${usergroup_user_index}]}","everytime"); | |
# with variables that are not unique, the emptyness detection is quite tricky | |
# either the variable is not defined, or the variable value is "" | |
"usermanagement_user_pw_no_variable_${usergroup_user_index}" not => isvariable("usergroup_user_password[${usergroup_user_index}]"); | |
"usermanagement_user_pw_no_value_${usergroup_user_index}" expression => strcmp("", "${usergroup_user_password[${usergroup_user_index}]}"); | |
"usermanagement_user_pwempty_${usergroup_user_index}" expression => "usermanagement_user_pw_no_variable_${usergroup_user_index}|usermanagement_user_pw_no_value_${usergroup_user_index}"; | |
"usermanagement_user_name_no_variable_${usergroup_user_index}" not => isvariable("usergroup_user_fullname[${usergroup_user_index}]"); | |
"usermanagement_user_name_no_value_${usergroup_user_index}" expression => strcmp("", "${usergroup_user_fullname[${usergroup_user_index}]}"); | |
"usermanagement_user_nameempty_${usergroup_user_index}" expression => "usermanagement_user_name_no_variable_${usergroup_user_index}|usermanagement_user_name_no_value_${usergroup_user_index}"; | |
"usermanagement_user_group_no_variable_${usergroup_user_index}" not => isvariable("usergroup_user_groupname[${usergroup_user_index}]"); | |
"usermanagement_user_group_no_value_${usergroup_user_index}" expression => strcmp("", "${usergroup_user_groupname[${usergroup_user_index}]}"); | |
"usermanagement_user_groupempty_${usergroup_user_index}" expression => "usermanagement_user_group_no_variable_${usergroup_user_index}|usermanagement_user_group_no_value_${usergroup_user_index}"; | |
"usermanagement_user_uid_no_variable_${usergroup_user_index}" not => isvariable("usergroup_user_uid[${usergroup_user_index}]"); | |
"usermanagement_user_uid_no_value_${usergroup_user_index}" expression => strcmp("", "${usergroup_user_uid[${usergroup_user_index}]}"); | |
"usermanagement_user_uid_empty_${usergroup_user_index}" expression => "usermanagement_user_uid_no_variable_${usergroup_user_index}|usermanagement_user_uid_no_value_${usergroup_user_index}"; | |
"usermanagement_user_groupmatchesname_${usergroup_user_index}" expression => strcmp("${usergroup_user_login[${usergroup_user_index}]}", "${usergroup_user_groupname[${usergroup_user_index}]}"); | |
# Group doesn't exist and group name is defined | |
"usermanagement_user_group_definition_error_${usergroup_user_index}" expression => "(!usermanagement_group_exists_${usergroup_user_index}.usermanagement_user_groupmatchesname_${usergroup_user_index})|(!usermanagement_user_groupempty_${usergroup_user_index}.!usermanagement_group_exists_${usergroup_user_index})"; | |
# check if user exists when enforcing ids | |
"usermanagement_uid_exists_${usergroup_user_index}" expression => userexists("${usergroup_user_uid[${usergroup_user_index}]}"), | |
ifvarclass => "!usermanagement_user_uid_empty_${usergroup_user_index}"; | |
# UID is defined and already exists | |
"usermanagement_user_uid_definition_error_${usergroup_user_index}" expression => "!usermanagement_user_uid_empty_${usergroup_user_index}.usermanagement_uid_exists_${usergroup_user_index}"; | |
# Class 'any' is executed before others classes defined. | |
# Same as 'any' but execution will be after all classes defined | |
"any_2nd_pass" expression => "any"; | |
"showtime" expression => isvariable("nameopt[1]"); | |
files: | |
"/etc/passwd" | |
create => "false", | |
edit_line => set_user_fullname("${usergroup_user_login[${usergroup_user_index}]}","${usergroup_user_index}","${usergroup_user_fullname[${usergroup_user_index}]}"), | |
edit_defaults => noempty_backup, | |
ifvarclass => "usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_nameempty_${usergroup_user_index}"; | |
"/etc/passwd" | |
create => "false", | |
edit_line => set_user_fullname("${usergroup_user_login[${usergroup_user_index}]}","${usergroup_user_index}","${usergroup_user_fullname[${usergroup_user_index}]}"), | |
edit_defaults => noempty_backup, | |
action => WarnOnly, | |
ifvarclass => "usermanagement_user_checkpres_${usergroup_user_index}.!usermanagement_user_nameempty_${usergroup_user_index}"; | |
# Define password when user has already been created | |
"/etc/shadow" | |
create => "false", | |
edit_line => set_user_field("${usergroup_user_login[${usergroup_user_index}]}", 2, "${usergroup_user_password[${usergroup_user_index}]}"), | |
edit_defaults => noempty_backup, | |
classes => kept_if_else("usermanagement_user_password_ok_${usergroup_user_index}", "usermanagement_user_password_repaired_${usergroup_user_index}", "usermanagement_user_password_failed_${usergroup_user_index}"), | |
ifvarclass => "(usermanagement_login_add_${usergroup_user_index}_repaired.usermanagement_user_pwoneshot_${usergroup_user_index}.!usermanagement_user_pwempty_${usergroup_user_index})|(usermanagement_user_update_${usergroup_user_index}.usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_pweverytime_${usergroup_user_index}.!usermanagement_user_pwempty_${usergroup_user_index})"; | |
commands: | |
&if(NOVA)& | |
windows.showtime:: | |
"\"${sys.winsysdir}\net.exe\"" | |
args => "USER ${usergroup_user_login[${usergroup_user_index}]} ${usergroup_user_password[${usergroup_user_index}]} /ADD ${nameopt[${usergroup_user_index}]}", | |
classes => cf2_if_else("usermanagement_login_add_${usergroup_user_index}_repaired", "usermanagement_login_add_${usergroup_user_index}_error"), | |
comment => "Create the user ${usergroup_user_login[${usergroup_user_index}]}", | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}"; | |
"\"${sys.winsysdir}\net.exe\"" | |
args => "USER ${usergroup_user_login[${usergroup_user_index}]} /DELETE", | |
classes => cf2_if_else("usermanagement_login_remove_${usergroup_user_index}_repaired", "usermanagement_login_remove_${usergroup_user_index}_error"), | |
comment => "Delete the user ${usergroup_user_login[${usergroup_user_index}]}", | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_remove_${usergroup_user_index}"; | |
"\"${sys.winsysdir}\net.exe\"" | |
args => "USER ${usergroup_user_login[${usergroup_user_index}]} ${usergroup_user_password[${usergroup_user_index}]}", | |
ifvarclass => "(usermanagement_login_add_${usergroup_user_index}_repaired.usermanagement_user_pwoneshot_${usergroup_user_index}.!usermanagement_user_pwempty_${usergroup_user_index})|(usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_pweverytime_${usergroup_user_index}.!usermanagement_user_pwempty_${usergroup_user_index})"; | |
&endif& | |
linux.showtime:: | |
"/usr/sbin/useradd" | |
args => "${useropt[${usergroup_user_index}]} ${groupopt[${usergroup_user_index}]} -m ${nameopt[${usergroup_user_index}]} -s ${usergroup_user_shell[${usergroup_user_index}]} ${usergroup_user_login[${usergroup_user_index}]}", | |
classes => cf2_if_else("usermanagement_login_add_${usergroup_user_index}_repaired", "usermanagement_login_add_${usergroup_user_index}_error"), | |
comment => "Create the user", | |
ifvarclass => "!usermanagement_user_uid_definition_error_${usergroup_user_index}.!usermanagement_user_group_definition_error_${usergroup_user_index}.!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_pershome_${usergroup_user_index}"; | |
"/usr/sbin/useradd" | |
args => "${useropt[${usergroup_user_index}]} ${groupopt[${usergroup_user_index}]} -m ${nameopt[${usergroup_user_index}]} -s ${usergroup_user_shell[${usergroup_user_index}]} -d ${usergroup_user_home[${usergroup_user_index}]} ${usergroup_user_login[${usergroup_user_index}]}", | |
classes => cf2_if_else("usermanagement_login_add_${usergroup_user_index}_repaired", "usermanagement_login_add_${usergroup_user_index}_error"), | |
comment => "Create the user with a custom home directory", | |
ifvarclass => "!usermanagement_user_uid_definition_error_${usergroup_user_index}.!usermanagement_user_group_definition_error_${usergroup_user_index}.!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.usermanagement_user_pershome_${usergroup_user_index}.usermanagement_user_custom_home_defined_${usergroup_user_index}"; | |
"/usr/sbin/userdel" | |
args => "${usergroup_user_login[${usergroup_user_index}]}", | |
classes => cf2_if_else("usermanagement_login_remove_${usergroup_user_index}_repaired", "usermanagement_login_remove_${usergroup_user_index}_error"), | |
comment => "Delete the user ${usergroup_user_login[${usergroup_user_index}]}", | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_remove_${usergroup_user_index}"; | |
reports: | |
(linux|windows).showtime:: | |
# Add user | |
## Does exist (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is already present on the system" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.!usermanagement_login_add_${usergroup_user_index}_repaired.(usermanagement_user_nameempty_${usergroup_user_index}|usermanagement_fullname_edit_${usergroup_user_index}_kept)"; | |
## Seems to exist with a wrong Full Name (Repaired) | |
"@@userGroupManagement@@result_repaired@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) had a wrong fullname" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_nameempty_${usergroup_user_index}.(usermanagement_fullname_edit_${usergroup_user_index}_repaired|usermanagement_fullname_edit_${usergroup_user_index}_error)"; | |
## Added (Repaired) | |
"@@userGroupManagement@@result_repaired@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) has been added to the system" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.usermanagement_login_add_${usergroup_user_index}_repaired"; | |
## Error | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) could not be added to the system" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.usermanagement_login_add_${usergroup_user_index}_error"; | |
## Could not be added, for the default path was not selected, but the custom one was not defined | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) could not be added to the system because the default home directory was not selected, but the custom path was not specified" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_update_${usergroup_user_index}.usermanagement_user_pershome_${usergroup_user_index}.!usermanagement_user_custom_home_defined_${usergroup_user_index}"; | |
## Could not be added, as a custom group was asked for and did not exist on the system | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) could not be added to the system because the custom group \"${usergroup_user_groupname[${usergroup_user_index}]}\" does not exist" | |
ifvarclass => "usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_group_definition_error_${usergroup_user_index}"; | |
## Could not be added, as a custom uid was asked for and did exist on the system | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) could not be added to the system because the custom uid \"${usergroup_user_uid[${usergroup_user_index}]}\" already exists" | |
ifvarclass => "usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_uid_definition_error_${usergroup_user_index}"; | |
# Remove user | |
## Does not exist (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) does not exist, as required" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_remove_${usergroup_user_index}"; | |
## Removed (Repaired) | |
"@@userGroupManagement@@result_repaired@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) has been removed from the system" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_remove_${usergroup_user_index}.usermanagement_login_remove_${usergroup_user_index}_repaired"; | |
## Error | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) could not be removed from the system" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_remove_${usergroup_user_index}.usermanagement_login_remove_${usergroup_user_index}_error"; | |
# Check user not exists | |
## Does not exist (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is not present on the system, which is in accordance with the non presence policy" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_checkabs_${usergroup_user_index}"; | |
## Does exist (Error) | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is present on the system, which violates the non presence policy" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_checkabs_${usergroup_user_index}"; | |
# Check user exists | |
## Does exist (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is present on the system, which is in conformance with the presence policy" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_checkpres_${usergroup_user_index}.(usermanagement_user_nameempty_${usergroup_user_index}|usermanagement_fullname_edit_${usergroup_user_index}_kept)"; | |
## Seems to exist with a wrong Full Name (Error) | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is present on the system, but does not have the right fullname" | |
ifvarclass => "usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_checkpres_${usergroup_user_index}.!usermanagement_user_nameempty_${usergroup_user_index}.(usermanagement_fullname_edit_${usergroup_user_index}_repaired|usermanagement_fullname_edit_${usergroup_user_index}_error)"; | |
## Does not exist (Error) | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Users@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) is not present on the system, which violates the presence policy" | |
ifvarclass => "!usermanagement_user_exists_${usergroup_user_index}.usermanagement_user_checkpres_${usergroup_user_index}"; | |
# Password handling | |
## Is OK (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Password@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) password is OK" | |
ifvarclass => "usermanagement_user_password_ok_${usergroup_user_index}"; | |
## Has been changed (Repaired) | |
"@@userGroupManagement@@result_repaired@@${usergroup_directive_id[${usergroup_user_index}]}@@Password@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) password has been changed" | |
ifvarclass => "usermanagement_user_password_repaired_${usergroup_user_index}"; | |
## Could not be changed (Error) | |
"@@userGroupManagement@@result_error@@${usergroup_directive_id[${usergroup_user_index}]}@@Password@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) password could NOT be changed !" | |
ifvarclass => "usermanagement_user_password_failed_${usergroup_user_index}"; | |
## Change not needed (Success) | |
"@@userGroupManagement@@result_success@@${usergroup_directive_id[${usergroup_user_index}]}@@Password@@${usergroup_user_login[${usergroup_user_index}]}@@${g.execRun}##${g.uuid}@#The user ${usergroup_user_login[${usergroup_user_index}]} ( ${repname[${usergroup_user_index}]} ) password change is not required" | |
ifvarclass => "((!usermanagement_user_password_ok_${usergroup_user_index}.!usermanagement_user_password_repaired_${usergroup_user_index}.!usermanagement_user_password_failed_${usergroup_user_index}).((usermanagement_user_pwoneshot_${usergroup_user_index}.usermanagement_user_exists_${usergroup_user_index})|usermanagement_user_pwempty_${usergroup_user_index}|(usermanagement_user_update_${usergroup_user_index}.!usermanagement_user_exists_${usergroup_user_index}.(usermanagement_user_group_definition_error_${usergroup_user_index}|usermanagement_user_uid_definition_error_${usergroup_user_index}))))|usermanagement_user_remove_${usergroup_user_index}"; | |
} | |
bundle edit_line set_user_fullname(user,user_index,fullname) | |
{ | |
field_edits: | |
"${user}:.*" | |
# Edit GECOS on /etc/passwd | |
edit_field => col(":", "5", "${fullname}", "set"), | |
classes => kept_if_else("usermanagement_fullname_edit_${user_index}_kept","usermanagement_fullname_edit_${user_index}_repaired","usermanagement_fullname_edit_${user_index}_error"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment