1bundle agent ha_update
2{
3 methods:
4
5  enable_cfengine_enterprise_hub_ha::
6
7      "Hubs have am_policy_hub marker"
8        usebundle => ha_hubs_have_am_policy_hub_marker,
9        comment => "All hubs should have the am_policy_hub marker. This bundle
10                    ensures that standby hubs get this marker even though they are not
11                    bootstrapped to themselves";
12
13  enable_cfengine_enterprise_hub_ha.am_policy_hub::
14      "share_keys" usebundle => ha_share_hub_keys;
15      "sync_hub_data" usebundle => ha_hub_sync;
16
17  enable_cfengine_enterprise_hub_ha.!am_policy_hub::
18      "sync_agent_data" usebundle => ha_agent_sync;
19
20  enable_cfengine_enterprise_hub_ha.hub_data_synced::
21      "manage_keys" usebundle => manage_hub_synced_data;
22
23  enable_cfengine_enterprise_hub_ha.ha_replication_only_node::
24      "syncronize_master_hub_dat" usebundle => sync_master_hub_dat;
25}
26
27bundle agent ha_hubs_have_am_policy_hub_marker
28# @brief Ensure that all ha hub members have the am_policy_hub state marker
29{
30  classes:
31      # We know we need the am_policy_hub marker if any of our ips are found in the ha definition
32      "ha_hub_member" expression => iprange( $(ha_def.ips) );
33
34  files:
35
36    ha_hub_member::
37
38      "$(sys.statedir)/am_policy_hub" -> { "ENT-3328" }
39        create => "true",
40        comment => "This file is automatically created when bootstrapping to
41                    self, but in a clustered environment standby hubs bootstrap to the
42                    primary and this marker will not be automatically created.";
43
44}
45
46bundle agent ha_agent_sync
47{
48 files:
49  "$(sys.workdir)/policy_server.dat"
50      copy_from => ha_update_ha_no_backup_scp("$(ha_def.master_hub_location)", @(update_def.policy_servers)),
51      handle => "ha_cfengine_node_update_master_ip",
52      comment => "Update master hub IP on CFEngine node. This is causing that clients will try
53                  to contact active/master hub first.";
54
55  "$(sys.workdir)/ppkeys"
56      copy_from => ha_update_ha_no_backup_scp("$(ha_def.hubs_keys_location)", @(update_def.policy_servers)),
57      file_select => hub_all_keys,
58      depth_search => ha_update_ha_recurse("inf"),
59      handle => "ha_copy_hub_keys_to_nodes",
60      comment => "Download keys of all hubs working in HA cluster and store in client's ppkeys directory.
61                  This is important for establishing trusted connection  with standby hub(s) in
62                  case of failover.";
63}
64
65bundle agent ha_share_hub_keys
66{
67 files:
68   "$(ha_def.hubs_keys_location)"
69      copy_from => ha_update_no_backup_cp("$(sys.workdir)/ppkeys"),
70      file_select => hubs_keys_select,
71      handle => "ha_copy_hubs_keys",
72      depth_search => ha_update_recurse("1"),
73      comment => "Clients need to be able to download keys of all hubs working in
74                  HA cluster. This is needed to establish trusted connection
75                  with standby hubs in case of failover. In order to limit possibility
76                  of copying wrong keys hub keys are copied to separate directory first
77                  and only ppkeys_hubs is accessible by clients.";
78}
79
80bundle agent ha_hub_sync
81{
82 vars:
83  "exclude_files" slist => {"localhost.priv", "localhost.pub", @(ha_def.hub_shas)};
84 files:
85  "$(ha_def.ppkeys_staging)"
86      copy_from => ha_update_ha_no_backup_scp("$(sys.workdir)/ppkeys", @(update_def.standby_servers)),
87      file_select => ha_update_ex_list(@(exclude_files)),
88      handle => "ha_copy_client_keys_between_replica_set_servers",
89      depth_search => ha_update_recurse("1"),
90      classes => ha_update_if_repaired("hub_data_synced"),
91      comment => "Distribute all client keys between replica set servers. This is
92                  important in case of failover. Once clients keys are synchronized
93                  between all hubs working in HA cluster, clients will be able
94                  to authenticate and establish connection with all hubs working in HA cluster.";
95}
96
97bundle agent manage_hub_synced_data
98# @brief Manage trust of clients bootstrapped other hubs in cluster
99#
100# Ensures keys collected from other hubs are present in ppkeys so that the
101# agents bootstrapped to other hubs are trusted.
102{
103 files:
104
105   # Ensure that localhost.pub and localhost.priv are not in the directory of
106   # keys collected from standby hubs
107
108   "$(ha_def.ppkeys_staging)/localhost.*" -> { "ENT-3303" }
109      delete => ha_tidy,
110      handle => "manage_hub_synced_data_ppkeys_staging_localhost_absent",
111      comment => "We don't want localhost related key files from a standby
112                  server to end up over-writing the active hubs key. That will
113                  cause an identity crisis and trust issues.";
114
115   # Ensure that keys collected from standby hubs are present in this hubs
116   # ppkeys directory so that agents bootstrapped to standby hubs will be
117   # trusted.
118
119   "$(sys.workdir)/ppkeys"
120      copy_from => ha_update_no_backup_cp("$(ha_def.ppkeys_staging)"),
121      file_select => ha_update_plain,
122      depth_search => ha_update_recurse("1"),
123      handle => "ha_copy_staged_client_keys",
124      comment => "Copy staged client keys to ppkeys. First client keys are copied
125                  to ppkeys_staging directory and then to ppkeys. Only clients which
126                  keys are copied to ppkeys will be able to authenticate and connect
127                  to hub.";
128}
129
130bundle agent sync_master_hub_dat
131{
132 files:
133    "$(ha_def.master_hub_location)"
134      copy_from => ha_update_ha_no_backup_scp("$(ha_def.master_hub_location)", @(update_def.standby_servers)),
135      comment => "Update master hub IP on CFEngine node",
136      handle => "ha_cfengine_hub_update_master_ip";
137
138}
139
140body file_select hub_all_keys
141{
142  leaf_name => {".*.pub"};
143  file_result => "leaf_name";
144}
145
146body file_select hubs_keys_select
147{
148 search_size => irange("426", "426");
149 leaf_name => {escape("root-SHA=$(ha_def.config[$(update_def.standby_servers)][sha]).pub")};
150 file_result => "leaf_name";
151}
152
153body copy_from ha_update_ha_no_backup_scp(from,server)
154{
155 servers     => { "$(server)" };
156 source      => "$(from)";
157 compare     => "digest";
158 copy_backup => "false";
159 encrypt     => "true";
160}
161
162body depth_search ha_update_ha_recurse(d)
163{
164 depth => "$(d)";
165 exclude_dirs => { "\.svn", "\.git", "git-core" };
166}
167
168body depth_search ha_update_recurse(d)
169{
170      depth => "$(d)";
171      xdev  => "true";
172}
173
174body classes ha_update_if_repaired(x)
175{
176      promise_repaired => { "$(x)" };
177}
178
179body file_select ha_update_ex_list(names)
180{
181      leaf_name  => { @(names)};
182      file_result => "!leaf_name";
183}
184
185body file_select ha_update_plain
186{
187      file_types  => { "plain" };
188      file_result => "file_types";
189}
190
191body copy_from ha_update_no_backup_cp(from)
192{
193      source      => "$(from)";
194      copy_backup => "false";
195}
196
197body delete ha_tidy
198# @brief Copy of body delete tidy from the standard library
199{
200        dirlinks => "delete";
201        rmdirs   => "true";
202}
203