From 0b3908ea518f371237642dec2790be6b1c25db95 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Sun, 5 Mar 2017 14:43:06 +0000 Subject: Initial import --- .gitignore | 1 + controls/cf_agent.cf | 7 ++ controls/cf_execd.cf | 10 +++ controls/cf_monitord.cf | 8 +++ controls/cf_runagent.cf | 5 ++ controls/cf_serverd.cf | 30 ++++++++ failsafe.cf | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ promises.cf | 29 ++++++++ services/main.cf | 24 +++++++ update.cf | 10 +++ 10 files changed, 309 insertions(+) create mode 100644 .gitignore create mode 100644 controls/cf_agent.cf create mode 100644 controls/cf_execd.cf create mode 100644 controls/cf_monitord.cf create mode 100644 controls/cf_runagent.cf create mode 100644 controls/cf_serverd.cf create mode 100644 failsafe.cf create mode 100644 promises.cf create mode 100644 services/main.cf create mode 100644 update.cf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..983bea5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.*.sw[mnop] diff --git a/controls/cf_agent.cf b/controls/cf_agent.cf new file mode 100644 index 0000000..b3b1020 --- /dev/null +++ b/controls/cf_agent.cf @@ -0,0 +1,7 @@ +body agent control +{ + any:: + ifelapsed => "1"; + skipidentify => "true"; + maxconnections => "30"; +} diff --git a/controls/cf_execd.cf b/controls/cf_execd.cf new file mode 100644 index 0000000..b960be3 --- /dev/null +++ b/controls/cf_execd.cf @@ -0,0 +1,10 @@ +body executor control +{ + any:: + splaytime => "4"; # activity will be spread over this many time slices + exec_command => "$(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated -f \"$(sys.failsafe_policy_path)\" ; $(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated"; + !cfengine_internal_disable_agent_email:: + mailto => "root@adyxax.org"; + mailfrom => "cfengine@adyxax.org"; + smtpserver => "10.1.0.254"; +} diff --git a/controls/cf_monitord.cf b/controls/cf_monitord.cf new file mode 100644 index 0000000..f9f2634 --- /dev/null +++ b/controls/cf_monitord.cf @@ -0,0 +1,8 @@ +body monitor control +{ + any:: + forgetrate => "0.7"; + histograms => "true"; + # tcpdump => "false"; + # tcpdumpcommand => "/usr/sbin/tcpdump -t -n -v"; +} diff --git a/controls/cf_runagent.cf b/controls/cf_runagent.cf new file mode 100644 index 0000000..6219b00 --- /dev/null +++ b/controls/cf_runagent.cf @@ -0,0 +1,5 @@ +body runagent control +{ + any:: + hosts => { "127.0.0.1" }; +} diff --git a/controls/cf_serverd.cf b/controls/cf_serverd.cf new file mode 100644 index 0000000..3b5a625 --- /dev/null +++ b/controls/cf_serverd.cf @@ -0,0 +1,30 @@ +body server control +{ + any:: + allowconnects => { "127.0.0.1" , "::1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" }; + allowallconnects => { "127.0.0.1" , "::1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" }; + trustkeysfrom => { "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" }; + maxconnections => "200"; + denybadclocks => "false"; + # last single quote in cfruncommand is left open, so that + # arguments (like -K and --remote-bundles) are properly appended. + cfruncommand => "$(def.cf_runagent_shell) -c \' + $(sys.cf_agent) -I -D cfruncommand -f $(sys.update_policy_path) ; + $(sys.cf_agent) -I -D cfruncommand"; + !policy_server:: + allowusers => { "root" }; +} + +bundle server access_rules() +{ + access: + any:: + "$(def.dir_masterfiles)" + shortcut => "masterfiles", + admit => { "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" }; + "$(def.cf_runagent_shell)" + admit => { "$(sys.policy_hub)" }; + roles: + any:: + ".*" authorize => { "root" }; +} diff --git a/failsafe.cf b/failsafe.cf new file mode 100644 index 0000000..c23942e --- /dev/null +++ b/failsafe.cf @@ -0,0 +1,185 @@ +# Failsafe file +# - Always ensured to run the update bundle. Do not modify. Ever. + +# Failsafe imports and promises +body agent control { + any:: + abortclasses => { "no_ppkeys_ABORT_kept" }; # Bootstrapping can't continue without keys + ifelapsed => "0"; # Make sure that running failsafe many times in a row does not change functionality +} + +bundle agent main { + methods: + any:: + "Check Keys" + usebundle => failsafe_checkkeys, + comment => "Without a valid keypair we aren't going to be able to establish trust"; + "Fetch Inputs" + usebundle => failsafe_update, + comment => "We need to fetch policy from upstream if we are bootstrapping or if we are performing failsafe recovery."; + "Actuate Update Policy" + usebundle => failsafe_call_update, + comment => "In order to speed up convergence and reporting we trigger the update policy right after initial + bootstrap. This allows the first scheduled run to happen with the most up to date and complete information."; + "Report" + usebundle => failsafe_report, + comment => "It's important to let the user know what happened as the result of the bootstrap or failsafe operation."; +} + +bundle agent failsafe_checkkeys +{ + classes: + any:: + "have_ppkeys" expression => fileexists("$(sys.workdir)/ppkeys/localhost.pub"); + reports: + !have_ppkeys:: + "No public/private key pair is loaded, please create one by running \"cf-key\"" classes => failsafe_results("namespace", "no_ppkeys_ABORT"); +} + +bundle agent failsafe_update { + vars: + any:: + # A policy server cannot use the shortcut feature to resolve + # masterfiles since cf-serverd is potentially not yet up and + # running. + # The unqualified path is used for non policy servers so that + # the policy server can use a shortcut to decide on behalf of + # the client which policy to serve by default. This is useful + # when running binaires from mixed sources (for example CFEngine + # produced binaries vs packages from the debian repository). + "masterfiles_dir_remote" string => ifelse( "policy_server", $(sys.masterdir), "masterfiles" ); + files: + any:: + "$(sys.inputdir)" + copy_from => failsafe_scp("$(masterfiles_dir_remote)"), + depth_search => failsafe_recurse("inf"), + file_select => failsafe_exclude_vcs_files, + classes => failsafe_results("namespace", "inputdir_update"); + inputdir_update_error:: + "$(sys.inputdir)" + copy_from => failsafe_scp("$(sys.masterdir)"), + depth_search => failsafe_recurse("inf"), + file_select => failsafe_exclude_vcs_files, + classes => failsafe_results("namespace", "inputdir_update"), + comment => "If we failed to fetch policy we try again using the legacy default in case we are fetching policy + from a hub that is not serving masterfiles via a shortcut."; + processes: + any:: + "cf-serverd" restart_class => "cf_serverd_not_running"; + inputdir_update_repaired:: + "cf-execd" restart_class => "cf_execd_not_running"; + commands: + cf_execd_not_running.!systemd:: + "$(sys.cf_execd)" classes => failsafe_results("namespace", "cf_execd_running"); + cf_serverd_not_running.!(windows|systemd):: + "$(sys.cf_serverd)" classes => failsafe_results("namespace", "cf_serverd_running"); + cf_execd_not_running.systemd:: + "/bin/systemctl restart cfengine3" classes => failsafe_results("namespace", "systemctl_restart_cfengine3"); +} + +bundle agent failsafe_call_update +{ + vars: + any:: + "mode" string => ifelse("bootstrap_mode", "bootstrap_mode", "failsafe_mode"); + commands: + any:: + "$(sys.cf_agent) -f $(sys.update_policy_path) --define $(mode)" if => fileexists( $(sys.update_policy_path) ); +} + +bundle agent failsafe_report { + classes: + any:: + "have_promises_cf" expression => fileexists("$(sys.inputdir)/promises.cf"); + reports: + !bootstrap_mode:: + "Built-in failsafe policy triggered"; + bootstrap_mode:: + "Bootstrapping from host '$(sys.policy_hub)' via built-in policy '$(this.promise_filename)'"; + bootstrap_mode.policy_server:: + "This host assumes the role of policy server"; + bootstrap_mode.!policy_server:: + "This autonomous node assumes the role of voluntary client"; + inputdir_update_repaired:: + "Updated local policy from policy server"; + inputdir_update_repaired.!have_promises_cf:: + "Failed to copy policy from policy server at $(sys.policy_hub):$(sys.masterdir) +Please check + * cf-serverd is running on $(sys.policy_hub) + * CFEngine version on the policy hub is 3.6.0 or latest - otherwise you need to tweak the protocol_version setting + * network connectivity to $(sys.policy_hub) on port $(sys.policy_hub_port) + * masterfiles 'body server control' - in particular allowconnects, trustkeysfrom and skipverify + * masterfiles 'bundle server' -> access: -> masterfiles -> admit/deny +It is often useful to restart cf-serverd in verbose mode (cf-serverd -v) on $(sys.policy_hub) to diagnose connection issues. +When updating masterfiles, wait (usually 5 minutes) for files to propagate to inputs on $(sys.policy_hub) before retrying."; + systemctl_restart_cfengine3_repaired:: + "Restarted systemd unit cfengine3"; + systemctl_restart_cfengine3_error:: + "Error restarting systemd unit cfengine3"; + cf_serverd_running_repaired:: + "Started the server"; + cf_serverd_running_failed:: + "Failed to start the server"; + cf_execd_running_repaired:: + "Started the scheduler"; + cf_execd_running_failed:: + "Failed to start the scheduler"; +} + +############################################ +body copy_from failsafe_scp(from) +{ + any:: + source => "$(from)"; + compare => "digest"; + encrypt => "true"; + verify => "true"; + copy_backup => "false"; + purge => "true"; + # This class is always set when bootstrapping. You can deactivate + # this class with --trust-server=no when bootstrapping + trust_server:: + trustkey => "true"; + !policy_server:: + servers => { "$(sys.policy_hub)" }; + portnumber => "$(sys.policy_hub_port)"; +} +############################################ +body depth_search failsafe_recurse(d) +{ + depth => "$(d)"; + exclude_dirs => { "\.svn", "\.git" }; +} +############################################ +body file_select failsafe_exclude_vcs_files +{ + leaf_name => { "\.git.*", "\.mailmap" }; + file_result => "!leaf_name"; +} +############################################ +body classes failsafe_results(scope, class_prefix) +# @brief Define classes prefixed with `class_prefix` and suffixed with +# appropriate outcomes: _kept, _repaired, _not_kept, _error, _failed, +# _denied, _timeout, _reached +# +# @param scope The scope in which the class should be defined (`bundle` or `namespace`) +# @param class_prefix The prefix for the classes defined +{ + scope => "$(scope)"; + promise_kept => { "$(class_prefix)_reached", + "$(class_prefix)_kept" }; + promise_repaired => { "$(class_prefix)_reached", + "$(class_prefix)_repaired" }; + repair_failed => { "$(class_prefix)_reached", + "$(class_prefix)_error", + "$(class_prefix)_not_kept", + "$(class_prefix)_failed" }; + repair_denied => { "$(class_prefix)_reached", + "$(class_prefix)_error", + "$(class_prefix)_not_kept", + "$(class_prefix)_denied" }; + repair_timeout => { "$(class_prefix)_reached", + "$(class_prefix)_error", + "$(class_prefix)_not_kept", + "$(class_prefix)_timeout" }; +} diff --git a/promises.cf b/promises.cf new file mode 100644 index 0000000..24a989c --- /dev/null +++ b/promises.cf @@ -0,0 +1,29 @@ +body common control +{ + any:: + bundlesequence => { + cfengine_controls, + classify, + hello, + }; + inputs => { + @(cfengine_controls.inputs), + "services/main.cf", + }; +} + +bundle common cfengine_controls +{ + vars: + any:: + "input[cf_agent]" string => "controls/cf_agent.cf"; + "input[cf_execd]" string => "controls/cf_execd.cf"; + "input[cf_monitord]" string => "controls/cf_monitord.cf"; + "input[cf_serverd]" string => "controls/cf_serverd.cf"; + "input[cf_runagent]" string => "controls/cf_runagent.cf"; + "inputs" slist => getvalues(input); + reports: + DEBUG|DEBUG_cfengine_controls:: + "DEBUG $(this.bundle)"; + "$(const.t)defining inputs='$(inputs)'"; +} diff --git a/services/main.cf b/services/main.cf new file mode 100644 index 0000000..5808f31 --- /dev/null +++ b/services/main.cf @@ -0,0 +1,24 @@ +############################################################################### +# +# bundle agent main +# - User/Site policy entry +# +############################################################################### + +bundle common classify +{ + classes: + any:: + "containers" or => { + regline(".*/lxc/.*", "/proc/1/cgroup"), + regline(".*lxc", "/proc/1/environ"), + }; + "mail_servers" or => { "legend" }; +} + +bundle agent hello +{ + reports: + any:: + "$(this.bundle): hello world"; +} diff --git a/update.cf b/update.cf new file mode 100644 index 0000000..af3bef1 --- /dev/null +++ b/update.cf @@ -0,0 +1,10 @@ +body common control +{ + any:: + bundlesequence => { + main, + }; + inputs => { + "failsafe.cf", + }; +} -- cgit v1.2.3