simp-cli 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/LICENSE +27 -0
- data/README.md +48 -0
- data/Rakefile +142 -0
- data/bin/simp +5 -0
- data/lib/simp/cli.rb +88 -0
- data/lib/simp/cli/commands/bootstrap.rb +275 -0
- data/lib/simp/cli/commands/check.rb +163 -0
- data/lib/simp/cli/commands/cleancerts.rb +114 -0
- data/lib/simp/cli/commands/config.rb +235 -0
- data/lib/simp/cli/commands/doc.rb +14 -0
- data/lib/simp/cli/commands/passgen.rb +128 -0
- data/lib/simp/cli/commands/puppeteval.rb +82 -0
- data/lib/simp/cli/commands/runpuppet.rb +95 -0
- data/lib/simp/cli/config/item.rb +456 -0
- data/lib/simp/cli/config/item/add_ldap_to_hiera.rb +43 -0
- data/lib/simp/cli/config/item/answers_yaml_file_writer.rb +58 -0
- data/lib/simp/cli/config/item/certificates.rb +39 -0
- data/lib/simp/cli/config/item/client_nets.rb +65 -0
- data/lib/simp/cli/config/item/common_runlevel_default.rb +32 -0
- data/lib/simp/cli/config/item/dns_search.rb +48 -0
- data/lib/simp/cli/config/item/dns_servers.rb +57 -0
- data/lib/simp/cli/config/item/failover_log_servers.rb +27 -0
- data/lib/simp/cli/config/item/gateway.rb +32 -0
- data/lib/simp/cli/config/item/grub_password.rb +51 -0
- data/lib/simp/cli/config/item/hostname.rb +24 -0
- data/lib/simp/cli/config/item/hostname_conf.rb +48 -0
- data/lib/simp/cli/config/item/ipaddress.rb +46 -0
- data/lib/simp/cli/config/item/is_master_yum_server.rb +23 -0
- data/lib/simp/cli/config/item/ldap_base_dn.rb +38 -0
- data/lib/simp/cli/config/item/ldap_bind_dn.rb +34 -0
- data/lib/simp/cli/config/item/ldap_bind_hash.rb +28 -0
- data/lib/simp/cli/config/item/ldap_bind_pw.rb +24 -0
- data/lib/simp/cli/config/item/ldap_master.rb +33 -0
- data/lib/simp/cli/config/item/ldap_root_dn.rb +42 -0
- data/lib/simp/cli/config/item/ldap_root_hash.rb +35 -0
- data/lib/simp/cli/config/item/ldap_sync_dn.rb +24 -0
- data/lib/simp/cli/config/item/ldap_sync_hash.rb +28 -0
- data/lib/simp/cli/config/item/ldap_sync_pw.rb +26 -0
- data/lib/simp/cli/config/item/ldap_uri.rb +43 -0
- data/lib/simp/cli/config/item/log_servers.rb +27 -0
- data/lib/simp/cli/config/item/netmask.rb +39 -0
- data/lib/simp/cli/config/item/network_conf.rb +63 -0
- data/lib/simp/cli/config/item/network_dhcp.rb +27 -0
- data/lib/simp/cli/config/item/network_interface.rb +41 -0
- data/lib/simp/cli/config/item/network_setup_nic.rb +28 -0
- data/lib/simp/cli/config/item/ntp_servers.rb +69 -0
- data/lib/simp/cli/config/item/puppet_autosign.rb +66 -0
- data/lib/simp/cli/config/item/puppet_ca.rb +31 -0
- data/lib/simp/cli/config/item/puppet_ca_port.rb +28 -0
- data/lib/simp/cli/config/item/puppet_conf.rb +98 -0
- data/lib/simp/cli/config/item/puppet_fileserver.rb +104 -0
- data/lib/simp/cli/config/item/puppet_hosts_entry.rb +44 -0
- data/lib/simp/cli/config/item/puppet_server.rb +30 -0
- data/lib/simp/cli/config/item/puppet_server_ip.rb +25 -0
- data/lib/simp/cli/config/item/puppetdb_port.rb +25 -0
- data/lib/simp/cli/config/item/puppetdb_server.rb +26 -0
- data/lib/simp/cli/config/item/remove_ldap_from_hiera.rb +47 -0
- data/lib/simp/cli/config/item/rename_fqdn_yaml.rb +40 -0
- data/lib/simp/cli/config/item/rsync_base.rb +37 -0
- data/lib/simp/cli/config/item/rsync_server.rb +44 -0
- data/lib/simp/cli/config/item/rsync_timeout.rb +26 -0
- data/lib/simp/cli/config/item/set_grub_password.rb +19 -0
- data/lib/simp/cli/config/item/simp_yum_servers.rb +30 -0
- data/lib/simp/cli/config/item/use_auditd.rb +19 -0
- data/lib/simp/cli/config/item/use_fips.rb +46 -0
- data/lib/simp/cli/config/item/use_iptables.rb +22 -0
- data/lib/simp/cli/config/item/use_ldap.rb +19 -0
- data/lib/simp/cli/config/item/use_selinux.rb +32 -0
- data/lib/simp/cli/config/item/yum_repositories.rb +75 -0
- data/lib/simp/cli/config/item_list_factory.rb +236 -0
- data/lib/simp/cli/config/questionnaire.rb +86 -0
- data/lib/simp/cli/config/utils.rb +128 -0
- data/lib/simp/cli/lib/utils.rb +114 -0
- data/lib/simp/simp.rb +77 -0
- data/spec/lib/simp/cli/commands/config_spec.rb +42 -0
- data/spec/lib/simp/cli/config/item/add_ldap_to_hiera_spec.rb +58 -0
- data/spec/lib/simp/cli/config/item/answers_yaml_file_writer_spec.rb +86 -0
- data/spec/lib/simp/cli/config/item/certificates_spec.rb +50 -0
- data/spec/lib/simp/cli/config/item/client_nets_spec.rb +66 -0
- data/spec/lib/simp/cli/config/item/common_runlevel_default_spec.rb +27 -0
- data/spec/lib/simp/cli/config/item/dns_search_spec.rb +74 -0
- data/spec/lib/simp/cli/config/item/dns_servers_spec.rb +76 -0
- data/spec/lib/simp/cli/config/item/failover_log_servers_spec.rb +49 -0
- data/spec/lib/simp/cli/config/item/files/FakeCA/cacertkey +1 -0
- data/spec/lib/simp/cli/config/item/files/FakeCA/gencerts_nopass.sh +10 -0
- data/spec/lib/simp/cli/config/item/files/autosign.conf.new +11 -0
- data/spec/lib/simp/cli/config/item/files/autosign.conf.used +15 -0
- data/spec/lib/simp/cli/config/item/files/fileserver.conf +41 -0
- data/spec/lib/simp/cli/config/item/files/hosts +2 -0
- data/spec/lib/simp/cli/config/item/files/hosts.old_puppet_entry +3 -0
- data/spec/lib/simp/cli/config/item/files/puppet.conf +25 -0
- data/spec/lib/simp/cli/config/item/files/puppet.your.domain.yaml +21 -0
- data/spec/lib/simp/cli/config/item/files/resolv.conf__multiple +10 -0
- data/spec/lib/simp/cli/config/item/files/resolv.conf__single +4 -0
- data/spec/lib/simp/cli/config/item/files/rsyncd.conf +225 -0
- data/spec/lib/simp/cli/config/item/gateway_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/grub_password_spec.rb +24 -0
- data/spec/lib/simp/cli/config/item/hostname_conf_spec.rb +27 -0
- data/spec/lib/simp/cli/config/item/hostname_spec.rb +22 -0
- data/spec/lib/simp/cli/config/item/ipaddress_spec.rb +40 -0
- data/spec/lib/simp/cli/config/item/is_master_yum_server_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/ldap_base_dn_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_bind_dn_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_bind_hash_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_bind_pw_spec.rb +21 -0
- data/spec/lib/simp/cli/config/item/ldap_master_spec.rb +37 -0
- data/spec/lib/simp/cli/config/item/ldap_root_dn_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_root_hash_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_sync_dn_spec.rb +22 -0
- data/spec/lib/simp/cli/config/item/ldap_sync_hash_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/ldap_sync_pw_spec.rb +21 -0
- data/spec/lib/simp/cli/config/item/ldap_uri_spec.rb +32 -0
- data/spec/lib/simp/cli/config/item/log_servers_spec.rb +49 -0
- data/spec/lib/simp/cli/config/item/netmask_spec.rb +28 -0
- data/spec/lib/simp/cli/config/item/network_conf_spec.rb +63 -0
- data/spec/lib/simp/cli/config/item/network_dhcp_spec.rb +11 -0
- data/spec/lib/simp/cli/config/item/network_interface_spec.rb +26 -0
- data/spec/lib/simp/cli/config/item/network_setup_nic_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/ntp_servers_spec.rb +43 -0
- data/spec/lib/simp/cli/config/item/puppet_autosign_spec.rb +55 -0
- data/spec/lib/simp/cli/config/item/puppet_ca_port_spec.rb +23 -0
- data/spec/lib/simp/cli/config/item/puppet_ca_spec.rb +22 -0
- data/spec/lib/simp/cli/config/item/puppet_conf_spec.rb +110 -0
- data/spec/lib/simp/cli/config/item/puppet_fileserver_spec.rb +53 -0
- data/spec/lib/simp/cli/config/item/puppet_hosts_entry_spec.rb +85 -0
- data/spec/lib/simp/cli/config/item/puppet_server_ip_spec.rb +24 -0
- data/spec/lib/simp/cli/config/item/puppet_server_spec.rb +22 -0
- data/spec/lib/simp/cli/config/item/puppetdb_port_spec.rb +25 -0
- data/spec/lib/simp/cli/config/item/puppetdb_server_spec.rb +25 -0
- data/spec/lib/simp/cli/config/item/remove_ldap_from_hiera_spec.rb +58 -0
- data/spec/lib/simp/cli/config/item/rename_fqdn_yaml_spec.rb +63 -0
- data/spec/lib/simp/cli/config/item/rsync_base_spec.rb +28 -0
- data/spec/lib/simp/cli/config/item/rsync_server_spec.rb +41 -0
- data/spec/lib/simp/cli/config/item/rsync_timeout_spec.rb +21 -0
- data/spec/lib/simp/cli/config/item/set_grub_password_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/simp_yum_servers_spec.rb +41 -0
- data/spec/lib/simp/cli/config/item/spec_helper.rb +22 -0
- data/spec/lib/simp/cli/config/item/use_auditd_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/use_fips_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/use_iptables_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/use_ldap_spec.rb +29 -0
- data/spec/lib/simp/cli/config/item/use_selinux_spec.rb +24 -0
- data/spec/lib/simp/cli/config/item/yum_repositories_spec.rb +94 -0
- data/spec/lib/simp/cli/config/item_spec.rb +106 -0
- data/spec/lib/simp/cli/config/spec_helper.rb +1 -0
- data/spec/lib/simp/cli/config/utils_spec.rb +131 -0
- data/spec/lib/simp/cli/spec_helper.rb +1 -0
- data/spec/spec_helper.rb +91 -0
- metadata +391 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
module Simp::Cli::Commands; end
|
|
2
|
+
|
|
3
|
+
class Simp::Cli::Commands::Check < Simp::Cli
|
|
4
|
+
@opt_parser = OptionParser.new do |opts|
|
|
5
|
+
opts.banner = "*Options*"
|
|
6
|
+
|
|
7
|
+
opts.on("-A", "--all", "Run all checks, equivalent to -nkl") do
|
|
8
|
+
@check_network = true
|
|
9
|
+
@check_keys = true
|
|
10
|
+
@check_ldap = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
opts.on("-p", "--pre", "Run checks that should pass before first run, equivalent to -nk") do
|
|
14
|
+
@check_network = true
|
|
15
|
+
@check_keys = true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
opts.on("-n", "--network", "Check network items") do
|
|
19
|
+
@check_network = true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
opts.on("-k", "--keys", "Check that keys have been generated for the host") do
|
|
23
|
+
@check_keys = true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
opts.on("-l", "--ldap", "Check validity of ldap passwords") do
|
|
27
|
+
@check_ldap = true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
opts.on("-v", "--verbose", "Run verbosely") do
|
|
31
|
+
@verbose = true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on("-r", "--report FILE", "Create a report in FILE. NOTE: if FILE exists, it will be overwritten!") do |file|
|
|
35
|
+
@report_file = file
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("-h", "--help", "Print this message") do
|
|
39
|
+
puts opts
|
|
40
|
+
exit
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.run(args)
|
|
45
|
+
raise "simp check Requires Arguments" if args.empty?
|
|
46
|
+
|
|
47
|
+
super
|
|
48
|
+
|
|
49
|
+
@version = Simp.version
|
|
50
|
+
|
|
51
|
+
report = []
|
|
52
|
+
|
|
53
|
+
system('clear')
|
|
54
|
+
|
|
55
|
+
if @check_network
|
|
56
|
+
report.push "\n***Starting Network Check***\n"
|
|
57
|
+
|
|
58
|
+
hostname = `hostname`.gsub!(/\s+/, '')
|
|
59
|
+
|
|
60
|
+
begin
|
|
61
|
+
network_hostname = `grep HOSTNAME /etc/sysconfig/network`.strip.match(/HOSTNAME\s*=\s*([^ ]*)/)[1]
|
|
62
|
+
rescue
|
|
63
|
+
report.push "ERROR: No hostname in /etc/sysconfig/network"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if hostname == network_hostname
|
|
67
|
+
report.push "Hostname matches hostname in /etc/sysconfig/network"
|
|
68
|
+
else
|
|
69
|
+
report.push "ERROR: Hostname does not match hostname in /etc/sysconfig/network"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if `grep ^127.0.0.1 /etc/hosts`.split("\n").any? { |line| line =~ /localhost.localdomain[\s+\z]/ and line =~ /localhost[\s+\z]/ }
|
|
73
|
+
report.push "Found valid entry for 127.0.0.1 in /etc/hosts"
|
|
74
|
+
else
|
|
75
|
+
report.push "ERROR: Did not find valid entry for 127.0.0.1 in /etc/hosts"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
if `grep ^::1 /etc/hosts`.split("\n").any? { |line| line =~ /localhost6\.localdomain6(\s+|$)/ and line =~ /localhost6(\s+|$)/ }
|
|
79
|
+
report.push "Found valid entry for ::1 in /etc/hosts"
|
|
80
|
+
else
|
|
81
|
+
report.push "ERROR: Did not find valid entry for ::1 in /etc/hosts"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if @check_keys
|
|
86
|
+
report.push "\n***Starting Keys Check***\n"
|
|
87
|
+
|
|
88
|
+
key_count = 0
|
|
89
|
+
valid_key_count = 0
|
|
90
|
+
|
|
91
|
+
Dir.foreach("/etc/puppet/keydist") do |host|
|
|
92
|
+
if (host !~ /\A\.+\z/) and (host !~ /\Acacerts\z/) and File::directory?("/etc/puppet/keydist/#{host}")
|
|
93
|
+
Dir.foreach("/etc/puppet/keydist/#{host}") do |key|
|
|
94
|
+
if key =~ /\.pem\z/ or key =~ /\.pub\z/
|
|
95
|
+
key_count += 1
|
|
96
|
+
|
|
97
|
+
if `openssl verify -CApath /etc/puppet/keydist/cacerts /etc/puppet/keydist/#{host}/#{key}`.strip =~ /\s+OK\z/
|
|
98
|
+
valid_key_count += 1
|
|
99
|
+
report.push "Key /etc/puppet/keydist/#{host}/#{key} validated\n"
|
|
100
|
+
else
|
|
101
|
+
report.push "ERROR: Key /etc/puppet/keydist/#{host}/#{key} did not validate\n"
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if key_count == 0
|
|
109
|
+
report.push "ERROR: No keys found (recursively) in /etc/puppet/keydist\n"
|
|
110
|
+
else
|
|
111
|
+
report.push "#{valid_key_count}/#{key_count} keys validated\n"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if @check_ldap
|
|
116
|
+
report.push "\n***Starting Ldap Check***\n"
|
|
117
|
+
|
|
118
|
+
binddn = ""
|
|
119
|
+
bindpw = ""
|
|
120
|
+
host = ""
|
|
121
|
+
base = ""
|
|
122
|
+
|
|
123
|
+
ldap_conf = '/etc/ldap.conf'
|
|
124
|
+
ldap_conf = '/etc/pam_ldap.conf' unless File.file?(ldap_conf)
|
|
125
|
+
|
|
126
|
+
File.open(ldap_conf).each_line do |line|
|
|
127
|
+
if (line =~ /\Abinddn\s+/) != nil
|
|
128
|
+
binddn = line.gsub(/\Abinddn\s+/, "").chomp
|
|
129
|
+
elsif (line =~ /\Abindpw\s+/) != nil
|
|
130
|
+
bindpw = line.gsub(/\Abindpw\s+/, "").chomp
|
|
131
|
+
elsif (line =~ /\Auri\s+/) != nil
|
|
132
|
+
host = line.gsub(/\Auri\s+/, "").chomp
|
|
133
|
+
elsif (line =~ /\Anss_base_passwd\s+/) != nil
|
|
134
|
+
base = line.gsub(/\Anss_base_passwd\s+/, "").chomp.gsub(/\?.*/, "")
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
exit_code = `ldapsearch -Z -LLLL -D "#{binddn}" -x -w "#{bindpw}" -H "#{host}" -b "#{base}" -s one uid sshPublidKey`.to_i
|
|
139
|
+
|
|
140
|
+
if exit_code == 0
|
|
141
|
+
report.push "Ldap appears to be working\n"
|
|
142
|
+
else
|
|
143
|
+
report.push "ERROR: Ldap does not appear to be working; ldapsearch exited with code #{exit_code}\n"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
report = report.select { |line| line =~ /\A(\*\*\*|WARNING|ERROR)/ } unless @verbose
|
|
148
|
+
|
|
149
|
+
report = report.join("\n")
|
|
150
|
+
|
|
151
|
+
unless @report_file.nil?
|
|
152
|
+
begin
|
|
153
|
+
f = File.open(File.expand_path(@report_file), 'w')
|
|
154
|
+
f.puts report
|
|
155
|
+
f.close
|
|
156
|
+
rescue
|
|
157
|
+
raise "An error occurred while writing the report:#{$!}"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
puts report
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Simp::Cli::Commands; end
|
|
2
|
+
|
|
3
|
+
class Simp::Cli::Commands::Cleancerts < Simp::Cli
|
|
4
|
+
@conf_dif = File.expand_path('~/.simp')
|
|
5
|
+
@host_file = "#{@conf_dir}/hosts"
|
|
6
|
+
@gen_host_list = true
|
|
7
|
+
@host_list = Array.new
|
|
8
|
+
@host_errors = Array.new
|
|
9
|
+
|
|
10
|
+
@opt_parser = OptionParser.new do |opts|
|
|
11
|
+
opts.banner = "\n === The SIMP CleanCerts Tool ==="
|
|
12
|
+
opts.separator ""
|
|
13
|
+
opts.separator "The SIMP CleanCerts Tool revokes and removes the Puppet certificates from a"
|
|
14
|
+
opts.separator "list of hosts."
|
|
15
|
+
opts.separator ""
|
|
16
|
+
opts.separator "Some requirements to use this tool:"
|
|
17
|
+
opts.separator " * the user must have SSH access to all of the list hosts"
|
|
18
|
+
opts.separator " * the user cannot be root"
|
|
19
|
+
opts.separator " * each target host must be able to run, with sudo, the following commands:"
|
|
20
|
+
opts.separator " - /usr/sbin/puppetd"
|
|
21
|
+
opts.separator " - /usr/sbin/puppetca"
|
|
22
|
+
opts.separator " - /bin/rm -rf /var/lib/puppet/ssl"
|
|
23
|
+
opts.separator ""
|
|
24
|
+
opts.separator "This tool will not clean the certificates for the hostname of the current box"
|
|
25
|
+
opts.separator "or the Puppet server listed in puppet.conf."
|
|
26
|
+
opts.separator ""
|
|
27
|
+
opts.separator "OPTIONS:\n"
|
|
28
|
+
|
|
29
|
+
opts.on("-H", "--hosts FILE", "FILE containing a list of hosts to clean.") do |file|
|
|
30
|
+
@host_file = file
|
|
31
|
+
@gen_host_list = false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on("-h", "--help", "Print this message") do
|
|
35
|
+
puts opts
|
|
36
|
+
exit 0
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def self.clean_certs
|
|
42
|
+
|
|
43
|
+
success
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.run(args = Array.new)
|
|
47
|
+
File.exists?('/usr/sbin/puppetd') && File.exists?('/usr/sbin/puppetca')
|
|
48
|
+
|
|
49
|
+
raise "SIMP CleanCerts cannot be run as 'root'." if Process.uid == 0
|
|
50
|
+
|
|
51
|
+
@host_list = Array.new
|
|
52
|
+
if @gen_host_list
|
|
53
|
+
@host_list = %x{cd /;sudo /usr/sbin/puppetca --list --all}.split("\n").map { |host| host.split(/\(.*\)/).first.split(/\s+/).last }
|
|
54
|
+
else
|
|
55
|
+
File.open(@host_file).each_line do |line|
|
|
56
|
+
@host_list << line.chomp
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
@host_list.compact!
|
|
60
|
+
|
|
61
|
+
if @host_list.size == 0
|
|
62
|
+
puts "No known hosts to clean!"
|
|
63
|
+
exit 0
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
system("echo 'Please review the list of hosts to clean certificates on:\n - #{@host_list.join("\n - ")}' | less -f")
|
|
67
|
+
|
|
68
|
+
if Utils.yes_or_no("Clean certificates for all listed hosts?", false)
|
|
69
|
+
if @gen_host_list
|
|
70
|
+
file = File.open(@host_file, 'w')
|
|
71
|
+
@host_list.each do |host|
|
|
72
|
+
file.puts host
|
|
73
|
+
end
|
|
74
|
+
file.close
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@host_list.each do |host|
|
|
78
|
+
%{sudo /usr/sbin/puppetca --revoke #{host}}
|
|
79
|
+
%{sudo /usr/sbin/puppetca --clean #{host}}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
result = %x{pssh -f -h #{@host_file} -OStrictHostKeyChecking=no "sudo /bin/rm -rf /var/lib/puppet/ssl"}
|
|
83
|
+
result.each_line do |line|
|
|
84
|
+
if line =~ /.*\[FAILURE\]\s([A-Za-z0-9\-\.]+).*/
|
|
85
|
+
success = false
|
|
86
|
+
@host_errors << $1
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
if @host_errors.empty?
|
|
91
|
+
puts "Successfully cleaned certificates for the #{@host_list.size} hosts listed in #{@host_file.path}."
|
|
92
|
+
else
|
|
93
|
+
filename = "#{@conf_dir}/pssh_error#{Time.now.strftime("%Y%m%d%H%M")}"
|
|
94
|
+
File.open(filename, 'w') do
|
|
95
|
+
@host_errors.each { |err| file.puts err }
|
|
96
|
+
end
|
|
97
|
+
raise "Errors occured while cleaning certificates, outputting list of hosts with errors to #{filename}"
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
if @gen_host_list
|
|
101
|
+
puts "If you do not want to clean all certificates, you can place"
|
|
102
|
+
puts "all hosts you want to clean in a newline-delimited file and"
|
|
103
|
+
puts "use the '--hosts <hosts_file>' command line option."
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
puts "If you want to manually clean certificates on all boxes,"
|
|
107
|
+
puts "follow the steps to clean certificates from the "
|
|
108
|
+
puts "'\033[1mChanging Puppet Masters\033[21m' users guide."
|
|
109
|
+
puts "Also look through the '\033[1mPerforming One Shot Operations\033[21m'"
|
|
110
|
+
puts "users guide for guidance on doing this with PSSH.\n"
|
|
111
|
+
puts "Users guides can be found using '\033[1msimp doc\033[21m'."
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
require 'highline/import'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'find'
|
|
5
|
+
|
|
6
|
+
require File.expand_path( '../../cli', File.dirname(__FILE__) )
|
|
7
|
+
require File.expand_path( '../config/item', File.dirname(__FILE__) )
|
|
8
|
+
require File.expand_path( '../config/questionnaire', File.dirname(__FILE__) )
|
|
9
|
+
require File.expand_path( '../config/item_list_factory', File.dirname(__FILE__) )
|
|
10
|
+
|
|
11
|
+
module Simp::Cli::Commands; end
|
|
12
|
+
|
|
13
|
+
# Handle CLI interactions for "simp config"
|
|
14
|
+
class Simp::Cli::Commands::Config < Simp::Cli
|
|
15
|
+
default_outfile = '~/.simp/simp_conf.yaml'
|
|
16
|
+
|
|
17
|
+
@version = Simp::Cli::VERSION
|
|
18
|
+
@advanced_config = false
|
|
19
|
+
@options = {
|
|
20
|
+
:verbose => 0,
|
|
21
|
+
:noninteractive => 0,
|
|
22
|
+
:dry_run => false, # TODO: between these two, we should choose better names
|
|
23
|
+
|
|
24
|
+
:input_file => nil,
|
|
25
|
+
:output_file => File.expand_path( default_outfile ),
|
|
26
|
+
:puppet_system_file => '/etc/puppet/environments/simp/hieradata/simp_def.yaml',
|
|
27
|
+
|
|
28
|
+
:use_safety_save => true,
|
|
29
|
+
:autoaccept_safety_save => false,
|
|
30
|
+
:fail_on_missing_answers => false,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@opt_parser = OptionParser.new do |opts|
|
|
34
|
+
opts_separator = ' '*4 + '-'*76
|
|
35
|
+
opts.banner = "\n=== The SIMP Configuration Tool === "
|
|
36
|
+
opts.separator ""
|
|
37
|
+
opts.separator "The SIMP Configuration Tool is designed to assist the configuration of a SIMP"
|
|
38
|
+
opts.separator "machine. It offers two main features:"
|
|
39
|
+
opts.separator ""
|
|
40
|
+
opts.separator " (1) create/edit system configurations, and"
|
|
41
|
+
opts.separator " (2) apply system configurations."
|
|
42
|
+
opts.separator ""
|
|
43
|
+
opts.separator "The features that will be used is dependent upon the options specified."
|
|
44
|
+
opts.separator ""
|
|
45
|
+
opts.separator "USAGE:"
|
|
46
|
+
opts.separator " #{File.basename($0)} config [KEY=VALUE] [KEY=VALUE1,,VALUE2,,VALUE3] [...]"
|
|
47
|
+
opts.separator ""
|
|
48
|
+
opts.separator "OPTIONS:\n"
|
|
49
|
+
opts.separator opts_separator
|
|
50
|
+
|
|
51
|
+
opts.on("-o", "--output FILE", "The answers FILE where the created/edited ",
|
|
52
|
+
"system configuration will be written. ",
|
|
53
|
+
" (defaults to '#{default_outfile}')") do |file|
|
|
54
|
+
@options[:output_file] = file
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
opts.on("-i", "-a", "-e", "--apply FILE", "Apply answers FILE (fails on missing items)"
|
|
58
|
+
) do |file|
|
|
59
|
+
@options[:input_file] = file
|
|
60
|
+
@options[:fail_on_missing_answers] = true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
opts.on("-I", "-A", "-E", "--apply-with-questions FILE",
|
|
64
|
+
"Apply answers FILE (asks on missing items) ",
|
|
65
|
+
" Note that the edited configuration",
|
|
66
|
+
" will be written to the file specified in ",
|
|
67
|
+
" --output.") do |file|
|
|
68
|
+
@options[:input_file] = file
|
|
69
|
+
@options[:fail_on_missing_answers] = false
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
opts.separator opts_separator
|
|
73
|
+
|
|
74
|
+
# TODO: improve nomenclature
|
|
75
|
+
opts.on("-v", "--verbose", "Verbose output (stacks)") do
|
|
76
|
+
@options[:verbose] += 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
opts.on("-q", "--quiet", "Quiet output (clears any verbosity)") do
|
|
80
|
+
@options[:verbose] = -1
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
opts.on("-n", "--dry-run", "Do not apply system changes",
|
|
84
|
+
" (e.g., NICs, puppet.conf, etc)" ) do
|
|
85
|
+
@options[:dry_run] = true
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
opts.on("-f", "--non-interactive", "Force default answers (prompt if unknown)"
|
|
89
|
+
#" (-ff fails instead of prompting)"
|
|
90
|
+
) do |file|
|
|
91
|
+
@options[:noninteractive] += 1
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
opts.on("-s", "--skip-safety-save", "Ignore any safety-save files") do
|
|
95
|
+
@options[:use_safety_save] = false
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
opts.on("-S", "--accept-safety-save", "Automatically apply any safety-save files") do
|
|
99
|
+
@options[:autoaccept_safety_save] = true
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
opts.separator opts_separator
|
|
103
|
+
|
|
104
|
+
opts.on("-h", "--help", "Print this message") do
|
|
105
|
+
puts opts
|
|
106
|
+
exit 0
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def self.saved_session
|
|
112
|
+
result = {}
|
|
113
|
+
if @options.fetch( :use_safety_save, false ) && file = @options.fetch( :output_file )
|
|
114
|
+
_file = File.join( File.dirname( file ), ".#{File.basename( file )}" )
|
|
115
|
+
if File.file?( _file )
|
|
116
|
+
lines = File.open( _file, 'r' ).readlines
|
|
117
|
+
saved_hash = read_answers_file _file
|
|
118
|
+
last_item = nil
|
|
119
|
+
if saved_hash.keys.size > 0
|
|
120
|
+
last_item = {saved_hash.keys.last =>
|
|
121
|
+
saved_hash[ saved_hash.keys.last ]}.to_yaml.gsub( /^---/, '' ).strip
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
message = %Q{WARNING: interrupted session detected!}
|
|
125
|
+
say "<%= color(%q{*** #{message} ***}, YELLOW, BOLD) %> \n\n"
|
|
126
|
+
say "<%= color(%q{An automatic safety-save file from a previous session has been found at:}, YELLOW) %> \n\n"
|
|
127
|
+
say " <%= color( %q{#{_file}}, BOLD ) %>\n\n"
|
|
128
|
+
if last_item
|
|
129
|
+
say "<%= color(%q{The most recent answer from this session was:}, YELLOW) %> \n\n"
|
|
130
|
+
say "<%= color( %q{#{last_item.gsub( /^/, " \0" )}} ) %>\n\n"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if @options.fetch( :autoaccept_safety_save, false )
|
|
134
|
+
color = 'YELLOW'
|
|
135
|
+
say "<%= color(%q{Automatically resuming these answers because }, #{color}) %>" +
|
|
136
|
+
"<%= color(%q{--accept-safety-save}, BOLD, #{color}) %>" +
|
|
137
|
+
"<%= color(%q{ is active.}, #{color}) %>\n\n"
|
|
138
|
+
result = saved_hash
|
|
139
|
+
else
|
|
140
|
+
say "<%= color(%q{You can resume these answers or delete the file.}, YELLOW) %>\n\n"
|
|
141
|
+
|
|
142
|
+
if agree( "resume the session? (no = deletes file)" ){ |q| q.default = 'yes' }
|
|
143
|
+
say "\n<%= color( %q{applying answers from '#{_file}'}, GREEN )%>\n"
|
|
144
|
+
result = saved_hash
|
|
145
|
+
else
|
|
146
|
+
say "\n<%= color( %q{removing file '#{_file}'}, RED )%>\n"
|
|
147
|
+
FileUtils.rm_f _file, :verbose => true
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
sleep 1
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
result
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def self.remove_saved_session
|
|
158
|
+
if file = @options.fetch( :output_file )
|
|
159
|
+
_file = File.join( File.dirname( file ), ".#{File.basename( file )}" )
|
|
160
|
+
FileUtils.rm_f( _file, :verbose => false ) if File.file?( _file )
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def self.read_answers_file file
|
|
166
|
+
answers_hash = {} # Read the input file
|
|
167
|
+
|
|
168
|
+
if file
|
|
169
|
+
unless File.exist?(file)
|
|
170
|
+
raise "Could not access the file '#{file}'!"
|
|
171
|
+
end
|
|
172
|
+
else
|
|
173
|
+
file = @options[:system_file]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
begin
|
|
177
|
+
answers_hash = YAML.load(File.read(file))
|
|
178
|
+
answers_hash.empty?
|
|
179
|
+
rescue Errno::EACCES
|
|
180
|
+
error = "WARNING: Could not access the answers file '#{file}'!"
|
|
181
|
+
say "<%= color(%q{#{error}}, YELLOW) %>\n"
|
|
182
|
+
rescue
|
|
183
|
+
# If the file existed, but ingest failed, then there's a problem
|
|
184
|
+
raise "System Configuration File: '#{file}' is corrupted.\nReview the file and either fix or remove it before trying again."
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
answers_hash
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def self.run(args = [])
|
|
191
|
+
begin
|
|
192
|
+
super # parse @options
|
|
193
|
+
rescue OptionParser::InvalidOption=> e
|
|
194
|
+
error = "ERROR: #{e.message}"
|
|
195
|
+
say "\n<%= color(%q{#{error}}, RED) %>\n"
|
|
196
|
+
puts @opt_parser
|
|
197
|
+
exit 1
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Ensure that custom facts are available before the first pluginsync
|
|
201
|
+
%x{puppet config print modulepath}.strip.split(':').each do |dir|
|
|
202
|
+
next unless File.directory?(dir)
|
|
203
|
+
Find.find(dir) do |mod_path|
|
|
204
|
+
fact_path = File.expand_path('lib/facter', mod_path)
|
|
205
|
+
Facter.search(fact_path) if File.directory?(fact_path)
|
|
206
|
+
Find.prune unless mod_path == dir
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# read in answers file
|
|
211
|
+
answers_hash = {}
|
|
212
|
+
if file = @options.fetch( :input_file )
|
|
213
|
+
answers_hash = read_answers_file( file )
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# NOTE: answers from an interrupted session take precedence over input file
|
|
217
|
+
answers_hash = saved_session.merge( answers_hash )
|
|
218
|
+
|
|
219
|
+
# NOTE: answers provided from the cli take precedence over everything else
|
|
220
|
+
cli_answers = Hash[ ARGV[1..-1].map{ |x| x.split '=' } ]
|
|
221
|
+
answers_hash = answers_hash.merge( cli_answers )
|
|
222
|
+
|
|
223
|
+
# get the list of items
|
|
224
|
+
# - applies any known answers at this point
|
|
225
|
+
item_list = Simp::Cli::Config::ItemListFactory.new( @options ).process( nil, answers_hash )
|
|
226
|
+
|
|
227
|
+
# process items:
|
|
228
|
+
# - get any remaining answers
|
|
229
|
+
# - apply changes as needed
|
|
230
|
+
questionnaire = Simp::Cli::Config::Questionnaire.new( @options )
|
|
231
|
+
answers = questionnaire.process( item_list, {} )
|
|
232
|
+
|
|
233
|
+
remove_saved_session
|
|
234
|
+
end
|
|
235
|
+
end
|