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,86 @@
|
|
|
1
|
+
module Simp; end
|
|
2
|
+
class Simp::Cli; end
|
|
3
|
+
module Simp::Cli::Config; end
|
|
4
|
+
|
|
5
|
+
require File.expand_path( '../commands/config', File.dirname(__FILE__) )
|
|
6
|
+
require File.expand_path( 'utils', File.dirname(__FILE__) )
|
|
7
|
+
|
|
8
|
+
# Builds a SIMP configuration profile based on an Array of Config::Items
|
|
9
|
+
#
|
|
10
|
+
# The configuration profile is built on a Questionnaire, which is interactive
|
|
11
|
+
# by default, but can be automated.
|
|
12
|
+
#
|
|
13
|
+
class Simp::Cli::Config::Questionnaire
|
|
14
|
+
|
|
15
|
+
INTERACTIVE = 0
|
|
16
|
+
NONINTERACTIVE = 1
|
|
17
|
+
REALLY_NONINTERACTIVE = 2
|
|
18
|
+
|
|
19
|
+
def initialize( options = {} )
|
|
20
|
+
@options = {
|
|
21
|
+
:noninteractive => INTERACTIVE,
|
|
22
|
+
:verbose => 0
|
|
23
|
+
}.merge( options )
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# processes an Array of Config::Items and returns a hash of Config::Item
|
|
28
|
+
# answers
|
|
29
|
+
def process( item_queue=[], answers={} )
|
|
30
|
+
if item = item_queue.shift
|
|
31
|
+
item.config_items = answers
|
|
32
|
+
process_item item
|
|
33
|
+
|
|
34
|
+
# add (or replace) this item's answer to the answers list
|
|
35
|
+
answers[ item.key ] = item
|
|
36
|
+
|
|
37
|
+
# add any next_items to the queue
|
|
38
|
+
item_queue = item.next_items + item_queue
|
|
39
|
+
|
|
40
|
+
process item_queue, answers
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
answers
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# process a Config::Item
|
|
48
|
+
#
|
|
49
|
+
# simp config can run in the following modes:
|
|
50
|
+
# - interactive (prompt each item)
|
|
51
|
+
# - mostly non-interactive (-f/-A; prompt items that can't be inferred)
|
|
52
|
+
# - never prompt (-a/-ff);
|
|
53
|
+
# - never prompt (-ff; relies on cli args for non-inferrable items))
|
|
54
|
+
def process_item item
|
|
55
|
+
item.skip_query = true if @options[ :noninteractive ] >= NONINTERACTIVE
|
|
56
|
+
if @options.fetch( :fail_on_missing_answers, false )
|
|
57
|
+
item.fail_on_missing_answer = true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if @options[ :noninteractive ] == INTERACTIVE
|
|
61
|
+
item.query
|
|
62
|
+
else
|
|
63
|
+
value = item.default_value
|
|
64
|
+
|
|
65
|
+
if item.validate( value )
|
|
66
|
+
item.value = value
|
|
67
|
+
item.print_summary if @options.fetch( :verbose ) >= 0
|
|
68
|
+
else
|
|
69
|
+
# alert user that the value is wrong
|
|
70
|
+
print_invalid_item_error item
|
|
71
|
+
|
|
72
|
+
# present an interactive prompt for invalid answers unless '-ff'
|
|
73
|
+
exit 1 if @options.fetch( :noninteractive ) >= REALLY_NONINTERACTIVE
|
|
74
|
+
item.skip_query = false
|
|
75
|
+
value = item.query
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
item.safe_apply
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def print_invalid_item_error item
|
|
82
|
+
error = "ERROR: '#{item.value}' is not a valid value for #{item.key}"
|
|
83
|
+
error += "\n#{item.not_valid_message}" if item.not_valid_message
|
|
84
|
+
say "<%= color(%q{#{error}}, RED) %>\n"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
module Simp; end
|
|
2
|
+
class Simp::Cli; end
|
|
3
|
+
module Simp::Cli::Config
|
|
4
|
+
class PasswordError < StandardError; end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class Simp::Cli::Config::Utils
|
|
8
|
+
DEFAULT_PASSWORD_LENGTH = 32
|
|
9
|
+
class << self
|
|
10
|
+
def validate_fqdn fqdn
|
|
11
|
+
# snarfed from:
|
|
12
|
+
# https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch08s15.html
|
|
13
|
+
regex = %r{\A((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\Z}
|
|
14
|
+
((fqdn =~ regex) ? true : false )
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def validate_ip ip
|
|
19
|
+
# using the native 'resolv' class in order to minimize non-EL rubygems
|
|
20
|
+
# snarfed from:
|
|
21
|
+
# http://stackoverflow.com/questions/3634998/how-do-i-check-whether-a-value-in-a-string-is-an-ip-address
|
|
22
|
+
require 'resolv'
|
|
23
|
+
((ip =~ Resolv::IPv4::Regex) || (ip =~ Resolv::IPv6::Regex)) ? true : false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def validate_hostname hostname
|
|
28
|
+
# based on:
|
|
29
|
+
# http://stackoverflow.com/questions/2532053/validate-a-hostname-string
|
|
30
|
+
#
|
|
31
|
+
# nicer solution that only works on ruby1.9+:
|
|
32
|
+
# ( hostname =~ %r{\A(?!-)[a-z0-9-]{1,63}(?<!-)\Z} ) ? true : false
|
|
33
|
+
#
|
|
34
|
+
# ruby1.8-safe version:
|
|
35
|
+
(( hostname =~ %r{\A[a-z0-9-]{1,63}\Z} ) ? true : false ) &&
|
|
36
|
+
(( hostname !~ %r{^-|-$} ) ? true : false )
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def validate_netmask( x )
|
|
41
|
+
# a brute-force regexp that validates all possible valid netmasks
|
|
42
|
+
nums = '(128|192|224|240|248|252|254)'
|
|
43
|
+
znums = '(0|128|192|224|240|248|252|254)'
|
|
44
|
+
regex = /^((#{nums}\.0\.0\.0)|(255\.#{znums}\.0\.0)|(255\.255\.#{znums}\.0)|(255\.255\.255\.#{znums}))$/i
|
|
45
|
+
x =~ regex ? true: false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def validate_hiera_lookup( x )
|
|
50
|
+
x.to_s.strip =~ %r@\%\{.+\}@ ? true : false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# NOTE: requires shell-based cracklib
|
|
55
|
+
# TODO: should we find a better way of returning specific error messages than an exception?
|
|
56
|
+
def validate_password( password )
|
|
57
|
+
require 'shellwords'
|
|
58
|
+
if password.length < 8
|
|
59
|
+
raise Simp::Cli::Config::PasswordError, "Password must be at least 8 characters long"
|
|
60
|
+
false
|
|
61
|
+
else
|
|
62
|
+
pass_result = `echo #{Shellwords.escape(password)} | cracklib-check`.split(':').last.strip
|
|
63
|
+
if pass_result == "OK"
|
|
64
|
+
true
|
|
65
|
+
else
|
|
66
|
+
raise Simp::Cli::Config::PasswordError, "Invalid Password: #{pass_result}"
|
|
67
|
+
false
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def generate_password( length = DEFAULT_PASSWORD_LENGTH )
|
|
74
|
+
password = ''
|
|
75
|
+
special_chars = ['#','%','&','*','+','-','.',':','@']
|
|
76
|
+
symbols = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a
|
|
77
|
+
Integer(length).times { |i| password += (symbols + special_chars)[rand((symbols.length-1 + special_chars.length-1))] }
|
|
78
|
+
# Ensure that the password does not start or end with a special
|
|
79
|
+
# character.
|
|
80
|
+
special_chars.include?(password[0].chr) and password[0] = symbols[rand(symbols.length-1)]
|
|
81
|
+
special_chars.include?(password[password.length-1].chr) and password[password.length-1] = symbols[rand(symbols.length-1)]
|
|
82
|
+
password
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# pure-ruby openldap hash generator
|
|
87
|
+
def encrypt_openldap_hash( string, salt=nil )
|
|
88
|
+
require 'digest/sha1'
|
|
89
|
+
require 'base64'
|
|
90
|
+
|
|
91
|
+
# Ruby 1.8.7 hack to do Random.new.bytes(4):
|
|
92
|
+
salt = salt || (x = ''; 4.times{ x += ((rand * 255).floor.chr ) }; x)
|
|
93
|
+
digest = Digest::SHA1.digest( string + salt )
|
|
94
|
+
|
|
95
|
+
# NOTE: Digest::SHA1.digest in Ruby 1.9+ returns a String encoding in
|
|
96
|
+
# ASCII-8BIT, whereas all other Strings in play are UTF-8
|
|
97
|
+
if RUBY_VERSION.split('.')[0..1].join('.').to_f > 1.8
|
|
98
|
+
digest = digest.force_encoding( 'UTF-8' )
|
|
99
|
+
salt = salt.force_encoding( 'UTF-8' )
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
"{SSHA}"+Base64.encode64( digest + salt ).chomp
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def validate_openldap_hash( x )
|
|
107
|
+
(x =~ %r@\{SSHA\}[A-Za-z0-9=+/]+@ ) ? true : false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def generate_certificates(
|
|
112
|
+
hostnames,
|
|
113
|
+
ca_dir='/etc/puppet/environments/simp/FakeCA'
|
|
114
|
+
)
|
|
115
|
+
result = true
|
|
116
|
+
Dir.chdir( ca_dir ) do
|
|
117
|
+
File.open('togen', 'w'){|file| hostnames.each{ |host| file.puts host }}
|
|
118
|
+
|
|
119
|
+
# NOTE: script must exist in ca_dir
|
|
120
|
+
result = system('./gencerts_nopass.sh auto') && result
|
|
121
|
+
|
|
122
|
+
# blank file so subsequent runs don't re-key our hosts
|
|
123
|
+
File.open('togen', 'w'){ |file| file.truncate(0) }
|
|
124
|
+
end
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Utils
|
|
2
|
+
module_function
|
|
3
|
+
|
|
4
|
+
DEFAULT_PASSWORD_LENGTH = 32
|
|
5
|
+
|
|
6
|
+
def yes_or_no(prompt, default_yes)
|
|
7
|
+
print prompt + (default_yes ? ' [Y|n]: ' : ' [y|N]: ')
|
|
8
|
+
case STDIN.gets
|
|
9
|
+
when /^(y|Y)/
|
|
10
|
+
true
|
|
11
|
+
when /^(n|N)/
|
|
12
|
+
false
|
|
13
|
+
when /^\s*$/
|
|
14
|
+
default_yes
|
|
15
|
+
else
|
|
16
|
+
yes_or_no(prompt, default_yes)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_password
|
|
21
|
+
print 'Enter password: '
|
|
22
|
+
|
|
23
|
+
system('/bin/stty', '-echo')
|
|
24
|
+
password1 = STDIN.gets.strip
|
|
25
|
+
system('/bin/stty', 'echo')
|
|
26
|
+
puts
|
|
27
|
+
|
|
28
|
+
print 'Re-enter password: '
|
|
29
|
+
system('/bin/stty', '-echo')
|
|
30
|
+
password2 = STDIN.gets.strip
|
|
31
|
+
system('/bin/stty', 'echo')
|
|
32
|
+
puts
|
|
33
|
+
|
|
34
|
+
if password1 == password2
|
|
35
|
+
if validate_password(password1)
|
|
36
|
+
password1
|
|
37
|
+
else
|
|
38
|
+
get_password
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
puts " Passwords do not match! Please try again."
|
|
42
|
+
get_password
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def generate_password(length = DEFAULT_PASSWORD_LENGTH, default_is_autogenerate = true)
|
|
47
|
+
password = ''
|
|
48
|
+
if Utils.yes_or_no('Do you want to autogenerate the password?', default_is_autogenerate )
|
|
49
|
+
special_chars = ['#','%','&','*','+','-','.',':','@']
|
|
50
|
+
symbols = ('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a
|
|
51
|
+
Integer(length).times { |i| password += (symbols + special_chars)[rand((symbols.length-1 + special_chars.length-1))] }
|
|
52
|
+
# Ensure that the password does not start or end with a special
|
|
53
|
+
# character.
|
|
54
|
+
special_chars.include?(password[0].chr) and password[0] = symbols[rand(symbols.length-1)]
|
|
55
|
+
special_chars.include?(password[password.length-1].chr) and password[password.length-1] = symbols[rand(symbols.length-1)]
|
|
56
|
+
puts "Your password is:\n#{password}"
|
|
57
|
+
print 'Push [ENTER] to continue.'
|
|
58
|
+
$stdout.flush
|
|
59
|
+
$stdin.gets
|
|
60
|
+
else
|
|
61
|
+
password = Utils.get_password
|
|
62
|
+
end
|
|
63
|
+
password
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def validate_password(password)
|
|
67
|
+
require 'shellwords'
|
|
68
|
+
|
|
69
|
+
if password.length < 8
|
|
70
|
+
puts " Invalid Password: Password must be at least 8 characters long"
|
|
71
|
+
false
|
|
72
|
+
else
|
|
73
|
+
pass_result = `echo #{Shellwords.escape(password)} | cracklib-check`.split(':').last.strip
|
|
74
|
+
if pass_result == "OK"
|
|
75
|
+
true
|
|
76
|
+
else
|
|
77
|
+
puts " Invalid Password: #{pass_result}"
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def get_value(default_value = '')
|
|
84
|
+
case default_value
|
|
85
|
+
when /\d+\.\d+\.\d+\.\d+/
|
|
86
|
+
print "Enter a new IP: "
|
|
87
|
+
value = STDIN.gets.strip
|
|
88
|
+
while !valid_ip?(value)
|
|
89
|
+
puts "INVALID! Try again..."
|
|
90
|
+
print "Enter a new IP: "
|
|
91
|
+
value = STDIN.gets.strip
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
print "Enter a value: "
|
|
95
|
+
value = STDIN.gets.strip
|
|
96
|
+
end
|
|
97
|
+
value
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def generate_certificates(hostname)
|
|
101
|
+
Dir.chdir('/etc/puppet/Config/FakeCA') do
|
|
102
|
+
file = File.open('togen', 'w')
|
|
103
|
+
file.puts hostname
|
|
104
|
+
file.close
|
|
105
|
+
|
|
106
|
+
passphrase = `cat cacertkey`.chomp
|
|
107
|
+
system('./gencerts_nopass.sh auto')
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def valid_ip?(value)
|
|
112
|
+
value.to_s =~ /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
|
113
|
+
end
|
|
114
|
+
end
|
data/lib/simp/simp.rb
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
class Simp
|
|
3
|
+
current_dir = File.dirname(File.expand_path(__FILE__)) + '/simp'
|
|
4
|
+
|
|
5
|
+
require 'optparse'
|
|
6
|
+
require current_dir + '/lib/utils'
|
|
7
|
+
|
|
8
|
+
protected
|
|
9
|
+
def self.menu
|
|
10
|
+
puts "Usage: simp [command]"
|
|
11
|
+
puts
|
|
12
|
+
puts " Commands"
|
|
13
|
+
@commands.each do |command_name, command_class|
|
|
14
|
+
puts " - " + command_name
|
|
15
|
+
end
|
|
16
|
+
puts " - help [command]"
|
|
17
|
+
puts
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.help
|
|
21
|
+
puts @opt_parser.to_s
|
|
22
|
+
puts
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.run(args = [])
|
|
26
|
+
@opt_parser.parse!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
def self.version
|
|
31
|
+
begin
|
|
32
|
+
%x{rpm -q simp}.split(/\n/).last.match(/([0-9]+\.[0-9]+\.?[0-9]*)/)[1]
|
|
33
|
+
rescue
|
|
34
|
+
#raise "Simp is not installed!"
|
|
35
|
+
'4.1'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# load the commands from commands/*.rb and grab the classes that are simp commands
|
|
40
|
+
Dir.glob(current_dir + '/commands/*.rb').sort_by(&:to_s).each do |command_file|
|
|
41
|
+
require command_file
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
@commands = Simp::Commands::constants.inject({}) do |commands, constant|
|
|
45
|
+
obj = Simp::Commands.const_get(constant)
|
|
46
|
+
if obj.respond_to?(:superclass) and obj.superclass == Simp
|
|
47
|
+
commands[constant.to_s.downcase] = obj
|
|
48
|
+
end
|
|
49
|
+
commands
|
|
50
|
+
end
|
|
51
|
+
@commands['version'] = self
|
|
52
|
+
|
|
53
|
+
if ARGV.length == 0 or (ARGV.length == 1 and ARGV[0] == 'help')
|
|
54
|
+
menu
|
|
55
|
+
elsif ARGV[0] == 'version'
|
|
56
|
+
puts version
|
|
57
|
+
elsif ARGV[0] == 'help'
|
|
58
|
+
if (command = @commands[ARGV[1]]).nil?
|
|
59
|
+
puts "\n\033[31m#{ARGV[1]} is not a recognized command\033[39m\n\n"
|
|
60
|
+
menu
|
|
61
|
+
elsif ARGV[1] == 'version'
|
|
62
|
+
puts "Display the current version of SIMP."
|
|
63
|
+
else
|
|
64
|
+
command.help
|
|
65
|
+
end
|
|
66
|
+
elsif (command = @commands[ARGV[0]]).nil?
|
|
67
|
+
puts "\n\033[31m#{ARGV[0]} is not a recognized command\033[39m\n\n"
|
|
68
|
+
menu
|
|
69
|
+
else
|
|
70
|
+
begin
|
|
71
|
+
command.run(ARGV.drop(1))
|
|
72
|
+
rescue => e
|
|
73
|
+
puts "\n\033[31m#{e.message}\033[39m\n\n"
|
|
74
|
+
e.backtrace.first(10).each{|l| puts l }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'simp/cli/commands/config'
|
|
2
|
+
require 'simp/cli/config/item'
|
|
3
|
+
require_relative( '../spec_helper' )
|
|
4
|
+
|
|
5
|
+
require 'yaml'
|
|
6
|
+
|
|
7
|
+
describe Simp::Cli::Commands::Config do
|
|
8
|
+
### describe ".print_answers_yaml" do
|
|
9
|
+
### before :each do
|
|
10
|
+
### ci = Simp::Cli::Config::Item.new
|
|
11
|
+
### ci.key = 'item'
|
|
12
|
+
### ci.value = 'foo'
|
|
13
|
+
### ci.description = 'A simple item'
|
|
14
|
+
### list = { foo: ci }
|
|
15
|
+
###
|
|
16
|
+
### ci = Simp::Cli::Config::ListItem.new
|
|
17
|
+
### ci.key = 'list'
|
|
18
|
+
### ci.value = ['one','two','three']
|
|
19
|
+
### ci.description = 'A simple list'
|
|
20
|
+
### list[ci.key] = ci
|
|
21
|
+
###
|
|
22
|
+
### ci = Simp::Cli::Config::YesNoItem.new
|
|
23
|
+
### ci.key = 'yesno'
|
|
24
|
+
### ci.value = true
|
|
25
|
+
### ci.description = 'A simple yes/no item'
|
|
26
|
+
### list[ci.key] = ci
|
|
27
|
+
###
|
|
28
|
+
### @simple_item_list = list
|
|
29
|
+
### end
|
|
30
|
+
###
|
|
31
|
+
### it "prints yaml" do
|
|
32
|
+
### io = StringIO.new
|
|
33
|
+
### Simp::Cli::Commands::Config.print_answers_yaml io, @simple_item_list
|
|
34
|
+
### y = YAML.load io.string
|
|
35
|
+
### expect( y ).to be_kind_of Hash
|
|
36
|
+
### expect( y ).not_to be_empty
|
|
37
|
+
### expect( y['item'] ).to eq('foo')
|
|
38
|
+
### expect( y['list'] ).to eq(['one','two','three'])
|
|
39
|
+
### expect( y['yesno'] ).to eq(true)
|
|
40
|
+
### end
|
|
41
|
+
### end
|
|
42
|
+
end
|