dust-deploy 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
 
@@ -1,6 +1,5 @@
1
1
  require 'dust/helper'
2
2
  require 'dust/print_status'
3
- require 'dust/convert_size'
4
3
  require 'dust/server'
5
4
  require 'dust/recipe'
6
5
 
@@ -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
@@ -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
@@ -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
- @node.scp "#{@template_path}/aliases", '/etc/aliases'
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.scp file, "/root/#{File.basename file}", :indent => 2
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
- template = ERB.new File.read("#{@template_path}/cronjob.erb"), nil, '%<>'
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
- @node.write cronjob_path, template.result(binding)
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.scp "#{@template_path}/hosts", '/etc/hosts'
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
@@ -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
- # configure node using erb template
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
@@ -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
- template = ERB.new( File.read("#{@template_path}/my.cnf.erb"), nil, '%<>')
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
- ::Dust.print_msg 'updating repositories'
8
- ::Dust.print_result @node.exec('aptitude update')[:exit_code]
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?'
@@ -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
- file = "#{@template_path}/sites/#{site}"
18
-
19
- # if this site is just a regular file, copy it to sites-available
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( @node.exec("cd /etc/nginx/sites-enabled && ln -s ../sites-available/#{site} #{site}")[:exit_code] )
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 'postgresql.conf', "#{@config['conf-dir']}/postgresql.conf"
28
- deploy_file 'pg_hba.conf', "#{@config['conf-dir']}/pg_hba.conf"
29
- deploy_file 'pg_ident.conf', "#{@config['conf-dir']}/pg_ident.conf"
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 'pacemaker.sh', "#{@config['conf-dir']}/pacemaker.sh"
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 'recovery.conf', "#{@config['data-dir']}/recovery.conf"
42
+ @node.deploy_file "#{@template_path}/recovery.conf", "#{@config['data-dir']}/recovery.conf", :binding => binding
45
43
  else
46
- deploy_file 'recovery.conf', "#{@config['data-dir']}/recovery.done"
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 'server.crt', "#{@config['data-dir']}/server.crt"
51
- deploy_file 'server.key', "#{@config['data-dir']}/server.key"
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
- # configure @node using erb template
9
- template = ERB.new File.read("#{@template_path}/zabbix_agentd.conf.erb"), nil, '%<>'
10
- ::Dust.print_msg 'adjusting and deploying zabbix_agentd.conf'
11
- @node.write '/etc/zabbix/zabbix_agentd.conf', template.result(binding), :quiet => true
12
- ::Dust.print_ok
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
- if @node.uses_emerge? :quiet => true
16
- @node.autostart_service 'zabbix-agentd'
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
 
@@ -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 initialize attr
11
- @attr = attr
12
-
13
- @attr['user'] ||= 'root'
14
- @attr['port'] ||= 22
15
- @attr['password'] ||= ''
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 @attr['hostname']
23
+ Dust.print_hostname @node['hostname']
20
24
  begin
21
25
  # connect to proxy if given
22
- if @attr['proxy']
23
- host, port = @attr['proxy'].split ':'
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 @attr['fqdn'], @attr['user'],
30
- { :password => @attr['password'],
31
- :port => @attr['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 #{@attr['fqdn']}"
35
- error_message += " (via socks5 proxy #{@attr['proxy']})" if 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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1, :env => ''}
172
- return true if package_installed? package, options
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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 @attr['operatingsystem']
307
+ collect_facts options unless @node['operatingsystem']
262
308
 
263
309
  os_list.each do |os|
264
- if @attr['operatingsystem'].downcase == os.downcase
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => true, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:quiet => false, :indent => 1}
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={:home => nil, :shell => nil, :quiet => false, :indent => 1}
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}", {:quiet => options[:quiet], :indent => options[:indent] + 1}
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={:quiet => false, :indent => 1}
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 @attr
443
+ # run facter with -y for yaml output, and merge results into @node
366
444
  ret = exec 'facter -y'
367
- @attr.merge! YAML.load ret[:stdout]
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 attributes accessible via server.attribute
376
- if @attr[method.to_s]
377
- @attr[method.to_s]
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['attribute']
380
- elsif @attr[args.first]
381
- @attr[args.first]
475
+ # and as server['nodeibute']
476
+ elsif @node[args.first]
477
+ @node[args.first]
382
478
 
383
479
  # default to super
384
480
  else
@@ -1,3 +1,3 @@
1
1
  module Dust
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 1
9
- version: 0.4.1
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-15 00:00:00 +01:00
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
@@ -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