summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--controls/cf_agent.cf7
-rw-r--r--controls/cf_execd.cf10
-rw-r--r--controls/cf_monitord.cf8
-rw-r--r--controls/cf_runagent.cf5
-rw-r--r--controls/cf_serverd.cf30
-rw-r--r--failsafe.cf185
-rw-r--r--promises.cf29
-rw-r--r--services/main.cf24
-rw-r--r--update.cf10
10 files changed, 309 insertions, 0 deletions
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",
+ };
+}