summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--controls/cf_execd.cf2
-rw-r--r--failsafe.cf255
-rw-r--r--promises.cf2
-rw-r--r--update.cf134
4 files changed, 133 insertions, 260 deletions
diff --git a/controls/cf_execd.cf b/controls/cf_execd.cf
index ddb9124..f75fe3c 100644
--- a/controls/cf_execd.cf
+++ b/controls/cf_execd.cf
@@ -2,7 +2,7 @@ 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";
+ exec_command => "$(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated -f \"$(sys.update_policy_path)\" ; $(sys.cf_agent) -Dfrom_cfexecd,cf_execd_initiated";
!cfengine_internal_disable_agent_email::
mailto => "root@adyxax.org";
mailfrom => "root@adyxax.org";
diff --git a/failsafe.cf b/failsafe.cf
deleted file mode 100644
index a7cacc1..0000000
--- a/failsafe.cf
+++ /dev/null
@@ -1,255 +0,0 @@
-# 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";
- "Copy binaries"
- usebundle => failsafe_copy_binaries,
- comment => "Not all distributions populate /var/cfengine/bin";
- "Fetch Inputs"
- usebundle => failsafe_update,
- comment => "We need to fetch policy from upstream if we are bootstrapping or if we are performing failsafe recovery.";
- "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_copy_binaries
-{
- classes:
- any::
- "alpinelinux" expression => fileexists("/etc/alpine-release");
- vars:
- alpinelinux|freebsd::
- "binaries" slist => {
- "cf-agent",
- "cf-execd",
- "cf-key",
- "cf-monitord",
- "cf-promises",
- "cf-runagent",
- "cf-serverd",
- "cf-upgrade",
- };
- files:
- alpinelinux::
- "$(sys.bindir)/$(binaries)"
- copy_from => failsafe_cp("/usr/sbin/$(binaries)"),
- action => failsafe_u_immediate,
- classes => failsafe_results("namespace", "copy_binaries");
- freebsd::
- "$(sys.bindir)/$(binaries)"
- copy_from => failsafe_cp("/usr/local/sbin/$(binaries)"),
- action => failsafe_u_immediate,
- classes => failsafe_results("namespace", "copy_binaries");
- reports:
- copy_binaries_repaired::
- "cf-engine binaries updated";
-}
-
-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" );
- classes:
- any::
- "alpinelinux" expression => fileexists("/etc/alpine-release");
- alpinelinux::
- "cf_execd_not_running" expression => returnszero("/usr/bin/pgrep cf-execd", "noshell");
- "cf_serverd_not_running" expression => returnszero("/usr/bin/pgrep cf-serverd", "noshell");
- systemd::
- "cfengine3_service_running" expression => returnszero("/bin/systemctl status cfengine3", "noshell");
- files:
- any::
- "$(sys.inputdir)"
- copy_from => failsafe_scp("$(masterfiles_dir_remote)"),
- depth_search => failsafe_recurse("inf"),
- action => failsafe_u_immediate,
- 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.";
- !am_policy_hub::
- "$(sys.workdir)/modules"
- copy_from => failsafe_scp("modules"),
- depth_search => failsafe_recurse("inf"),
- perms => failsafe_u_m("755"),
- action => failsafe_u_immediate,
- file_select => failsafe_exclude_vcs_files,
- classes => failsafe_results("namespace", "modulesdir_update");
- processes:
- !(alpinelinux|systemd|windows)::
- "cf-serverd" restart_class => "cf_serverd_not_running";
- !(alpinelinux|systemd|windows).inputdir_update_repaired::
- "cf-execd" restart_class => "cf_execd_not_running";
- commands:
- cf_execd_not_running::
- "$(sys.cf_execd)" classes => failsafe_results("namespace", "cf_execd_running");
- cf_serverd_not_running::
- "$(sys.cf_serverd)" classes => failsafe_results("namespace", "cf_serverd_running");
- systemd.(!cfengine3_service_running|inputdir_update_repaired)::
- "/bin/systemctl restart cfengine3"
- contain => failsafe_noshell_and_silent,
- classes => failsafe_results("namespace", "systemctl_restart_cfengine3");
-}
-
-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.";
- bootstrap_mode.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_cp(from)
-{
- any::
- source => "$(from)";
- compare => "digest";
- encrypt => "true";
- verify => "true";
- copy_backup => "false";
- purge => "true";
-}
-############################################
-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" };
-}
-
-body contain failsafe_noshell_and_silent
-{
- useshell => "noshell";
- no_output => true;
-}
-
-body perms failsafe_u_m(p)
-{
- mode => "$(p)";
-}
-
-body action failsafe_u_immediate
-{
- ifelapsed => "0";
-}
diff --git a/promises.cf b/promises.cf
index 5712848..3da719c 100644
--- a/promises.cf
+++ b/promises.cf
@@ -43,4 +43,4 @@ bundle common cfengine_stdlib
reports:
DEBUG|DEBUG_cfengine_stdlib::
"$(const.t): defining inputs='$(inputs)'";
-}
+} \ No newline at end of file
diff --git a/update.cf b/update.cf
index 94cd97a..7f0d6ff 100644
--- a/update.cf
+++ b/update.cf
@@ -4,7 +4,135 @@ body common control
bundlesequence => {
main,
};
- inputs => {
- "failsafe.cf",
- };
+ inputs => {};
+}
+
+bundle agent main
+{
+ vars:
+ any::
+ "input_name_patterns" slist => {
+ "authorized_keys",
+ "cf_promises_release_id",
+ ".*templates.*",
+ ".*\.cf",
+ ".*\.dat",
+ ".*\.txt",
+ ".*\.cfg",
+ ".*\.conf",
+ ".*\.json",
+ ".*\.mustache",
+ ".*\.pl",
+ ".*\.py",
+ ".*\.rb",
+ ".*\.sh",
+ ".*\.yaml",
+ };
+ files:
+ !am_policy_hub::
+ "$(sys.inputdir)/cf_promises_validated"
+ copy_from => secure_cp("$(sys.masterdir)/cf_promises_validated"),
+ action => immediate,
+ classes => if_repaired("validated_updates_ready");
+ "$(sys.workdir)/modules"
+ copy_from => secure_cp("modules"),
+ depth_search => recurse("inf"),
+ perms => m("755"),
+ action => immediate,
+ file_select => exclude_vcs_files;
+ am_policy_hub::
+ "$(sys.masterdir)/."
+ perms => m(700),
+ depth_search => recurse_basedir("inf"),
+ action => immediate;
+ am_policy_hub|validated_updates_ready::
+ "$(sys.inputdir)"
+ copy_from => secure_cp("$(sys.masterdir)"),
+ depth_search => recurse("inf"),
+ file_select => input_files,
+ action => immediate,
+ classes => results("bundle", "update_inputs");
+ update_inputs_not_kept::
+ "$(sys.inputdir)/cf_promises_validated"
+ delete => tidy;
+}
+
+body file_select exclude_vcs_files
+{
+ leaf_name => { "\.git.*" };
+ file_result => "!leaf_name";
+}
+
+body file_select input_files
+{
+ leaf_name => { @(main.input_name_patterns) };
+ file_result => "leaf_name";
+}
+
+body perms m(mode)
+{
+ mode => "$(mode)";
+}
+
+body copy_from secure_cp(from)
+{
+ any::
+ source => "$(from)";
+ compare => "digest";
+ encrypt => "true";
+ verify => "true";
+ !am_policy_hub::
+ servers => { "$(sys.policy_hub)" };
+ portnumber => "$(sys.policy_hub_port)";
}
+
+body action immediate
+{
+ ifelapsed => "0";
+}
+
+body classes if_repaired(x)
+{
+ promise_repaired => { "$(x)" };
+}
+
+body depth_search recurse(d)
+{
+ depth => "$(d)";
+ xdev => "true";
+}
+
+body depth_search recurse_basedir(d)
+{
+ include_basedir => "true";
+ depth => "$(d)";
+ exclude_dirs => { "\.svn", "\.git", "git-core" };
+}
+
+body delete tidy
+{
+ dirlinks => "delete";
+ rmdirs => "true";
+}
+
+body classes results(scope, class_prefix)
+{
+ 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" };
+} \ No newline at end of file