dust-deploy 0.4.1 → 0.4.2
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.
- data/changelog.md +7 -0
- data/lib/dust.rb +0 -1
- data/lib/dust/examples/templates/hash_check/weak_passwords +26 -0
- data/lib/dust/helper.rb +21 -0
- data/lib/dust/recipes/aliases.rb +2 -1
- data/lib/dust/recipes/basic_setup.rb +1 -1
- data/lib/dust/recipes/duplicity.rb +4 -6
- data/lib/dust/recipes/etc_hosts.rb +1 -1
- data/lib/dust/recipes/hash_check.rb +44 -0
- data/lib/dust/recipes/motd.rb +2 -6
- data/lib/dust/recipes/mysql.rb +1 -4
- data/lib/dust/recipes/newrelic.rb +4 -2
- data/lib/dust/recipes/nginx.rb +4 -20
- data/lib/dust/recipes/postgres.rb +8 -28
- data/lib/dust/recipes/zabbix_agent.rb +13 -20
- data/lib/dust/server.rb +157 -61
- data/lib/dust/version.rb +1 -1
- metadata +5 -4
- data/lib/dust/convert_size.rb +0 -21
data/changelog.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
Changelog
|
2
2
|
=============
|
3
3
|
|
4
|
+
0.4.2
|
5
|
+
------------
|
6
|
+
|
7
|
+
adds hash_check recipe, which can check for weak hashes (according to provided list) in your /etc/shadow files.
|
8
|
+
can be used e.g. for making sure that none of your servers still has the template password.
|
9
|
+
|
10
|
+
|
4
11
|
0.4.1
|
5
12
|
------------
|
6
13
|
|
data/lib/dust.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
root
|
2
|
+
toor
|
3
|
+
user
|
4
|
+
123456
|
5
|
+
12345
|
6
|
+
password
|
7
|
+
password1
|
8
|
+
123456789
|
9
|
+
12345678
|
10
|
+
1234567890
|
11
|
+
abc123
|
12
|
+
computer
|
13
|
+
tigger
|
14
|
+
1234
|
15
|
+
qwerty
|
16
|
+
money
|
17
|
+
carmen
|
18
|
+
mickey
|
19
|
+
secret
|
20
|
+
summer
|
21
|
+
internet
|
22
|
+
a1b2c3
|
23
|
+
123
|
24
|
+
service
|
25
|
+
hello
|
26
|
+
123abc
|
data/lib/dust/helper.rb
CHANGED
@@ -49,3 +49,24 @@ class String
|
|
49
49
|
false
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
|
54
|
+
module Dust
|
55
|
+
# converts string to kilobytes (rounded)
|
56
|
+
def self.convert_size s
|
57
|
+
i, unit = s.split(' ')
|
58
|
+
|
59
|
+
case unit.downcase
|
60
|
+
when 'kb'
|
61
|
+
return i.to_i
|
62
|
+
when 'mb'
|
63
|
+
return (i.to_f * 1024).to_i
|
64
|
+
when 'gb'
|
65
|
+
return (i.to_f * 1024 * 1024).to_i
|
66
|
+
when 'tb'
|
67
|
+
return (i.to_f * 1024 * 1024 * 1024).to_i
|
68
|
+
else
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/dust/recipes/aliases.rb
CHANGED
@@ -2,7 +2,8 @@ class Aliases < Recipe
|
|
2
2
|
desc 'aliases:deploy', 'installs email aliases'
|
3
3
|
def deploy
|
4
4
|
return unless @node.package_installed? 'postfix'
|
5
|
-
|
5
|
+
|
6
|
+
@node.deploy_file "#{@template_path}/aliases", '/etc/aliases', :binding => binding
|
6
7
|
|
7
8
|
::Dust.print_msg 'running newaliases'
|
8
9
|
::Dust.print_result @node.exec('newaliases')[:exit_code]
|
@@ -25,7 +25,7 @@ class BasicSetup < Recipe
|
|
25
25
|
::Dust.print_msg "deploying configuration files for root\n"
|
26
26
|
Dir["#{@template_path}/.*"].each do |file|
|
27
27
|
next unless File.file? file
|
28
|
-
@node.
|
28
|
+
@node.deploy_file file, "/root/#{File.basename file}", { :binding => binding, :indent => 2 }
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class Duplicity < Recipe
|
4
2
|
desc 'duplicity:deploy', 'installs and configures duplicity backups'
|
5
3
|
def deploy
|
@@ -46,11 +44,11 @@ class Duplicity < Recipe
|
|
46
44
|
cronjob_path = "/etc/cron.#{config['interval']}/duplicity-#{scenario}"
|
47
45
|
|
48
46
|
# adjust and upload cronjob
|
49
|
-
|
50
|
-
::Dust.print_msg "adjusting and deploying cronjob (scenario: #{scenario}, interval: #{config['interval']})\n"
|
47
|
+
::Dust.print_msg "adjusting and deploying cronjob (scenario: #{scenario}, interval: #{config['interval']})\n"
|
51
48
|
config['options'].each { |option| ::Dust.print_ok "adding option: #{option}", :indent => 2 }
|
52
|
-
|
53
|
-
|
49
|
+
|
50
|
+
@node.deploy_file "#{@template_path}/cronjob", cronjob_path, :binding => binding
|
51
|
+
|
54
52
|
# making cronjob executeable
|
55
53
|
@node.chmod '0700', cronjob_path
|
56
54
|
puts
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class EtcHosts < Recipe
|
2
2
|
desc 'etc_hosts:deploy', 'deploys /etc/hosts'
|
3
3
|
def deploy
|
4
|
-
@node.
|
4
|
+
@node.deploy_file "#{@template_path}/hosts", '/etc/hosts', :binding => binding
|
5
5
|
|
6
6
|
# restart dns service
|
7
7
|
if @options.restart? and @config.is_a? String
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class HashCheck < Recipe
|
2
|
+
|
3
|
+
desc 'hash_check:deploy', 'checks /etc/shadow for weak hashes'
|
4
|
+
def deploy
|
5
|
+
# mkpasswd is in the package 'whois' resp. 'expect'
|
6
|
+
@node.install_package 'whois' if @node.uses_apt?
|
7
|
+
@node.install_package 'expect' if @node.uses_rpm?
|
8
|
+
|
9
|
+
# those keys indicate that no password is set, or login is disabled
|
10
|
+
keys = [ '*', '!', '!!', '', 'LK', 'NP' ]
|
11
|
+
|
12
|
+
# mapping the magic numbers to the actual hash algorithms
|
13
|
+
algorithms = { '1' => 'md5', '2' => 'blowfish', '5' => 'sha-256', '6' => 'sha-512' }
|
14
|
+
|
15
|
+
weak_passwords = File.open "#{@template_path}/weak_passwords", 'r'
|
16
|
+
shadow = @node.exec('cat /etc/shadow')[:stdout]
|
17
|
+
|
18
|
+
::Dust.print_msg "checking for weak password hashes\n"
|
19
|
+
|
20
|
+
found_weak = false
|
21
|
+
|
22
|
+
shadow.each do |line|
|
23
|
+
user, hash = line.split(':')[0..1]
|
24
|
+
next if keys.include? hash
|
25
|
+
method, salt = hash.split('$')[1..2]
|
26
|
+
|
27
|
+
weak_passwords.each_line do |password|
|
28
|
+
password.chomp!
|
29
|
+
|
30
|
+
# generate the hash for this password, according to salt and method
|
31
|
+
weak_hash = @node.exec("mkpasswd -m #{algorithms[method.to_s]} -S '#{salt}' '#{password}'")[:stdout]
|
32
|
+
weak_hash.chomp!
|
33
|
+
|
34
|
+
if weak_hash == hash
|
35
|
+
::Dust.print_failed "user #{user} has a weak password! (#{password})", :indent => 2
|
36
|
+
found_weak= true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
weak_passwords.close
|
42
|
+
::Dust.print_ok 'none found.', :indent => 2 unless found_weak
|
43
|
+
end
|
44
|
+
end
|
data/lib/dust/recipes/motd.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class Motd < Recipe
|
4
2
|
desc 'motd:deploy', 'creates message of the day'
|
5
|
-
def deploy
|
6
|
-
#
|
7
|
-
template = ERB.new File.read("#{@template_path}/motd.erb"), nil, '%<>'
|
8
|
-
@node.write '/etc/motd', template.result(binding)
|
3
|
+
def deploy
|
4
|
+
@node.deploy_file "#{@template_path}/motd", '/etc/motd', :binding => binding
|
9
5
|
end
|
10
6
|
end
|
data/lib/dust/recipes/mysql.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class Mysql < Recipe
|
4
2
|
desc 'mysql:deploy', 'installs and configures mysql database'
|
5
3
|
def deploy
|
@@ -36,8 +34,7 @@ class Mysql < Recipe
|
|
36
34
|
|
37
35
|
::Dust.print_ok "setting innodb buffer pool to '#{@config['innodb_buffer_pool_size']}'", :indent => 2
|
38
36
|
|
39
|
-
|
40
|
-
@node.write '/etc/mysql/my.cnf', template.result(binding)
|
37
|
+
@node.deploy_file "#{@template_path}/my.cnf", '/etc/mysql/my.cnf', :binding => binding
|
41
38
|
@node.chmod '644', '/etc/mysql/my.cnf'
|
42
39
|
|
43
40
|
@node.restart_service 'mysql-server' if options.restart?
|
@@ -4,8 +4,10 @@ class Newrelic < Recipe
|
|
4
4
|
return Dust.print_failed 'no key specified' unless @config
|
5
5
|
return unless @node.uses_apt? :quiet=>false
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
if @options.restart? or @options.reload?
|
8
|
+
::Dust.print_msg 'updating repositories'
|
9
|
+
::Dust.print_result @node.exec('aptitude update')[:exit_code]
|
10
|
+
end
|
9
11
|
|
10
12
|
unless @node.install_package 'newrelic-sysmond'
|
11
13
|
::Dust.print_failed 'installing newrelic monitoring daemon failed, did you setup the newrelic repositories?'
|
data/lib/dust/recipes/nginx.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class Nginx < Recipe
|
4
2
|
desc 'nginx:deploy', 'installs and configures nginx web server'
|
5
3
|
def deploy
|
@@ -14,27 +12,13 @@ class Nginx < Recipe
|
|
14
12
|
::Dust.print_ok
|
15
13
|
|
16
14
|
@config.each do |state, site|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if File.exists? file
|
21
|
-
@node.scp file, "/etc/nginx/sites-available/#{site}"
|
22
|
-
|
23
|
-
# if this site is an erb template, render it and deploy
|
24
|
-
elsif File.exists? "#{file}.erb"
|
25
|
-
template = ERB.new( File.read("#{file}.erb"), nil, '%<>')
|
26
|
-
@node.write "/etc/nginx/sites-available/#{site}", template.result(binding)
|
27
|
-
|
28
|
-
# skip to next site if template wasn't found
|
29
|
-
else
|
30
|
-
::Dust.print_failed "couldn't find template for #{site}", :indent => 2
|
31
|
-
next
|
32
|
-
end
|
33
|
-
|
15
|
+
|
16
|
+
@node.deploy_file "#{@template_path}/sites/#{site}", "/etc/nginx/sites-available/#{site}", :binding => binding
|
17
|
+
|
34
18
|
# symlink to sites-enabled if this is listed as an enabled site
|
35
19
|
if state == 'sites-enabled'
|
36
20
|
::Dust.print_msg "enabling #{site}", :indent => 2
|
37
|
-
::Dust.print_result
|
21
|
+
::Dust.print_result @node.exec("cd /etc/nginx/sites-enabled && ln -s ../sites-available/#{site} #{site}")[:exit_code]
|
38
22
|
end
|
39
23
|
end
|
40
24
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class Postgres < Recipe
|
4
2
|
desc 'postgres:deploy', 'installs and configures postgresql database'
|
5
3
|
def deploy
|
@@ -24,9 +22,9 @@ class Postgres < Recipe
|
|
24
22
|
end
|
25
23
|
|
26
24
|
|
27
|
-
deploy_file
|
28
|
-
deploy_file
|
29
|
-
deploy_file
|
25
|
+
@node.deploy_file "#{@template_path}/postgresql.conf", "#{@config['conf-dir']}/postgresql.conf", :binding => binding
|
26
|
+
@node.deploy_file "#{@template_path}/pg_hba.conf", "#{@config['conf-dir']}/pg_hba.conf", :binding => binding
|
27
|
+
@node.deploy_file "#{@template_path}/pg_ident.conf", "#{@config['conf-dir']}/pg_ident.conf", :binding => binding
|
30
28
|
|
31
29
|
@node.chmod '644', "#{@config['conf-dir']}/postgresql.conf"
|
32
30
|
@node.chmod '644', "#{@config['conf-dir']}/pg_hba.conf"
|
@@ -34,21 +32,21 @@ class Postgres < Recipe
|
|
34
32
|
|
35
33
|
# deploy pacemaker script
|
36
34
|
if @node.package_installed? 'pacemaker'
|
37
|
-
deploy_file
|
35
|
+
@node.deploy_file "#{@template_path}/pacemaker.sh", "#{@config['conf-dir']}/pacemaker.sh", :binding => binding
|
38
36
|
@node.chmod '755', "#{@config['conf-dir']}/pacemaker.sh"
|
39
37
|
end
|
40
38
|
|
41
39
|
# copy recovery.conf to either recovery.conf or recovery.done
|
42
40
|
# depending on which file already exists.
|
43
41
|
if @node.file_exists? "#{@config['data-dir']}/recovery.conf", :quiet => true
|
44
|
-
deploy_file
|
42
|
+
@node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.conf", :binding => binding
|
45
43
|
else
|
46
|
-
deploy_file
|
44
|
+
@node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.done", :binding => binding
|
47
45
|
end
|
48
46
|
|
49
47
|
# deploy certificates to data-dir
|
50
|
-
deploy_file
|
51
|
-
deploy_file
|
48
|
+
@node.deploy_file "#{@template_path}/server.crt", "#{@config['data-dir']}/server.crt", :binding => binding
|
49
|
+
@node.deploy_file "#{@template_path}/server.key", "#{@config['data-dir']}/server.key", :binding => binding
|
52
50
|
|
53
51
|
@node.chown @config['dbuser'], @config['data-dir'] if @config['dbuser']
|
54
52
|
@node.chmod 'u+Xrw,g-rwx,o-rwx', @config['data-dir']
|
@@ -91,23 +89,5 @@ class Postgres < Recipe
|
|
91
89
|
@node.reload_service @config['service-name'] if options.reload?
|
92
90
|
end
|
93
91
|
|
94
|
-
private
|
95
|
-
def deploy_file file, target
|
96
|
-
# if file is just a regular file, copy it to sites-available
|
97
|
-
if File.exists? "#{@template_path}/#{file}"
|
98
|
-
@node.scp "#{@template_path}/#{file}", target
|
99
|
-
|
100
|
-
# if file is an erb template, render it and deploy
|
101
|
-
elsif File.exists? "#{@template_path}/#{file}.erb"
|
102
|
-
::Dust.print_msg "adjusting and deploying #{file}"
|
103
|
-
template = ERB.new( File.read("#{@template_path}/#{file}.erb"), nil, '%<>')
|
104
|
-
::Dust.print_result @node.write(target, template.result(binding), :quiet => true)
|
105
|
-
|
106
|
-
# file was not found, return
|
107
|
-
else
|
108
|
-
return ::Dust.print_failed "file '#{@template_path}/#{file}' not found."
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
92
|
end
|
113
93
|
|
@@ -1,24 +1,16 @@
|
|
1
|
-
require 'erb'
|
2
|
-
|
3
1
|
class ZabbixAgent < Recipe
|
4
2
|
desc 'zabbix_agent:deploy', 'installs and configures zabbix agent'
|
5
3
|
def deploy
|
6
4
|
return unless install_zabbix
|
7
5
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
@node.
|
12
|
-
|
13
|
-
|
6
|
+
@node.deploy_file "#{@template_path}/zabbix_agentd.conf", '/etc/zabbix/zabbix_agentd.conf', :binding => binding
|
7
|
+
|
8
|
+
# set daemon name, according zu distribution
|
9
|
+
daemon = @node.uses_emerge? ? 'zabbix-agentd' : 'zabbix-agent'
|
10
|
+
|
14
11
|
# restart using new configuration
|
15
|
-
|
16
|
-
|
17
|
-
@node.restart_service 'zabbix-agentd' if options.restart?
|
18
|
-
else
|
19
|
-
@node.autostart_service 'zabbix-agent'
|
20
|
-
@node.restart_service 'zabbix-agent' if options.restart?
|
21
|
-
end
|
12
|
+
@node.autostart_service daemon
|
13
|
+
@node.restart_service daemon if options.restart?
|
22
14
|
end
|
23
15
|
|
24
16
|
private
|
@@ -26,15 +18,13 @@ class ZabbixAgent < Recipe
|
|
26
18
|
def install_zabbix
|
27
19
|
|
28
20
|
if @node.uses_apt?
|
21
|
+
# debsecan is needed for zabbix checks (security updates)
|
29
22
|
return false unless @node.install_package 'zabbix-agent'
|
30
|
-
|
31
|
-
# debsecan is needed for zabbix checks (security updates)
|
32
23
|
return false unless @node.install_package 'debsecan'
|
33
24
|
|
34
25
|
elsif @node.uses_emerge?
|
26
|
+
# glsa-check (part of gentoolkit) is needed for zabbix checks (security updates)
|
35
27
|
return false unless @node.install_package 'zabbix', :env => 'USE=agent'
|
36
|
-
|
37
|
-
# glsa-check (part of gentoolkit) is needed for zabbix checks (security updates)
|
38
28
|
return false unless @node.install_package 'gentoolkit'
|
39
29
|
|
40
30
|
elsif @node.uses_rpm?
|
@@ -49,6 +39,9 @@ class ZabbixAgent < Recipe
|
|
49
39
|
true
|
50
40
|
end
|
51
41
|
|
42
|
+
|
43
|
+
# below this line is unfinished code, not in use yet
|
44
|
+
|
52
45
|
# TODO (not yet finished)
|
53
46
|
desc 'zabbix_agent:postgres', 'configure postgres database for zabbix monitoring'
|
54
47
|
def postgres
|
@@ -69,7 +62,7 @@ class ZabbixAgent < Recipe
|
|
69
62
|
::Dust.print_result( @node.exec('createuser -U postgres zabbix -RSD')[:exit_code] )
|
70
63
|
end
|
71
64
|
|
72
|
-
# TODO: only GRANT is this is a master
|
65
|
+
# TODO: only GRANT is this is a master
|
73
66
|
::Dust.print_msg 'GRANT zabbix user access to postgres database'
|
74
67
|
::Dust.print_result( @node.exec('psql -U postgres -c "GRANT SELECT ON pg_stat_database TO zabbix" postgres')[:exit_code] )
|
75
68
|
|
data/lib/dust/server.rb
CHANGED
@@ -2,37 +2,41 @@ require 'rubygems'
|
|
2
2
|
require 'net/ssh'
|
3
3
|
require 'net/scp'
|
4
4
|
require 'net/ssh/proxy/socks5'
|
5
|
+
require 'erb'
|
5
6
|
|
6
7
|
module Dust
|
7
8
|
class Server
|
8
9
|
attr_reader :ssh
|
9
10
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@
|
11
|
+
def default_options options = {}
|
12
|
+
{ :quiet => false, :indent => 1 }.merge options
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize node
|
16
|
+
@node = node
|
17
|
+
@node['user'] ||= 'root'
|
18
|
+
@node['port'] ||= 22
|
19
|
+
@node['password'] ||= ''
|
16
20
|
end
|
17
21
|
|
18
22
|
def connect
|
19
|
-
Dust.print_hostname @
|
23
|
+
Dust.print_hostname @node['hostname']
|
20
24
|
begin
|
21
25
|
# connect to proxy if given
|
22
|
-
if @
|
23
|
-
host, port = @
|
26
|
+
if @node['proxy']
|
27
|
+
host, port = @node['proxy'].split ':'
|
24
28
|
proxy = Net::SSH::Proxy::SOCKS5.new host, port
|
25
29
|
else
|
26
30
|
proxy = nil
|
27
31
|
end
|
28
32
|
|
29
|
-
@ssh = Net::SSH.start @
|
30
|
-
{ :password => @
|
31
|
-
:port => @
|
33
|
+
@ssh = Net::SSH.start @node['fqdn'], @node['user'],
|
34
|
+
{ :password => @node['password'],
|
35
|
+
:port => @node['port'],
|
32
36
|
:proxy => proxy }
|
33
37
|
rescue Exception
|
34
|
-
error_message = "coudln't connect to #{@
|
35
|
-
error_message += " (via socks5 proxy #{@
|
38
|
+
error_message = "coudln't connect to #{@node['fqdn']}"
|
39
|
+
error_message += " (via socks5 proxy #{@node['proxy']})" if proxy
|
36
40
|
Dust.print_failed error_message
|
37
41
|
return false
|
38
42
|
end
|
@@ -66,7 +70,9 @@ module Dust
|
|
66
70
|
end
|
67
71
|
|
68
72
|
|
69
|
-
def write target, text, options={
|
73
|
+
def write target, text, options = {}
|
74
|
+
options = default_options.merge options
|
75
|
+
|
70
76
|
Dust.print_msg "deploying #{File.basename target}", options
|
71
77
|
|
72
78
|
# escape $ signs and \ at the end of line
|
@@ -84,40 +90,54 @@ module Dust
|
|
84
90
|
restorecon target, options # restore SELinux labels
|
85
91
|
end
|
86
92
|
|
87
|
-
def append target, text, options={
|
93
|
+
def append target, text, options = {}
|
94
|
+
options = default_options.merge options
|
95
|
+
|
88
96
|
Dust.print_msg "appending to #{File.basename target}", options
|
89
97
|
Dust.print_result exec("cat << EOF >> #{target}\n#{text}\nEOF")[:exit_code], options
|
90
98
|
end
|
91
99
|
|
92
|
-
def scp source, destination, options={
|
100
|
+
def scp source, destination, options = {}
|
101
|
+
options = default_options.merge options
|
102
|
+
|
93
103
|
Dust.print_msg "deploying #{File.basename(source)}", options
|
94
104
|
@ssh.scp.upload! source, destination
|
95
105
|
Dust.print_ok '', options
|
96
106
|
restorecon destination, options # restore SELinux labels
|
97
107
|
end
|
98
108
|
|
99
|
-
def symlink source, destination, options={
|
109
|
+
def symlink source, destination, options = {}
|
110
|
+
options = default_options.merge options
|
111
|
+
|
100
112
|
Dust.print_msg "symlinking #{File.basename(source)} to '#{destination}'", options
|
101
113
|
Dust.print_result exec("ln -s #{source} #{destination}")[:exit_code], options
|
102
114
|
restorecon destination, options # restore SELinux labels
|
103
115
|
end
|
104
116
|
|
105
|
-
def chmod mode, file, options={
|
117
|
+
def chmod mode, file, options = {}
|
118
|
+
options = default_options.merge options
|
119
|
+
|
106
120
|
Dust.print_msg "setting mode of #{File.basename(file)} to #{mode}", options
|
107
121
|
Dust.print_result exec("chmod -R #{mode} #{file}")[:exit_code], options
|
108
122
|
end
|
109
123
|
|
110
|
-
def chown user, file, options={
|
124
|
+
def chown user, file, options = {}
|
125
|
+
options = default_options.merge options
|
126
|
+
|
111
127
|
Dust.print_msg "setting owner of #{File.basename(file)} to #{user}", options
|
112
128
|
Dust.print_result exec("chown -R #{user} #{file}")[:exit_code], options
|
113
129
|
end
|
114
130
|
|
115
|
-
def rm file, options={
|
131
|
+
def rm file, options = {}
|
132
|
+
options = default_options.merge options
|
133
|
+
|
116
134
|
Dust.print_msg "deleting #{file}", options
|
117
135
|
Dust.print_result exec("rm -rf #{file}")[:exit_code], options
|
118
136
|
end
|
119
137
|
|
120
|
-
def mkdir dir, options={
|
138
|
+
def mkdir dir, options = {}
|
139
|
+
options = default_options.merge options
|
140
|
+
|
121
141
|
return true if dir_exists? dir, :quiet => true
|
122
142
|
|
123
143
|
Dust.print_msg "creating directory #{dir}", options
|
@@ -127,7 +147,9 @@ module Dust
|
|
127
147
|
|
128
148
|
# check if restorecon (selinux) is available
|
129
149
|
# if so, run it on "path" recursively
|
130
|
-
def restorecon path, options={
|
150
|
+
def restorecon path, options = {}
|
151
|
+
options = default_options.merge options
|
152
|
+
|
131
153
|
|
132
154
|
# if restorecon is not installed, just return true
|
133
155
|
ret = exec 'which restorecon'
|
@@ -137,7 +159,9 @@ module Dust
|
|
137
159
|
Dust.print_result exec("#{ret[:stdout].chomp} -R #{path}")[:exit_code], options
|
138
160
|
end
|
139
161
|
|
140
|
-
def get_system_users options={
|
162
|
+
def get_system_users options = {}
|
163
|
+
options = default_options.merge options
|
164
|
+
|
141
165
|
Dust.print_msg "getting all system users", options
|
142
166
|
ret = exec 'getent passwd |cut -d: -f1'
|
143
167
|
Dust.print_result ret[:exit_code], options
|
@@ -150,7 +174,9 @@ module Dust
|
|
150
174
|
end
|
151
175
|
|
152
176
|
# checks if one of the packages is installed
|
153
|
-
def package_installed? packages, options={
|
177
|
+
def package_installed? packages, options = {}
|
178
|
+
options = default_options.merge options
|
179
|
+
|
154
180
|
packages = [ packages ] if packages.is_a? String
|
155
181
|
|
156
182
|
Dust.print_msg "checking if #{packages.join(' or ')} is installed", options
|
@@ -168,10 +194,16 @@ module Dust
|
|
168
194
|
Dust.print_failed '', options
|
169
195
|
end
|
170
196
|
|
171
|
-
def install_package package, options={
|
172
|
-
|
197
|
+
def install_package package, options = {}
|
198
|
+
options = default_options.merge options
|
199
|
+
options[:env] ||= ''
|
200
|
+
|
201
|
+
if package_installed? package, :quiet=>true
|
202
|
+
return Dust.print_ok "package #{package} already installed"
|
203
|
+
end
|
204
|
+
|
205
|
+
Dust.print_msg "installing #{package}", :indent => options[:indent] + 1
|
173
206
|
|
174
|
-
Dust.print_msg "installing #{package}", {:quiet => options[:quiet], :indent => options[:indent] + 1}
|
175
207
|
if uses_apt?
|
176
208
|
exec "DEBIAN_FRONTEND=noninteractive aptitude install -y #{package}"
|
177
209
|
elsif uses_emerge?
|
@@ -186,7 +218,9 @@ module Dust
|
|
186
218
|
Dust.print_result package_installed? package, :quiet => true
|
187
219
|
end
|
188
220
|
|
189
|
-
def remove_package package, options={
|
221
|
+
def remove_package package, options = {}
|
222
|
+
options = default_options.merge options
|
223
|
+
|
190
224
|
unless package_installed? package, :quiet => true
|
191
225
|
return Dust.print_ok "package #{package} not installed", options
|
192
226
|
end
|
@@ -203,7 +237,9 @@ module Dust
|
|
203
237
|
end
|
204
238
|
end
|
205
239
|
|
206
|
-
def update_repos options={
|
240
|
+
def update_repos options = {}
|
241
|
+
options = default_options.merge options
|
242
|
+
|
207
243
|
Dust.print_msg 'updating system repositories', options
|
208
244
|
|
209
245
|
if uses_apt?
|
@@ -217,7 +253,9 @@ module Dust
|
|
217
253
|
end
|
218
254
|
end
|
219
255
|
|
220
|
-
def system_update options={
|
256
|
+
def system_update options = {}
|
257
|
+
options = default_options.merge options
|
258
|
+
|
221
259
|
Dust.print_msg 'installing system updates', options
|
222
260
|
|
223
261
|
if uses_apt?
|
@@ -241,27 +279,35 @@ module Dust
|
|
241
279
|
|
242
280
|
# determining the system packet manager has to be done without facter
|
243
281
|
# because it's used to find out whether facter is installed / install facter
|
244
|
-
def uses_apt? options={
|
282
|
+
def uses_apt? options = {}
|
283
|
+
options = default_options(:quiet => true).merge options
|
284
|
+
|
245
285
|
Dust.print_msg 'determining whether node uses apt', options
|
246
286
|
Dust.print_result exec('test -e /etc/debian_version')[:exit_code], options
|
247
287
|
end
|
248
288
|
|
249
|
-
def uses_rpm? options={
|
289
|
+
def uses_rpm? options = {}
|
290
|
+
options = default_options(:quiet => true).merge options
|
291
|
+
|
250
292
|
Dust.print_msg 'determining whether node uses rpm', options
|
251
293
|
Dust.print_result exec('test -e /etc/redhat-release')[:exit_code], options
|
252
294
|
end
|
253
295
|
|
254
|
-
def uses_emerge? options={
|
296
|
+
def uses_emerge? options = {}
|
297
|
+
options = default_options(:quiet => true).merge options
|
298
|
+
|
255
299
|
Dust.print_msg 'determining whether node uses emerge', options
|
256
300
|
Dust.print_result exec('test -e /etc/gentoo-release')[:exit_code], options
|
257
301
|
end
|
258
302
|
|
259
|
-
def is_os? os_list, options={
|
303
|
+
def is_os? os_list, options = {}
|
304
|
+
options = default_options(:quiet => true).merge options
|
305
|
+
|
260
306
|
Dust.print_msg "checking if this machine runs #{os_list.join(' or ')}", options
|
261
|
-
collect_facts options unless @
|
307
|
+
collect_facts options unless @node['operatingsystem']
|
262
308
|
|
263
309
|
os_list.each do |os|
|
264
|
-
if @
|
310
|
+
if @node['operatingsystem'].downcase == os.downcase
|
265
311
|
return Dust.print_ok '', options
|
266
312
|
end
|
267
313
|
end
|
@@ -270,46 +316,66 @@ module Dust
|
|
270
316
|
false
|
271
317
|
end
|
272
318
|
|
273
|
-
def is_debian? options={
|
319
|
+
def is_debian? options = {}
|
320
|
+
options = default_options(:quiet => true).merge options
|
321
|
+
|
274
322
|
is_os? ['debian'], options
|
275
323
|
end
|
276
324
|
|
277
|
-
def is_ubuntu? options={
|
325
|
+
def is_ubuntu? options = {}
|
326
|
+
options = default_options(:quiet => true).merge options
|
327
|
+
|
278
328
|
is_os? ['ubuntu'], options
|
279
329
|
end
|
280
330
|
|
281
|
-
def is_gentoo? options={
|
331
|
+
def is_gentoo? options = {}
|
332
|
+
options = default_options(:quiet => true).merge options
|
333
|
+
|
282
334
|
is_os? ['gentoo'], options
|
283
335
|
end
|
284
336
|
|
285
|
-
def is_centos? options={
|
337
|
+
def is_centos? options = {}
|
338
|
+
options = default_options(:quiet => true).merge options
|
339
|
+
|
286
340
|
is_os? ['centos'], options
|
287
341
|
end
|
288
342
|
|
289
|
-
def is_scientific? options={
|
343
|
+
def is_scientific? options = {}
|
344
|
+
options = default_options(:quiet => true).merge options
|
345
|
+
|
290
346
|
is_os? ['scientific'], options
|
291
347
|
end
|
292
348
|
|
293
|
-
def is_fedora? options={
|
349
|
+
def is_fedora? options = {}
|
350
|
+
options = default_options(:quiet => true).merge options
|
351
|
+
|
294
352
|
is_os? ['fedora'], options
|
295
353
|
end
|
296
354
|
|
297
|
-
def is_executable? file, options={
|
355
|
+
def is_executable? file, options = {}
|
356
|
+
options = default_options.merge options
|
357
|
+
|
298
358
|
Dust.print_msg "checking if file #{file} exists and is executeable", options
|
299
359
|
Dust.print_result exec("test -x $(which #{file})")[:exit_code], options
|
300
360
|
end
|
301
361
|
|
302
|
-
def file_exists? file, options={
|
362
|
+
def file_exists? file, options = {}
|
363
|
+
options = default_options.merge options
|
364
|
+
|
303
365
|
Dust.print_msg "checking if file #{file} exists", options
|
304
366
|
Dust.print_result exec("test -e #{file}")[:exit_code], options
|
305
367
|
end
|
306
368
|
|
307
|
-
def dir_exists? dir, options={
|
369
|
+
def dir_exists? dir, options = {}
|
370
|
+
options = default_options.merge options
|
371
|
+
|
308
372
|
Dust.print_msg "checking if directory #{dir} exists", options
|
309
373
|
Dust.print_result exec("test -d #{dir}")[:exit_code], options
|
310
374
|
end
|
311
375
|
|
312
|
-
def autostart_service service, options={
|
376
|
+
def autostart_service service, options = {}
|
377
|
+
options = default_options.merge options
|
378
|
+
|
313
379
|
Dust.print_msg "autostart #{service} on boot", options
|
314
380
|
if uses_rpm?
|
315
381
|
Dust.print_result exec("chkconfig #{service} on")[:exit_code], options
|
@@ -320,27 +386,37 @@ module Dust
|
|
320
386
|
end
|
321
387
|
end
|
322
388
|
|
323
|
-
def restart_service service, options={
|
389
|
+
def restart_service service, options = {}
|
390
|
+
options = default_options.merge options
|
391
|
+
|
324
392
|
Dust.print_msg "restarting #{service}", options
|
325
393
|
Dust.print_result exec("/etc/init.d/#{service} restart")[:exit_code], options
|
326
394
|
end
|
327
395
|
|
328
|
-
def reload_service service, options={
|
396
|
+
def reload_service service, options = {}
|
397
|
+
options = default_options.merge options
|
398
|
+
|
329
399
|
Dust.print_msg "reloading #{service}", options
|
330
400
|
Dust.print_result exec("/etc/init.d/#{service} reload")[:exit_code], options
|
331
401
|
end
|
332
402
|
|
333
403
|
# check whether a user exists on this node
|
334
|
-
def user_exists? user, options={
|
404
|
+
def user_exists? user, options = {}
|
405
|
+
options = default_options.merge options
|
406
|
+
|
335
407
|
Dust.print_msg "checking if user #{user} exists", options
|
336
408
|
Dust.print_result exec("id #{user}")[:exit_code], options
|
337
409
|
end
|
338
410
|
|
339
411
|
# create a user
|
340
|
-
def create_user user, options={
|
412
|
+
def create_user user, options = {}
|
413
|
+
options = default_options.merge options
|
414
|
+
options[:home] ||= nil
|
415
|
+
options[:shell] ||= nil
|
416
|
+
|
341
417
|
return true if user_exists? user, options
|
342
418
|
|
343
|
-
Dust.print_msg "creating user #{user}",
|
419
|
+
Dust.print_msg "creating user #{user}", :indent => options[:indent]
|
344
420
|
cmd = "useradd #{user} -m"
|
345
421
|
cmd += " -d #{options[:home]}" if options[:home]
|
346
422
|
cmd += " -s #{options[:shell]}" if options[:shell]
|
@@ -348,7 +424,9 @@ module Dust
|
|
348
424
|
end
|
349
425
|
|
350
426
|
# collect additional system facts using puppets facter
|
351
|
-
def collect_facts options={
|
427
|
+
def collect_facts options = {}
|
428
|
+
options = default_options.merge options
|
429
|
+
|
352
430
|
|
353
431
|
# check if lsb-release (on apt systems) and facter are installed
|
354
432
|
# and install them if not
|
@@ -362,23 +440,41 @@ module Dust
|
|
362
440
|
|
363
441
|
Dust.print_msg "collecting additional system facts (using facter)", options
|
364
442
|
|
365
|
-
# run facter with -y for yaml output, and merge results into @
|
443
|
+
# run facter with -y for yaml output, and merge results into @node
|
366
444
|
ret = exec 'facter -y'
|
367
|
-
@
|
445
|
+
@node.merge! YAML.load ret[:stdout]
|
368
446
|
|
369
447
|
Dust.print_result ret[:exit_code], options
|
370
448
|
end
|
371
449
|
|
450
|
+
# if file is a regular file, copy it using scp
|
451
|
+
# if it's an file.erb exists, render template and push to server
|
452
|
+
def deploy_file file, destination, options = {}
|
453
|
+
options = default_options(:binding => binding).merge options
|
454
|
+
|
455
|
+
if File.exists? file
|
456
|
+
scp file, destination, options
|
457
|
+
|
458
|
+
elsif File.exists? "#{file}.erb"
|
459
|
+
template = ERB.new( File.read("#{file}.erb"), nil, '%<>')
|
460
|
+
write destination, template.result(options[:binding]), options
|
461
|
+
|
462
|
+
else
|
463
|
+
::Dust.print_failed "'#{file}' was not found."
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
|
372
468
|
private
|
373
469
|
|
374
470
|
def method_missing method, *args, &block
|
375
|
-
# make server
|
376
|
-
if @
|
377
|
-
@
|
471
|
+
# make server nodeibutes accessible via server.nodeibute
|
472
|
+
if @node[method.to_s]
|
473
|
+
@node[method.to_s]
|
378
474
|
|
379
|
-
# and as server['
|
380
|
-
elsif @
|
381
|
-
@
|
475
|
+
# and as server['nodeibute']
|
476
|
+
elsif @node[args.first]
|
477
|
+
@node[args.first]
|
382
478
|
|
383
479
|
# default to super
|
384
480
|
else
|
data/lib/dust/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 4
|
8
|
-
-
|
9
|
-
version: 0.4.
|
8
|
+
- 2
|
9
|
+
version: 0.4.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- kris kechagia
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-01-
|
17
|
+
date: 2012-01-17 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -96,7 +96,6 @@ files:
|
|
96
96
|
- changelog.md
|
97
97
|
- dust.gemspec
|
98
98
|
- lib/dust.rb
|
99
|
-
- lib/dust/convert_size.rb
|
100
99
|
- lib/dust/examples/nodes/_debian.yaml
|
101
100
|
- lib/dust/examples/nodes/_default.yaml
|
102
101
|
- lib/dust/examples/nodes/_newrelic.yaml
|
@@ -111,6 +110,7 @@ files:
|
|
111
110
|
- lib/dust/examples/templates/basic_setup/.your-vimrc
|
112
111
|
- lib/dust/examples/templates/duplicity/cronjob.erb
|
113
112
|
- lib/dust/examples/templates/etc_hosts/hosts
|
113
|
+
- lib/dust/examples/templates/hash_check/weak_passwords
|
114
114
|
- lib/dust/examples/templates/motd/motd.erb
|
115
115
|
- lib/dust/examples/templates/nginx/nginx.conf
|
116
116
|
- lib/dust/examples/templates/nginx/sites/othersite.erb
|
@@ -130,6 +130,7 @@ files:
|
|
130
130
|
- lib/dust/recipes/debsecan.rb
|
131
131
|
- lib/dust/recipes/duplicity.rb
|
132
132
|
- lib/dust/recipes/etc_hosts.rb
|
133
|
+
- lib/dust/recipes/hash_check.rb
|
133
134
|
- lib/dust/recipes/iptables.rb
|
134
135
|
- lib/dust/recipes/locale.rb
|
135
136
|
- lib/dust/recipes/memory_limit.rb
|
data/lib/dust/convert_size.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Dust
|
2
|
-
|
3
|
-
# converts string to kilobytes (rounded)
|
4
|
-
def self.convert_size s
|
5
|
-
i, unit = s.split(' ')
|
6
|
-
|
7
|
-
case unit.downcase
|
8
|
-
when 'kb'
|
9
|
-
return i.to_i
|
10
|
-
when 'mb'
|
11
|
-
return (i.to_f * 1024).to_i
|
12
|
-
when 'gb'
|
13
|
-
return (i.to_f * 1024 * 1024).to_i
|
14
|
-
when 'tb'
|
15
|
-
return (i.to_f * 1024 * 1024 * 1024).to_i
|
16
|
-
else
|
17
|
-
return false
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|