cloud-mu 3.5.0 → 3.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Berksfile +5 -2
- data/Berksfile.lock +135 -0
- data/ansible/roles/mu-base/README.md +33 -0
- data/ansible/roles/mu-base/defaults/main.yml +2 -0
- data/ansible/roles/mu-base/files/check_apm.cfg +1 -0
- data/ansible/roles/mu-base/files/check_apm.sh +18 -0
- data/ansible/roles/mu-base/files/check_disk.cfg +1 -0
- data/ansible/roles/mu-base/files/check_elastic_shards.cfg +1 -0
- data/ansible/roles/mu-base/files/check_elastic_shards.sh +12 -0
- data/ansible/roles/mu-base/files/check_logstash.cfg +1 -0
- data/ansible/roles/mu-base/files/check_logstash.sh +14 -0
- data/ansible/roles/mu-base/files/check_mem.cfg +1 -0
- data/ansible/roles/mu-base/files/check_updates.cfg +1 -0
- data/ansible/roles/mu-base/files/logrotate.conf +35 -0
- data/ansible/roles/mu-base/files/nrpe-apm-sudo +1 -0
- data/ansible/roles/mu-base/files/nrpe-elasticshards-sudo +2 -0
- data/ansible/roles/mu-base/handlers/main.yml +5 -0
- data/ansible/roles/mu-base/meta/main.yml +53 -0
- data/ansible/roles/mu-base/tasks/main.yml +113 -0
- data/ansible/roles/mu-base/templates/nrpe.cfg.j2 +231 -0
- data/ansible/roles/mu-base/tests/inventory +2 -0
- data/ansible/roles/mu-base/tests/test.yml +5 -0
- data/ansible/roles/mu-base/vars/main.yml +1 -0
- data/ansible/roles/mu-compliance/README.md +33 -0
- data/ansible/roles/mu-compliance/defaults/main.yml +2 -0
- data/ansible/roles/mu-compliance/files/U_MS_Windows_Server_2016_V2R1_STIG_SCAP_1-2_Benchmark.xml +15674 -0
- data/ansible/roles/mu-compliance/files/U_MS_Windows_Server_2019_V2R1_STIG_SCAP_1-2_Benchmark.xml +17553 -0
- data/ansible/roles/mu-compliance/handlers/main.yml +2 -0
- data/ansible/roles/mu-compliance/meta/main.yml +53 -0
- data/ansible/roles/mu-compliance/tasks/main.yml +45 -0
- data/ansible/roles/mu-compliance/tests/inventory +2 -0
- data/ansible/roles/mu-compliance/tests/test.yml +5 -0
- data/ansible/roles/mu-compliance/vars/main.yml +4 -0
- data/ansible/roles/mu-elastic/README.md +51 -0
- data/ansible/roles/mu-elastic/defaults/main.yml +2 -0
- data/ansible/roles/mu-elastic/files/jvm.options +93 -0
- data/ansible/roles/mu-elastic/handlers/main.yml +10 -0
- data/ansible/roles/mu-elastic/meta/main.yml +52 -0
- data/ansible/roles/mu-elastic/tasks/main.yml +186 -0
- data/ansible/roles/mu-elastic/templates/elasticsearch.yml.j2 +110 -0
- data/ansible/roles/mu-elastic/templates/kibana.yml.j2 +131 -0
- data/ansible/roles/mu-elastic/templates/password_set.expect.j2 +19 -0
- data/ansible/roles/mu-elastic/tests/inventory +2 -0
- data/ansible/roles/mu-elastic/tests/test.yml +5 -0
- data/ansible/roles/mu-elastic/vars/main.yml +2 -0
- data/ansible/roles/mu-logstash/README.md +51 -0
- data/ansible/roles/mu-logstash/defaults/main.yml +2 -0
- data/ansible/roles/mu-logstash/files/02-beats-input.conf +5 -0
- data/ansible/roles/mu-logstash/files/10-rails-filter.conf +16 -0
- data/ansible/roles/mu-logstash/files/jvm.options +84 -0
- data/ansible/roles/mu-logstash/files/logstash.yml +304 -0
- data/ansible/roles/mu-logstash/handlers/main.yml +20 -0
- data/ansible/roles/mu-logstash/meta/main.yml +52 -0
- data/ansible/roles/mu-logstash/tasks/main.yml +254 -0
- data/ansible/roles/mu-logstash/templates/20-cloudtrail.conf.j2 +28 -0
- data/ansible/roles/mu-logstash/templates/30-elasticsearch-output.conf.j2 +19 -0
- data/ansible/roles/mu-logstash/templates/apm-server.yml.j2 +33 -0
- data/ansible/roles/mu-logstash/templates/heartbeat.yml.j2 +29 -0
- data/ansible/roles/mu-logstash/templates/nginx/apm.conf.j2 +25 -0
- data/ansible/roles/mu-logstash/templates/nginx/default.conf.j2 +56 -0
- data/ansible/roles/mu-logstash/templates/nginx/elastic.conf.j2 +27 -0
- data/ansible/roles/mu-logstash/tests/inventory +2 -0
- data/ansible/roles/mu-logstash/tests/test.yml +5 -0
- data/ansible/roles/mu-logstash/vars/main.yml +2 -0
- data/ansible/roles/mu-rdp/README.md +33 -0
- data/ansible/roles/mu-rdp/meta/main.yml +53 -0
- data/ansible/roles/mu-rdp/tasks/main.yml +9 -0
- data/ansible/roles/mu-rdp/tests/inventory +2 -0
- data/ansible/roles/mu-rdp/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/tasks/main.yml +3 -0
- data/bin/mu-ansible-secret +1 -1
- data/bin/mu-aws-setup +4 -3
- data/bin/mu-azure-setup +5 -5
- data/bin/mu-configure +25 -17
- data/bin/mu-firewall-allow-clients +1 -0
- data/bin/mu-gcp-setup +3 -3
- data/bin/mu-load-config.rb +1 -0
- data/bin/mu-node-manage +66 -33
- data/bin/mu-self-update +2 -2
- data/bin/mu-upload-chef-artifacts +6 -1
- data/bin/mu-user-manage +1 -1
- data/cloud-mu.gemspec +25 -23
- data/cookbooks/firewall/CHANGELOG.md +417 -224
- data/cookbooks/firewall/LICENSE +202 -0
- data/cookbooks/firewall/README.md +153 -126
- data/cookbooks/firewall/TODO.md +6 -0
- data/cookbooks/firewall/attributes/firewalld.rb +7 -0
- data/cookbooks/firewall/attributes/iptables.rb +3 -3
- data/cookbooks/firewall/chefignore +115 -0
- data/cookbooks/firewall/libraries/helpers.rb +5 -0
- data/cookbooks/firewall/libraries/helpers_firewalld.rb +1 -1
- data/cookbooks/firewall/libraries/helpers_firewalld_dbus.rb +72 -0
- data/cookbooks/firewall/libraries/helpers_iptables.rb +3 -3
- data/cookbooks/firewall/libraries/helpers_nftables.rb +170 -0
- data/cookbooks/firewall/libraries/helpers_ufw.rb +7 -0
- data/cookbooks/firewall/libraries/helpers_windows.rb +8 -9
- data/cookbooks/firewall/libraries/provider_firewall_firewalld.rb +9 -9
- data/cookbooks/firewall/libraries/provider_firewall_iptables.rb +7 -7
- data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu.rb +12 -8
- data/cookbooks/firewall/libraries/provider_firewall_iptables_ubuntu1404.rb +13 -9
- data/cookbooks/firewall/libraries/provider_firewall_rule.rb +1 -1
- data/cookbooks/firewall/libraries/provider_firewall_ufw.rb +5 -5
- data/cookbooks/firewall/libraries/provider_firewall_windows.rb +4 -4
- data/cookbooks/firewall/libraries/resource_firewall_rule.rb +3 -3
- data/cookbooks/firewall/metadata.json +40 -1
- data/cookbooks/firewall/metadata.rb +15 -0
- data/cookbooks/firewall/recipes/default.rb +7 -7
- data/cookbooks/firewall/recipes/disable_firewall.rb +1 -1
- data/cookbooks/firewall/recipes/firewalld.rb +87 -0
- data/cookbooks/firewall/renovate.json +18 -0
- data/cookbooks/firewall/resources/firewalld.rb +28 -0
- data/cookbooks/firewall/resources/firewalld_config.rb +39 -0
- data/cookbooks/firewall/resources/firewalld_helpers.rb +106 -0
- data/cookbooks/firewall/resources/firewalld_icmptype.rb +88 -0
- data/cookbooks/firewall/resources/firewalld_ipset.rb +104 -0
- data/cookbooks/firewall/resources/firewalld_policy.rb +115 -0
- data/cookbooks/firewall/resources/firewalld_service.rb +98 -0
- data/cookbooks/firewall/resources/firewalld_zone.rb +118 -0
- data/cookbooks/firewall/resources/nftables.rb +71 -0
- data/cookbooks/firewall/resources/nftables_rule.rb +113 -0
- data/cookbooks/mu-activedirectory/Berksfile +1 -1
- data/cookbooks/mu-activedirectory/metadata.rb +1 -1
- data/cookbooks/mu-firewall/metadata.rb +2 -2
- data/cookbooks/mu-master/Berksfile +4 -3
- data/cookbooks/mu-master/attributes/default.rb +5 -2
- data/cookbooks/mu-master/files/default/check_elastic.sh +761 -0
- data/cookbooks/mu-master/files/default/check_kibana.rb +45 -0
- data/cookbooks/mu-master/libraries/mu.rb +24 -0
- data/cookbooks/mu-master/metadata.rb +5 -5
- data/cookbooks/mu-master/recipes/default.rb +31 -20
- data/cookbooks/mu-master/recipes/firewall-holes.rb +5 -0
- data/cookbooks/mu-master/recipes/init.rb +58 -19
- data/cookbooks/mu-master/recipes/update_nagios_only.rb +251 -178
- data/cookbooks/mu-master/templates/default/nagios.conf.erb +5 -11
- data/cookbooks/mu-master/templates/default/web_app.conf.erb +3 -0
- data/cookbooks/mu-php54/Berksfile +1 -1
- data/cookbooks/mu-php54/metadata.rb +2 -2
- data/cookbooks/mu-tools/Berksfile +2 -3
- data/cookbooks/mu-tools/attributes/default.rb +3 -4
- data/cookbooks/mu-tools/files/amazon/etc/bashrc +90 -0
- data/cookbooks/mu-tools/files/amazon/etc/login.defs +292 -0
- data/cookbooks/mu-tools/files/amazon/etc/profile +77 -0
- data/cookbooks/mu-tools/files/amazon/etc/security/limits.conf +63 -0
- data/cookbooks/mu-tools/files/amazon/etc/sysconfig/init +19 -0
- data/cookbooks/mu-tools/files/amazon/etc/sysctl.conf +82 -0
- data/cookbooks/mu-tools/files/amazon-2023/etc/login.defs +294 -0
- data/cookbooks/mu-tools/files/default/logrotate.conf +35 -0
- data/cookbooks/mu-tools/files/default/nrpe_conf_d.pp +0 -0
- data/cookbooks/mu-tools/libraries/helper.rb +21 -9
- data/cookbooks/mu-tools/metadata.rb +4 -4
- data/cookbooks/mu-tools/recipes/apply_security.rb +3 -2
- data/cookbooks/mu-tools/recipes/aws_api.rb +23 -5
- data/cookbooks/mu-tools/recipes/base_repositories.rb +4 -1
- data/cookbooks/mu-tools/recipes/gcloud.rb +56 -56
- data/cookbooks/mu-tools/recipes/nagios.rb +1 -1
- data/cookbooks/mu-tools/recipes/nrpe.rb +20 -2
- data/cookbooks/mu-tools/recipes/rsyslog.rb +12 -1
- data/cookbooks/mu-tools/recipes/set_local_fw.rb +1 -1
- data/data_bags/nagios_services/apm_backend_connect.json +5 -0
- data/data_bags/nagios_services/apm_listen.json +5 -0
- data/data_bags/nagios_services/elastic_shards.json +5 -0
- data/data_bags/nagios_services/logstash.json +5 -0
- data/data_bags/nagios_services/rhel7_updates.json +8 -0
- data/extras/image-generators/AWS/centos7.yaml +1 -0
- data/extras/image-generators/AWS/rhel7.yaml +21 -0
- data/extras/image-generators/AWS/win2k12r2.yaml +1 -0
- data/extras/image-generators/AWS/win2k16.yaml +1 -0
- data/extras/image-generators/AWS/win2k19.yaml +1 -0
- data/extras/list-stock-amis +0 -0
- data/extras/ruby_rpm/muby.spec +8 -5
- data/extras/vault_tools/export_vaults.sh +1 -1
- data/extras/vault_tools/recreate_vaults.sh +0 -0
- data/extras/vault_tools/test_vaults.sh +0 -0
- data/install/deprecated-bash-library.sh +1 -1
- data/install/installer +4 -2
- data/modules/mommacat.ru +3 -1
- data/modules/mu/adoption.rb +1 -1
- data/modules/mu/cloud/dnszone.rb +2 -2
- data/modules/mu/cloud/machine_images.rb +26 -25
- data/modules/mu/cloud/resource_base.rb +213 -182
- data/modules/mu/cloud/server_pool.rb +1 -1
- data/modules/mu/cloud/ssh_sessions.rb +7 -5
- data/modules/mu/cloud/wrappers.rb +2 -2
- data/modules/mu/cloud.rb +1 -1
- data/modules/mu/config/bucket.rb +1 -1
- data/modules/mu/config/function.rb +6 -1
- data/modules/mu/config/loadbalancer.rb +24 -2
- data/modules/mu/config/ref.rb +12 -0
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +42 -9
- data/modules/mu/config/server.rb +43 -27
- data/modules/mu/config/tail.rb +19 -10
- data/modules/mu/config.rb +6 -5
- data/modules/mu/defaults/AWS.yaml +78 -114
- data/modules/mu/deploy.rb +9 -2
- data/modules/mu/groomer.rb +12 -4
- data/modules/mu/groomers/ansible.rb +104 -20
- data/modules/mu/groomers/chef.rb +15 -6
- data/modules/mu/master.rb +9 -4
- data/modules/mu/mommacat/daemon.rb +4 -2
- data/modules/mu/mommacat/naming.rb +1 -2
- data/modules/mu/mommacat/storage.rb +7 -2
- data/modules/mu/mommacat.rb +33 -6
- data/modules/mu/providers/aws/database.rb +161 -8
- data/modules/mu/providers/aws/dnszone.rb +11 -6
- data/modules/mu/providers/aws/endpoint.rb +81 -6
- data/modules/mu/providers/aws/firewall_rule.rb +254 -172
- data/modules/mu/providers/aws/function.rb +65 -3
- data/modules/mu/providers/aws/loadbalancer.rb +39 -28
- data/modules/mu/providers/aws/log.rb +2 -1
- data/modules/mu/providers/aws/role.rb +25 -7
- data/modules/mu/providers/aws/server.rb +36 -12
- data/modules/mu/providers/aws/server_pool.rb +237 -127
- data/modules/mu/providers/aws/storage_pool.rb +7 -1
- data/modules/mu/providers/aws/user.rb +1 -1
- data/modules/mu/providers/aws/userdata/linux.erb +6 -2
- data/modules/mu/providers/aws/userdata/windows.erb +7 -5
- data/modules/mu/providers/aws/vpc.rb +49 -25
- data/modules/mu/providers/aws.rb +13 -8
- data/modules/mu/providers/azure/container_cluster.rb +1 -1
- data/modules/mu/providers/azure/loadbalancer.rb +2 -2
- data/modules/mu/providers/azure/server.rb +5 -2
- data/modules/mu/providers/azure/userdata/linux.erb +1 -1
- data/modules/mu/providers/azure.rb +11 -8
- data/modules/mu/providers/cloudformation/dnszone.rb +1 -1
- data/modules/mu/providers/google/container_cluster.rb +15 -2
- data/modules/mu/providers/google/folder.rb +2 -1
- data/modules/mu/providers/google/function.rb +130 -4
- data/modules/mu/providers/google/habitat.rb +2 -1
- data/modules/mu/providers/google/loadbalancer.rb +407 -160
- data/modules/mu/providers/google/role.rb +16 -3
- data/modules/mu/providers/google/server.rb +5 -1
- data/modules/mu/providers/google/user.rb +25 -18
- data/modules/mu/providers/google/userdata/linux.erb +1 -1
- data/modules/mu/providers/google/vpc.rb +53 -7
- data/modules/mu/providers/google.rb +39 -39
- data/modules/mu.rb +8 -8
- data/modules/tests/elk.yaml +46 -0
- data/test/mu-master-test/controls/all_in_one.rb +1 -1
- metadata +207 -112
- data/cookbooks/firewall/CONTRIBUTING.md +0 -2
- data/cookbooks/firewall/MAINTAINERS.md +0 -19
- data/cookbooks/firewall/libraries/matchers.rb +0 -30
- data/extras/image-generators/AWS/rhel71.yaml +0 -17
@@ -19,6 +19,7 @@ module MU
|
|
19
19
|
class Groomer
|
20
20
|
# Support for Ansible as a host configuration management layer.
|
21
21
|
class Ansible
|
22
|
+
require 'open3'
|
22
23
|
|
23
24
|
# Failure to load or create a deploy
|
24
25
|
class NoAnsibleExecError < MuError;
|
@@ -77,7 +78,7 @@ module MU
|
|
77
78
|
# @param data [Hash]: Data to save
|
78
79
|
# @param permissions [Boolean]: If true, save the secret under the current active deploy (if any), rather than in the global location for this user
|
79
80
|
# @param deploy_dir [String]: If permissions is +true+, save the secret here
|
80
|
-
def self.saveSecret(vault: nil, item: nil, data: nil, permissions: false, deploy_dir: nil)
|
81
|
+
def self.saveSecret(vault: nil, item: nil, data: nil, permissions: false, deploy_dir: nil, quiet: false)
|
81
82
|
|
82
83
|
if vault.nil? or vault.empty? or item.nil? or item.empty?
|
83
84
|
raise MuError, "Must call saveSecret with vault and item names"
|
@@ -86,6 +87,7 @@ module MU
|
|
86
87
|
raise MuError, "Ansible vault/item names cannot include forward slashes"
|
87
88
|
end
|
88
89
|
pwfile = vaultPasswordFile
|
90
|
+
vault_cmd = %Q{#{ansibleExecDir}/ansible-vault}
|
89
91
|
|
90
92
|
dir = if permissions
|
91
93
|
if deploy_dir
|
@@ -104,7 +106,7 @@ module MU
|
|
104
106
|
FileUtils.mkdir_p(dir, mode: 0700)
|
105
107
|
end
|
106
108
|
|
107
|
-
if File.exist?(path)
|
109
|
+
if File.exist?(path) and !quiet
|
108
110
|
MU.log "Overwriting existing vault #{vault} item #{item}"
|
109
111
|
end
|
110
112
|
|
@@ -112,14 +114,36 @@ module MU
|
|
112
114
|
f.write data.to_yaml
|
113
115
|
}
|
114
116
|
|
115
|
-
cmd = %Q{#{
|
116
|
-
MU.log cmd
|
117
|
+
cmd = %Q{#{vault_cmd} encrypt #{path} --vault-password-file #{pwfile}}
|
118
|
+
MU.log cmd if !quiet
|
117
119
|
raise MuError, "Failed Ansible command: #{cmd}" if !system(cmd)
|
120
|
+
|
121
|
+
# If we're stashing things under a deploy, go ahead and munge them into
|
122
|
+
# variables that actual Ansible tasks can get at
|
123
|
+
if permissions
|
124
|
+
encrypted_string = File.read(path).chomp
|
125
|
+
dir = (deploy_dir ? deploy_dir : MU.mommacat.deploy_dir)+"/ansible"
|
126
|
+
FileUtils.mkdir_p(dir, mode: 0700) if !Dir.exist?(dir)
|
127
|
+
FileUtils.mkdir_p(dir+"/vars", mode: 0700) if !Dir.exist?(dir+"/vars")
|
128
|
+
vars_file = "#{dir}/vars/#{vault}.yml"
|
129
|
+
|
130
|
+
vars = if File.exist?(vars_file)
|
131
|
+
YAML.load(File.read(vars_file))
|
132
|
+
else
|
133
|
+
{}
|
134
|
+
end
|
135
|
+
vars[item] = encrypted_string
|
136
|
+
File.open(vars_file, File::CREAT|File::RDWR|File::TRUNC, 0600) { |f|
|
137
|
+
f.flock(File::LOCK_EX)
|
138
|
+
f.puts vars.to_yaml
|
139
|
+
f.flock(File::LOCK_UN)
|
140
|
+
}
|
141
|
+
end
|
118
142
|
end
|
119
143
|
|
120
144
|
# see {MU::Groomer::Ansible.saveSecret}
|
121
|
-
def saveSecret(vault: @server.mu_name, item: nil, data: nil, permissions: true)
|
122
|
-
self.class.saveSecret(vault: vault, item: item, data: data, permissions: permissions, deploy_dir: @server.deploy.deploy_dir)
|
145
|
+
def saveSecret(vault: @server.mu_name, item: nil, data: nil, permissions: true, quiet: false)
|
146
|
+
self.class.saveSecret(vault: vault, item: item, data: data, permissions: permissions, deploy_dir: @server.deploy.deploy_dir, quiet: quiet)
|
123
147
|
end
|
124
148
|
|
125
149
|
# Retrieve sensitive data, which hopefully we're storing and retrieving
|
@@ -128,7 +152,7 @@ module MU
|
|
128
152
|
# @param item [String]: The item within the repository to retrieve
|
129
153
|
# @param field [String]: OPTIONAL - A specific field within the item to return.
|
130
154
|
# @return [Hash]
|
131
|
-
def self.getSecret(vault: nil, item: nil, field: nil, deploy_dir: nil)
|
155
|
+
def self.getSecret(vault: nil, item: nil, field: nil, deploy_dir: nil, quiet: false, cmd_only: false)
|
132
156
|
if vault.nil? or vault.empty?
|
133
157
|
raise MuError, "Must call getSecret with at least a vault name"
|
134
158
|
end
|
@@ -137,7 +161,7 @@ module MU
|
|
137
161
|
dir = nil
|
138
162
|
try = [secret_dir+"/"+vault]
|
139
163
|
try << deploy_dir+"/ansible/vaults/"+vault if deploy_dir
|
140
|
-
try << MU.mommacat.deploy_dir+"/ansible/vaults/"+vault if MU.mommacat.deploy_dir
|
164
|
+
try << MU.mommacat.deploy_dir+"/ansible/vaults/"+vault if MU.mommacat and MU.mommacat.deploy_dir
|
141
165
|
try.each { |maybe_dir|
|
142
166
|
if Dir.exist?(maybe_dir) and (item.nil? or File.exist?(maybe_dir+"/"+item))
|
143
167
|
dir = maybe_dir
|
@@ -155,7 +179,8 @@ module MU
|
|
155
179
|
raise MuNoSuchSecret, "No such item #{item} in vault #{vault}"
|
156
180
|
end
|
157
181
|
cmd = %Q{#{ansibleExecDir}/ansible-vault view #{itempath} --vault-password-file #{pwfile}}
|
158
|
-
|
182
|
+
return cmd if cmd_only
|
183
|
+
MU.log cmd if !quiet
|
159
184
|
a = `#{cmd}`
|
160
185
|
# If we happen to have stored recognizeable JSON or YAML, return it
|
161
186
|
# as parsed, which is a behavior we're used to from Chef vault.
|
@@ -187,8 +212,8 @@ module MU
|
|
187
212
|
end
|
188
213
|
|
189
214
|
# see {MU::Groomer::Ansible.getSecret}
|
190
|
-
def getSecret(vault:
|
191
|
-
self.class.getSecret(vault: vault, item: item, field: field, deploy_dir: @server.deploy.deploy_dir)
|
215
|
+
def getSecret(vault: @server.mu_name, item: nil, field: nil, quiet: false, cmd_only: false)
|
216
|
+
self.class.getSecret(vault: vault, item: item, field: field, deploy_dir: @server.deploy.deploy_dir, quiet: quiet, cmd_only: cmd_only)
|
192
217
|
end
|
193
218
|
|
194
219
|
# Delete a Ansible data bag / Vault
|
@@ -259,6 +284,16 @@ module MU
|
|
259
284
|
|
260
285
|
cmd = %Q{cd #{@ansible_path} && echo "#{purpose}" && #{@ansible_execs}/ansible-playbook -i hosts #{playbook} --limit=#{@server.windows? ? @server.canonicalIP : @server.mu_name} --vault-password-file #{pwfile} --timeout=30 --vault-password-file #{@ansible_path}/.vault_pw -u #{ssh_user}}
|
261
286
|
|
287
|
+
if @server.config['vault_access']
|
288
|
+
@server.config['vault_access'].each { |entry|
|
289
|
+
vault = entry['vault'] || @server.deploy.deploy_id
|
290
|
+
begin
|
291
|
+
MU.log "To retrieve secret #{vault}:#{entry['item']} - "+getSecret(vault: vault, item: entry['item'], cmd_only: true), MU::SUMMARY
|
292
|
+
rescue MuNoSuchSecret
|
293
|
+
end
|
294
|
+
}
|
295
|
+
end
|
296
|
+
|
262
297
|
retries = 0
|
263
298
|
begin
|
264
299
|
MU.log cmd
|
@@ -315,8 +350,13 @@ module MU
|
|
315
350
|
play["become"] = "yes"
|
316
351
|
end
|
317
352
|
|
318
|
-
if @server.
|
319
|
-
play["roles"] =
|
353
|
+
if @server.windows?
|
354
|
+
play["roles"] = ["mu-windows"]
|
355
|
+
else
|
356
|
+
play["roles"] = ["mu-base"]
|
357
|
+
end
|
358
|
+
if @server.config['run_list']
|
359
|
+
play["roles"].concat(@server.config['run_list'])
|
320
360
|
end
|
321
361
|
|
322
362
|
if @server.config['ansible_vars']
|
@@ -326,6 +366,7 @@ module MU
|
|
326
366
|
if @server.windows?
|
327
367
|
play["vars"] ||= {}
|
328
368
|
play["vars"]["ansible_connection"] = "winrm"
|
369
|
+
play["vars"]['ansible_python_interpreter'] = "c:/bin/python/python310/python.exe"
|
329
370
|
play["vars"]["ansible_winrm_scheme"] = "https"
|
330
371
|
play["vars"]["ansible_winrm_transport"] = "ntlm"
|
331
372
|
play["vars"]["ansible_winrm_server_cert_validation"] = "ignore" # XXX this sucks; use Mu_CA.pem if we can get it to work
|
@@ -355,18 +396,43 @@ module MU
|
|
355
396
|
allvars = {
|
356
397
|
"mu_deployment" => MU::Config.stripConfig(@server.deploy.deployment),
|
357
398
|
"mu_service_name" => @config["name"],
|
399
|
+
"mu_name" => @server.mu_name,
|
400
|
+
"mu_deploy_id" => @server.deploy.deploy_id,
|
358
401
|
"mu_canonical_ip" => @server.canonicalIP,
|
359
402
|
"mu_admin_email" => $MU_CFG['mu_admin_email'],
|
360
|
-
"mu_environment" => MU.environment.downcase
|
403
|
+
"mu_environment" => MU.environment.downcase,
|
404
|
+
"mu_vaults" => {}
|
361
405
|
}
|
362
406
|
allvars['mu_deployment']['ssh_public_key'] = @server.deploy.ssh_public_key
|
363
407
|
|
408
|
+
vaultdir = @ansible_path+"/vaults"
|
409
|
+
if Dir.exist?(vaultdir)
|
410
|
+
Dir.entries(vaultdir).each { |v|
|
411
|
+
next if !File.directory?(vaultdir+"/"+v)
|
412
|
+
next if [".", ".."].include?(v)
|
413
|
+
Dir.entries(vaultdir+"/"+v).each { |i|
|
414
|
+
next if File.directory?(vaultdir+"/"+v+"/"+i)
|
415
|
+
value = getSecret(vault: v, item: i, quiet: true)
|
416
|
+
next if !value # ignore corrupted data
|
417
|
+
|
418
|
+
# Ansible struggles to actually use this. The only thing that
|
419
|
+
# seems to work is writing it (decrypted) to a tmp file on the
|
420
|
+
# target host then reading that back, which is both ugly and
|
421
|
+
# insecure. None of these workarounds seem to do the thing:
|
422
|
+
# https://github.com/ansible/ansible/issues/24425
|
423
|
+
allvars["mu_vaults"][v] ||= {}
|
424
|
+
allvars["mu_vaults"][v].merge!(YAML.load(self.class.encryptString(value.to_yaml, i)))
|
425
|
+
}
|
426
|
+
}
|
427
|
+
end
|
428
|
+
|
364
429
|
if @server.config['cloud'] == "AWS"
|
365
430
|
allvars["ec2"] = MU.structToHash(@server.cloud_desc, stringify_keys: true)
|
366
431
|
end
|
367
432
|
|
368
433
|
if @server.windows?
|
369
434
|
allvars['windows_admin_username'] = @config['windows_admin_username']
|
435
|
+
allvars['ansible_python_interpreter'] = "c:/bin/python/python310/python.exe"
|
370
436
|
end
|
371
437
|
|
372
438
|
if !@server.cloud.nil?
|
@@ -380,6 +446,9 @@ module MU
|
|
380
446
|
}
|
381
447
|
|
382
448
|
groupvars = allvars.dup
|
449
|
+
if @server.windows? and @server.mu_windows_name
|
450
|
+
groupvars['mu_windows_name'] = @server.mu_windows_name
|
451
|
+
end
|
383
452
|
if @server.deploy.original_config.has_key?('parameters')
|
384
453
|
groupvars["mu_parameters"] = @server.deploy.original_config['parameters']
|
385
454
|
end
|
@@ -433,17 +502,23 @@ module MU
|
|
433
502
|
found
|
434
503
|
end
|
435
504
|
|
436
|
-
# Encrypt a string using +ansible-vault encrypt_string+ and
|
437
|
-
# the results to +STDOUT+.
|
438
|
-
# @param name [String]: The variable name to use for the string's YAML key
|
505
|
+
# Encrypt a string using +ansible-vault encrypt_string+ and return +STDOUT+
|
439
506
|
# @param string [String]: The string to encrypt
|
440
|
-
|
507
|
+
# @param name [String]: A name to use for the string's YAML key
|
508
|
+
def self.encryptString(string, name = nil)
|
441
509
|
pwfile = vaultPasswordFile
|
442
510
|
cmd = %Q{#{ansibleExecDir}/ansible-vault}
|
443
|
-
|
511
|
+
|
512
|
+
stdout, status = if name
|
513
|
+
Open3.capture2(cmd, "encrypt_string", string, "--name", name, "--vault-password-file", pwfile)
|
514
|
+
else
|
515
|
+
Open3.capture2(cmd, "encrypt_string", string, "--vault-password-file", pwfile)
|
516
|
+
end
|
517
|
+
|
518
|
+
if !status.success?
|
444
519
|
raise MuError, "Failed Ansible command: #{cmd} encrypt_string <redacted> --name #{name} --vault-password-file"
|
445
520
|
end
|
446
|
-
|
521
|
+
stdout.strip
|
447
522
|
end
|
448
523
|
|
449
524
|
# Hunt down and return a path for a Python executable
|
@@ -630,6 +705,14 @@ module MU
|
|
630
705
|
File.symlink(MU.myRoot+"/ansible/roles/"+role, roledir+"/"+role)
|
631
706
|
}
|
632
707
|
|
708
|
+
coldir = "#{Etc.getpwuid(Process.uid).dir}/.ansible/collections/ansible_collections"
|
709
|
+
["ansible.windows", "community.general.gem"].each { |coll|
|
710
|
+
%x{#{@ansible_execs}/ansible-galaxy collection list -p "#{coldir}"}
|
711
|
+
if $? != 0
|
712
|
+
system(%Q{#{@ansible_execs}/ansible-galaxy}, "collection", "install", coll, "-p", coldir)
|
713
|
+
end
|
714
|
+
}
|
715
|
+
|
633
716
|
if @server.config['run_list']
|
634
717
|
@server.config['run_list'].each { |role|
|
635
718
|
found = false
|
@@ -655,6 +738,7 @@ module MU
|
|
655
738
|
end
|
656
739
|
}
|
657
740
|
end
|
741
|
+
|
658
742
|
end
|
659
743
|
|
660
744
|
# Upload the certificate to a Chef Vault for this node
|
data/modules/mu/groomers/chef.rb
CHANGED
@@ -58,6 +58,9 @@ module MU
|
|
58
58
|
require 'chef/knife/ssh'
|
59
59
|
require 'mu/monkey_patches/chef_knife_ssh'
|
60
60
|
require 'chef/knife/bootstrap'
|
61
|
+
require 'chef/knife/bootstrap/train_connector'
|
62
|
+
require 'chef/knife/bootstrap/chef_vault_handler'
|
63
|
+
require 'chef/knife/bootstrap/client_builder'
|
61
64
|
require 'chef/knife/node_delete'
|
62
65
|
require 'chef/knife/client_delete'
|
63
66
|
require 'chef/knife/data_bag_delete'
|
@@ -96,11 +99,11 @@ module MU
|
|
96
99
|
}
|
97
100
|
end
|
98
101
|
|
99
|
-
|
102
|
+
@@knife = "cd #{MU.myRoot} && env -i HOME=#{Etc.getpwnam(MU.mu_user).dir} PATH=/usr/local/ruby-current/bin:/opt/chef/embedded/bin:/usr/bin:/usr/sbin knife"
|
100
103
|
# The canonical path to invoke Chef's *knife* utility with a clean environment.
|
101
104
|
# @return [String]
|
102
|
-
def self.knife
|
103
|
-
|
105
|
+
def self.knife
|
106
|
+
@@knife
|
104
107
|
end
|
105
108
|
|
106
109
|
attr_reader :knife
|
@@ -218,7 +221,7 @@ module MU
|
|
218
221
|
end
|
219
222
|
|
220
223
|
# see {MU::Groomer::Chef.getSecret}
|
221
|
-
def getSecret(vault:
|
224
|
+
def getSecret(vault: @server.mu_name, item: nil, field: nil)
|
222
225
|
self.class.getSecret(vault: vault, item: item, field: field)
|
223
226
|
end
|
224
227
|
|
@@ -618,8 +621,10 @@ module MU
|
|
618
621
|
kb.name_args = "#{canonical_addr}"
|
619
622
|
kb.config[:distro] = 'chef-full'
|
620
623
|
kb.config[:ssh_user] = ssh_user
|
624
|
+
kb.config[:ssh_verify_host_key] = :accept_new
|
621
625
|
kb.config[:forward_agent] = ssh_user
|
622
626
|
kb.config[:identity_file] = "#{Etc.getpwuid(Process.uid).dir}/.ssh/#{ssh_key_name}"
|
627
|
+
kb.config[:ssh_identity_file] = "#{Etc.getpwuid(Process.uid).dir}/.ssh/#{ssh_key_name}"
|
623
628
|
else
|
624
629
|
kb = ::Chef::Knife::BootstrapWindowsWinrm.new([@server.mu_name])
|
625
630
|
kb.name_args = [@server.mu_name]
|
@@ -628,6 +633,7 @@ module MU
|
|
628
633
|
kb.config[:winrm_port] = 5986
|
629
634
|
kb.config[:session_timeout] = timeout
|
630
635
|
kb.config[:operation_timeout] = timeout
|
636
|
+
# kb.config[:bootstrap_curl_options] = ""
|
631
637
|
if retries % 2 == 0
|
632
638
|
kb.config[:host] = canonical_addr
|
633
639
|
kb.config[:winrm_authentication_protocol] = :basic
|
@@ -658,7 +664,9 @@ module MU
|
|
658
664
|
kb.config[:json_attribs] = JSON.generate(json_attribs) if json_attribs.size > 1
|
659
665
|
kb.config[:run_list] = run_list
|
660
666
|
kb.config[:chef_node_name] = @server.mu_name
|
667
|
+
kb.config[:bootstrap_product] = "chef"
|
661
668
|
kb.config[:bootstrap_version] = MU.chefVersion
|
669
|
+
kb.config[:channel] = "stable"
|
662
670
|
# XXX key off of MU verbosity level
|
663
671
|
kb.config[:log_level] = :debug
|
664
672
|
# kb.config[:ssh_gateway] = "#{nat_ssh_user}@#{nat_ssh_host}" if !nat_ssh_host.nil? # Breaking bootsrap
|
@@ -898,7 +906,7 @@ retry
|
|
898
906
|
vaults_to_clean.each { |vault|
|
899
907
|
MU::MommaCat.lock("vault-#{vault['vault']}", false, true)
|
900
908
|
MU.log "Purging unknown clients from #{vault['vault']} #{vault['item']}", MU::DEBUG
|
901
|
-
output = %x{#{
|
909
|
+
output = %x{#{knife} data bag show "#{vault['vault']}" "#{vault['item']}_keys" --format json}
|
902
910
|
# This is an ugly workaround for --clean-unknown-clients, which in
|
903
911
|
# fact cleans known clients.
|
904
912
|
if output
|
@@ -941,7 +949,7 @@ retry
|
|
941
949
|
MU::MommaCat.lock("vault-#{vault}", false, true)
|
942
950
|
MU.log "Granting #{host} access to #{vault} #{item}"
|
943
951
|
begin
|
944
|
-
::Chef::Knife.run(['vault', 'update', vault, item, "--
|
952
|
+
::Chef::Knife.run(['vault', 'update', vault, item, "--clients", "#{host}"])
|
945
953
|
rescue StandardError => e
|
946
954
|
MU.log e.inspect, MU::ERR, details: caller
|
947
955
|
end
|
@@ -1087,6 +1095,7 @@ retry
|
|
1087
1095
|
def grantSecretAccess(vault, item)
|
1088
1096
|
return if @secrets_granted["#{vault}:#{item}"] == item
|
1089
1097
|
self.class.grantSecretAccess(@server.mu_name, vault, item)
|
1098
|
+
MU.log %Q{To retrieve secret #{vault}:#{item} - #{self.class.knife} vault show "#{vault}" "#{item}"}, MU::SUMMARY
|
1090
1099
|
@secrets_granted["#{vault}:#{item}"] = item
|
1091
1100
|
end
|
1092
1101
|
|
data/modules/mu/master.rb
CHANGED
@@ -202,6 +202,7 @@ module MU
|
|
202
202
|
else
|
203
203
|
device.dup
|
204
204
|
end
|
205
|
+
|
205
206
|
alias_device = cryptfile ? "/dev/mapper/"+path.gsub(/[^0-9a-z_\-]/i, "_") : realdevice
|
206
207
|
|
207
208
|
if !File.exist?(realdevice)
|
@@ -212,7 +213,7 @@ module MU
|
|
212
213
|
cloud_id: MU.myInstanceId,
|
213
214
|
kitten_cfg: {}
|
214
215
|
)
|
215
|
-
dummy_svr.addVolume(device, size)
|
216
|
+
dummy_svr.addVolume(dev: device, size: size)
|
216
217
|
MU::Cloud::AWS::Server.tagVolumes(
|
217
218
|
MU.myInstanceId,
|
218
219
|
device: device,
|
@@ -228,7 +229,7 @@ module MU
|
|
228
229
|
cloud_id: MU.myInstanceId,
|
229
230
|
kitten_cfg: { 'project' => MU::Cloud::Google.myProject, 'availability_zone' => MU.myAZ }
|
230
231
|
)
|
231
|
-
dummy_svr.addVolume(device, size) # This will tag itself sensibly
|
232
|
+
dummy_svr.addVolume(dev: device, size: size) # This will tag itself sensibly
|
232
233
|
else
|
233
234
|
raise MuError, "Not in a familiar cloud, so I don't know how to create volumes for myself"
|
234
235
|
end
|
@@ -271,14 +272,16 @@ module MU
|
|
271
272
|
end
|
272
273
|
|
273
274
|
%x{/usr/sbin/xfs_admin -l "#{alias_device}" > /dev/null 2>&1}
|
275
|
+
|
274
276
|
if $?.exitstatus != 0
|
275
277
|
MU.log "Formatting #{alias_device}", MU::NOTICE
|
276
278
|
%x{/sbin/mkfs.xfs "#{alias_device}"}
|
277
279
|
%x{/usr/sbin/xfs_admin -L "#{path.gsub(/[^0-9a-z_\-]/i, "_")}" "#{alias_device}"}
|
278
280
|
end
|
279
281
|
Dir.mkdir(path, 0700) if !Dir.exist?(path) # XXX recursive
|
282
|
+
|
280
283
|
%x{/usr/sbin/xfs_info "#{alias_device}" > /dev/null 2>&1}
|
281
|
-
if $?.exitstatus
|
284
|
+
if $?.exitstatus == 0 and !File.open("/etc/mtab").read.match(/ #{path} /)
|
282
285
|
MU.log "Mounting #{alias_device} to #{path}"
|
283
286
|
%x{/bin/mount "#{alias_device}" "#{path}"}
|
284
287
|
end
|
@@ -797,6 +800,7 @@ module MU
|
|
797
800
|
nagios_threads = []
|
798
801
|
nagios_threads << Thread.new {
|
799
802
|
MU.dupGlobals(parent_thread_id)
|
803
|
+
Thread.current.thread_variable_set("syncMonitoringConfig", "<main>")
|
800
804
|
realhome = Etc.getpwnam("nagios").dir
|
801
805
|
[NAGIOS_HOME, "#{NAGIOS_HOME}/.ssh"].each { |dir|
|
802
806
|
Dir.mkdir(dir, 0711) if !Dir.exist?(dir)
|
@@ -839,6 +843,7 @@ module MU
|
|
839
843
|
MU.dupGlobals(parent_thread_id)
|
840
844
|
threads << Thread.new {
|
841
845
|
MU::MommaCat.setThreadContext(deploy)
|
846
|
+
Thread.current.thread_variable_set("syncMonitoringConfig",server.mu_name)
|
842
847
|
MU.log "Adding #{server.mu_name} to #{NAGIOS_HOME}/.ssh/config", MU::DEBUG
|
843
848
|
MU::Master.addHostToSSHConfig(
|
844
849
|
server,
|
@@ -941,7 +946,7 @@ module MU
|
|
941
946
|
return true if l =~ /^\/dev\/nvme\d/
|
942
947
|
}
|
943
948
|
else
|
944
|
-
return true if File.
|
949
|
+
return true if File.exist?("/dev/nvme0n1")
|
945
950
|
end
|
946
951
|
false
|
947
952
|
end
|
@@ -213,6 +213,7 @@ module MU
|
|
213
213
|
need_reload = false
|
214
214
|
@cleanup_threads << Thread.new {
|
215
215
|
MU.dupGlobals(parent_thread_id)
|
216
|
+
Thread.current.thread_variable_set("cleanTerminatedInstances", deploy_id)
|
216
217
|
deploy = MU::MommaCat.getLitter(deploy_id, set_context_to_me: true)
|
217
218
|
purged_this_deploy = 0
|
218
219
|
MU.log "#{deploy_id} has some kittens in it", loglevel, details: deploy.kittens.keys
|
@@ -225,7 +226,8 @@ module MU
|
|
225
226
|
servers.each_pair { |mu_name, server|
|
226
227
|
server.describe
|
227
228
|
if !server.cloud_id
|
228
|
-
MU.log "Checking for presence of #{mu_name}, but unable to fetch its cloud_id", MU::WARN,
|
229
|
+
MU.log "Checking for presence of instance '#{mu_name}', but unable to fetch its cloud_id", MU::WARN, server.class.name
|
230
|
+
pp servers.keys
|
229
231
|
elsif !server.active?
|
230
232
|
next if File.exist?(deploy_dir(deploy_id)+"/.cleanup-"+server.cloud_id)
|
231
233
|
deletia << mu_name
|
@@ -313,7 +315,7 @@ module MU
|
|
313
315
|
return 0
|
314
316
|
end
|
315
317
|
|
316
|
-
File.unlink(daemonPidFile) if File.
|
318
|
+
File.unlink(daemonPidFile) if File.exist?(daemonPidFile)
|
317
319
|
MU.log "Starting Momma Cat on port #{MU.mommaCatPort}, logging to #{daemonLogFile}, PID file #{daemonPidFile}"
|
318
320
|
origdir = Dir.getwd
|
319
321
|
Dir.chdir(MU.myRoot+"/modules")
|
@@ -305,9 +305,8 @@ module MU
|
|
305
305
|
zones = MU::Cloud::DNSZone.find(cloud_id: "platform-mu")
|
306
306
|
mu_zone = zones.values.first if !zones.nil?
|
307
307
|
end
|
308
|
-
|
309
308
|
if !mu_zone.nil?
|
310
|
-
MU::Cloud::DNSZone.genericMuDNSEntry(name: node.gsub(/[^a-z0-9!"\#$%&'\(\)\*\+,\-\/:;<=>\?@\[\]\^_`{\|}~\.]
|
309
|
+
MU::Cloud::DNSZone.genericMuDNSEntry(name: node.gsub(/[^a-z0-9!"\#$%&'\(\)\*\+,\-\/:;<=>\?@\[\]\^_`{\|}~\.]/i, '-').gsub(/--|^-/, ''), target: server.canonicalIP, cloudclass: MU::Cloud::Server, sync_wait: sync_wait)
|
311
310
|
else
|
312
311
|
MU::Master.addInstanceToEtcHosts(server.canonicalIP, node)
|
313
312
|
end
|
@@ -179,6 +179,7 @@ module MU
|
|
179
179
|
# return [false, nil]
|
180
180
|
def self.lock(id, nonblock = false, global = false, retries: 0, deploy_id: MU.deploy_id)
|
181
181
|
raise MuError, "Can't pass a nil id to MU::MommaCat.lock" if id.nil?
|
182
|
+
called_by = caller[0]
|
182
183
|
|
183
184
|
if !global
|
184
185
|
lockdir = "#{deploy_dir(deploy_id)}/locks"
|
@@ -200,6 +201,10 @@ module MU
|
|
200
201
|
@locks[Thread.current.object_id][id] = File.open("#{lockdir}/#{id}.lock", File::CREAT|File::RDWR, 0600)
|
201
202
|
}
|
202
203
|
|
204
|
+
thr_to_s = Proc.new { |t|
|
205
|
+
"#{t.object_id} (#{t.thread_variables.map { |v| "#{v.to_s}: #{t.thread_variable_get(v).to_s}" }.join(", ")})"
|
206
|
+
}
|
207
|
+
|
203
208
|
MU.log "Getting a lock on #{lockdir}/#{id}.lock (thread #{Thread.current.object_id})...", MU::DEBUG, details: caller
|
204
209
|
show_relevant = Proc.new {
|
205
210
|
@lock_semaphore.synchronize {
|
@@ -208,7 +213,7 @@ module MU
|
|
208
213
|
if lockid == id
|
209
214
|
thread = Thread.list.select { |t| t.object_id == thread_id }.first
|
210
215
|
if thread.object_id != Thread.current.object_id
|
211
|
-
MU.log "#{
|
216
|
+
MU.log "Thread #{thr_to_s.call(thread)} sitting on #{id}, which is needed by #{thr_to_s.call(Thread.current)} at #{called_by}", MU::WARN, thread.backtrace
|
212
217
|
end
|
213
218
|
end
|
214
219
|
}
|
@@ -585,7 +590,7 @@ module MU
|
|
585
590
|
orig_cfg = findResourceConfig(type, res_name)
|
586
591
|
|
587
592
|
if orig_cfg.nil?
|
588
|
-
MU.log "Failed to locate original config for #{attrs[:cfg_name]} #{res_name} in #{@deploy_id}", MU::
|
593
|
+
MU.log "Failed to locate original config for #{attrs[:cfg_name]} #{res_name}, seen in cached deployment.json for #{@deploy_id}", MU::DEBUG
|
589
594
|
next
|
590
595
|
end
|
591
596
|
|
data/modules/mu/mommacat.rb
CHANGED
@@ -150,6 +150,7 @@ module MU
|
|
150
150
|
@deploy_id = deploy_id
|
151
151
|
@mu_user = mu_user.dup
|
152
152
|
@no_artifacts = no_artifacts
|
153
|
+
@ssh_key_generated = false
|
153
154
|
|
154
155
|
# Make sure mu_user and chef_user are sane.
|
155
156
|
if @mu_user == "root"
|
@@ -167,7 +168,6 @@ module MU
|
|
167
168
|
@need_deploy_flush = false
|
168
169
|
@node_cert_semaphore = Mutex.new
|
169
170
|
@deployment = deployment_data
|
170
|
-
|
171
171
|
@deployment['mu_public_ip'] = MU.mu_public_ip
|
172
172
|
@private_key = nil
|
173
173
|
@public_key = nil
|
@@ -175,6 +175,7 @@ module MU
|
|
175
175
|
@secrets['instance_secret'] = Hash.new
|
176
176
|
@secrets['windows_admin_password'] = Hash.new
|
177
177
|
@ssh_key_name = ssh_key_name
|
178
|
+
@ssh_key_name ||= "deploy-#{@deploy_id}"
|
178
179
|
@ssh_private_key = ssh_private_key
|
179
180
|
@ssh_public_key = ssh_public_key
|
180
181
|
@clouds = {}
|
@@ -195,6 +196,7 @@ module MU
|
|
195
196
|
setDeploySecret
|
196
197
|
MU::MommaCat.setThreadContext(self) if set_context_to_me
|
197
198
|
save!
|
199
|
+
generatePasswords
|
198
200
|
end
|
199
201
|
|
200
202
|
@appname ||= MU.appname
|
@@ -202,6 +204,7 @@ module MU
|
|
202
204
|
@environment ||= MU.environment
|
203
205
|
|
204
206
|
loadDeploy(set_context_to_me: set_context_to_me)
|
207
|
+
@deployment['mu_all_ips'] ||= [MU.mu_public_ip, MU.my_private_ip].uniq
|
205
208
|
if !deploy_secret.nil? and !authKey(deploy_secret)
|
206
209
|
raise DeployInitializeError, "Client request did not include a valid deploy authorization secret. Verify that userdata runs correctly?"
|
207
210
|
end
|
@@ -224,6 +227,29 @@ module MU
|
|
224
227
|
# if !@@litter_semaphore.owned?
|
225
228
|
end # end of initialize()
|
226
229
|
|
230
|
+
def generatePasswords
|
231
|
+
return if !@original_config['generate_passwords']
|
232
|
+
|
233
|
+
@original_config['generate_passwords'].each { |pw|
|
234
|
+
password = MU.generatePassword(safe_pattern: pw['safe_chars'], length: pw['minlength'])
|
235
|
+
MU.supportedGroomers.each { |g|
|
236
|
+
groomclass = MU.loadGroomer(g)
|
237
|
+
begin
|
238
|
+
groomclass.getSecret(vault: @deploy_id,
|
239
|
+
item: pw['itemname'],
|
240
|
+
field: 'password')
|
241
|
+
rescue MU::Groomer::MuNoSuchSecret
|
242
|
+
pwdata = { "password" => password }
|
243
|
+
pwdata["username"] = pw["username"] if pw["username"]
|
244
|
+
groomclass.saveSecret(vault: @deploy_id,
|
245
|
+
item: pw['itemname'],
|
246
|
+
data: pwdata,
|
247
|
+
permissions: (g == "Ansible"))
|
248
|
+
end
|
249
|
+
}
|
250
|
+
}
|
251
|
+
end
|
252
|
+
|
227
253
|
# List all the cloud providers declared by resources in our deploy.
|
228
254
|
def cloudsUsed
|
229
255
|
seen = []
|
@@ -490,7 +516,7 @@ module MU
|
|
490
516
|
# Return the parts and pieces of this deploy's node ssh key set. Generate
|
491
517
|
# or load if that hasn't been done already.
|
492
518
|
def SSHKey
|
493
|
-
return [@ssh_key_name, @ssh_private_key, @ssh_public_key] if
|
519
|
+
return [@ssh_key_name, @ssh_private_key, @ssh_public_key] if @ssh_key_generated
|
494
520
|
if numKittens(types: ["Server", "ServerPool", "ContainerCluster"]) == 0
|
495
521
|
return []
|
496
522
|
end
|
@@ -535,6 +561,7 @@ module MU
|
|
535
561
|
}
|
536
562
|
end
|
537
563
|
|
564
|
+
@ssh_key_generated = true
|
538
565
|
return [@ssh_key_name, @ssh_private_key, @ssh_public_key]
|
539
566
|
end
|
540
567
|
|
@@ -549,8 +576,8 @@ module MU
|
|
549
576
|
# @param triggering_node [MU::Cloud]: A cloud object calling this notify, usually on behalf of itself
|
550
577
|
# @param remove [Boolean]: Remove this resource from the deploy structure, instead of adding it.
|
551
578
|
# @return [void]
|
552
|
-
def notify(type, key, data, mu_name: nil, remove: false, triggering_node: nil, delayed_save: false)
|
553
|
-
no_write
|
579
|
+
def notify(type, key, data, mu_name: nil, remove: false, triggering_node: nil, delayed_save: false, no_write: nil)
|
580
|
+
no_write ||= (@no_artifacts or !caller.grep(/\/mommacat\.rb:\d+:in `notify'/).empty?)
|
554
581
|
|
555
582
|
begin
|
556
583
|
if !no_write
|
@@ -831,7 +858,7 @@ MAIL_HEAD_END
|
|
831
858
|
next if sibling.config.has_key?("groom") and !sibling.config["groom"]
|
832
859
|
threads << Thread.new {
|
833
860
|
Thread.abort_on_exception = true
|
834
|
-
Thread.current.thread_variable_set("
|
861
|
+
Thread.current.thread_variable_set("syncLitterThread", sibling.mu_name)
|
835
862
|
MU.setVar("syncLitterThread", true)
|
836
863
|
begin
|
837
864
|
sibling.groomer.saveDeployData
|
@@ -874,7 +901,7 @@ MAIL_HEAD_END
|
|
874
901
|
sans << resource.mu_name.downcase if resource.mu_name and resource.mu_name != cert_cn
|
875
902
|
# XXX were there other names we wanted to include?
|
876
903
|
key = MU::Master::SSL.getKey(cert_cn, keysize: keysize)
|
877
|
-
cert, pfx_cert = MU::Master::SSL.getCert(cert_cn, "/CN=#{cert_cn}/O=Mu/C=US", sans: sans, pfx:
|
904
|
+
cert, pfx_cert = MU::Master::SSL.getCert(cert_cn, "/CN=#{cert_cn}/O=Mu/C=US", sans: sans, pfx: true)
|
878
905
|
results[cert_cn] = [key, cert]
|
879
906
|
|
880
907
|
winrm_cert = nil
|