risu 1.4.4 → 1.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/NEWS.markdown +14 -1
  2. data/README.markdown +23 -41
  3. data/TODO.markdown +48 -39
  4. data/lib/risu.rb +4 -9
  5. data/lib/risu/base.rb +15 -0
  6. data/lib/risu/base/prawn_templater.rb +37 -0
  7. data/lib/risu/{schema.rb → base/schema.rb} +34 -15
  8. data/lib/risu/base/template_base.rb +23 -0
  9. data/lib/risu/base/template_manager.rb +106 -0
  10. data/lib/risu/base/templater.rb +37 -0
  11. data/lib/risu/cli/application.rb +28 -8
  12. data/lib/risu/models.rb +1 -2
  13. data/lib/risu/models/host.rb +147 -23
  14. data/lib/risu/models/item.rb +131 -43
  15. data/lib/risu/models/plugin.rb +1 -1
  16. data/lib/risu/models/report.rb +11 -1
  17. data/lib/risu/models/serverpreference.rb +0 -2
  18. data/lib/risu/models/servicedescription.rb +10 -0
  19. data/lib/risu/parsers.rb +2 -3
  20. data/lib/risu/parsers/nessus/nessus_document.rb +69 -0
  21. data/lib/risu/parsers/nessus/nessus_sax_listener.rb +278 -0
  22. data/lib/risu/templates/assets.rb +45 -18
  23. data/lib/risu/templates/cover_sheet.rb +70 -42
  24. data/lib/risu/templates/exec_summary.rb +64 -45
  25. data/lib/risu/templates/executive_summary.rb +185 -161
  26. data/lib/risu/templates/finding_statistics.rb +44 -17
  27. data/lib/risu/templates/findings_host.rb +70 -46
  28. data/lib/risu/templates/findings_summary.rb +78 -54
  29. data/lib/risu/templates/findings_summary_with_pluginid.rb +80 -54
  30. data/lib/risu/templates/graphs.rb +46 -19
  31. data/lib/risu/templates/host_summary.rb +62 -39
  32. data/lib/risu/templates/ms_patch_summary.rb +59 -35
  33. data/lib/risu/templates/ms_update_summary.rb +59 -35
  34. data/lib/risu/templates/pci_compliance.rb +88 -64
  35. data/lib/risu/templates/technical_findings.rb +132 -106
  36. data/lib/risu/templates/template.rb +24 -0
  37. metadata +12 -6
  38. data/lib/risu/listener.rb +0 -274
  39. data/lib/risu/nessusdocument.rb +0 -66
  40. data/lib/risu/prawn_templater.rb +0 -38
@@ -0,0 +1,106 @@
1
+ module Risu
2
+ module Base
3
+ class TemplateManager
4
+ attr_accessor :registered_templates
5
+
6
+ #
7
+ #
8
+ def initialize (path)
9
+ @registered_templates = Array.new
10
+ @templates = Array.new
11
+
12
+ load_templates(path)
13
+ end
14
+
15
+ #
16
+ #
17
+ def load_templates(path)
18
+ begin
19
+ base_dir = __FILE__.gsub("risu/base/template_manager.rb", "")
20
+ Dir["#{base_dir + path}/**/*.rb"].each do |x|
21
+ begin
22
+ load x
23
+ rescue => e
24
+ next
25
+ end
26
+ end
27
+
28
+ TemplateBase.possible_templates.each do |p|
29
+ if validate(p) == true
30
+ @registered_templates << p
31
+ end
32
+ end
33
+ rescue => e
34
+ puts "Bad plugin"
35
+ end
36
+ end
37
+
38
+ #
39
+ #
40
+ def validate(template)
41
+ t = template.new
42
+
43
+ if t == nil
44
+ return false
45
+ end
46
+
47
+ if t.respond_to?(:render) == false
48
+ return false
49
+ end
50
+
51
+ return true
52
+ end
53
+
54
+ #
55
+ #
56
+ def find_plugins(file_name)
57
+ Dir.new("#{file_name}").each do |file|
58
+ next if file.match(/^\.+/)
59
+ path = "#{file_name}/#{file}"
60
+
61
+ if FileTest.directory?("#{path}")
62
+ list("#{path}")
63
+ else
64
+ self.register_template path
65
+ end
66
+ end
67
+ end
68
+
69
+ #
70
+ #
71
+ def register_template(plugin)
72
+ load plugin
73
+
74
+ @templates.push(plugin)
75
+ end
76
+
77
+ #
78
+ #
79
+ def find_template_by_name(name)
80
+ @registered_templates.each do |template|
81
+ t = template.new
82
+ if t.template_info[:name] == name
83
+ return t
84
+ end
85
+ end
86
+
87
+ return nil
88
+ end
89
+
90
+ #
91
+ #
92
+ def display_templates
93
+ puts "Available Templates"
94
+ @registered_templates.each do |x|
95
+ p = x.new
96
+ puts "\t#{p.template_info[:name]} - #{p.template_info[:description]}\n",
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+
104
+
105
+
106
+
@@ -0,0 +1,37 @@
1
+ module Risu
2
+ module Base
3
+ # Templater class for generating a report from a erb template
4
+ #
5
+ # @author Jacob Hammack
6
+ class Templater
7
+ attr_accessor :template, :template_manager, :findings, :output_file
8
+
9
+ # Setups of the Templater class initalizing all of the variables
10
+ #
11
+ # @return [Templater] New Instance
12
+ def initialize(template, findings, output, template_manager)
13
+ @template = template
14
+ @findings = findings
15
+ @output_file = output
16
+ @template_manager = template_manager
17
+ end
18
+
19
+ # Generates a report based on the erb template
20
+ #
21
+ def generate
22
+ begin
23
+ template = @template
24
+ template_manager = @template_manager
25
+
26
+ Prawn::Document.generate(@output_file, :margin => [75, 50, 75, 50]) do |output|
27
+ output.font_size 12
28
+ t = template_manager.find_template_by_name(template)
29
+ t.render(output) unless t == nil
30
+ end
31
+ rescue => e
32
+ puts "Error: #{e.message} \n #{e.backtrace.join("\n\t")}\n"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -7,6 +7,7 @@ module Risu
7
7
  #
8
8
  # @author Jacob Hammack <jacob.hammack@hammackj.com>
9
9
  class Application
10
+ include Risu::Base
10
11
  attr_accessor :database
11
12
 
12
13
  #
@@ -18,6 +19,9 @@ module Risu
18
19
  @blacklist = {}
19
20
 
20
21
  @options[:debug] = false
22
+ @options[:list_templates] = false
23
+
24
+ @template_manager = Risu::Base::TemplateManager.new "risu/templates"
21
25
  end
22
26
 
23
27
  # Creates a blank config file
@@ -88,7 +92,7 @@ module Risu
88
92
  end
89
93
 
90
94
  ActiveRecord::Base.establish_connection(@database)
91
- require 'risu/schema'
95
+ require 'risu/base/schema'
92
96
  Schema.migrate(direction)
93
97
 
94
98
  if direction == :up
@@ -193,13 +197,23 @@ module Risu
193
197
  opt.separator('')
194
198
  opt.separator("Reporting Options")
195
199
 
196
- opt.on('-t','--template FILE','The filename of the template to use') do |option|
200
+ opt.on('-t', '--template FILE', 'The filename of the template to use') do |option|
197
201
  @options[:template] = option
198
202
  end
199
203
 
200
- opt.on('-o','--output-file FILE','The filename to output the generated report to') do |option|
204
+ opt.on('-o', '--output-file FILE', 'The filename to output the generated report to') do |option|
201
205
  @options[:output_file] = option
202
206
  end
207
+
208
+ opt.on('-l', '--list-templates', "Lists all of the templates available to #{APP_NAME}") do |option|
209
+ @options[:list_templates] = option
210
+ end
211
+
212
+ opt.on('--create-template NAME', "Creates a template file in the ~/.risu/templates directory") do |option|
213
+ if File.exists?(option) == true
214
+ puts "[!] Template "
215
+ end
216
+ end
203
217
 
204
218
  opt.separator('')
205
219
  opt.separator('Configuration Options')
@@ -287,6 +301,12 @@ module Risu
287
301
  #
288
302
  def run
289
303
  parse_options
304
+
305
+ if @options[:list_templates]
306
+ @template_manager.display_templates
307
+
308
+ exit
309
+ end
290
310
 
291
311
  if @options[:debug] == true
292
312
  puts "[*] Enabling Debug Mode"
@@ -326,8 +346,8 @@ module Risu
326
346
  end
327
347
 
328
348
  if @options[:template] != nil and @options[:output_file] != nil
329
- if File.exists?(@options[:template]) == false
330
- puts "[!] Template \"#{@options[:template]}\" does not exist. Please check the filename"
349
+ if @template_manager.find_template_by_name(@options[:template]) == nil
350
+ puts "[!] Template \"#{@options[:template]}\" does not exist. Please check the name"
331
351
  exit
332
352
  end
333
353
 
@@ -337,8 +357,8 @@ module Risu
337
357
  @findings.title = @report["title"]
338
358
  @findings.company = @report["company"]
339
359
  @findings.classification = @report["classification"]
340
-
341
- template = PrawnTemplater.new(@options[:template], @findings, @options[:output_file])
360
+
361
+ template = Templater.new(@options[:template], @findings, @options[:output_file], @template_manager)
342
362
  template.generate
343
363
  end
344
364
 
@@ -371,7 +391,7 @@ module Risu
371
391
  raise Risu::Exceptions::InvalidDocument, "[!] Document does not exist - #{file}"
372
392
  end
373
393
 
374
- doc = NessusDocument.new file
394
+ doc = Risu::Parsers::Nessus::NessusDocument.new file
375
395
  if doc.valid? == true
376
396
  doc.parse
377
397
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  module Risu
4
2
  module Models
5
3
  end
@@ -16,3 +14,4 @@ require 'risu/models/report'
16
14
  require 'risu/models/reference'
17
15
  require 'risu/models/policy'
18
16
  require 'risu/models/version'
17
+ require 'risu/models/servicedescription'
@@ -45,7 +45,7 @@ module Risu
45
45
  def os_windows
46
46
  where("os LIKE '%Windows%'")#.group(:os)
47
47
  end
48
-
48
+
49
49
  # Negation query for all hosts with a Windows based Operating system
50
50
  #
51
51
  # @return [ActiveRecord::Relation] with the query results
@@ -59,21 +59,21 @@ module Risu
59
59
  def os_windows_nt
60
60
  where("os LIKE '%Windows NT%'")
61
61
  end
62
-
62
+
63
63
  # Negation query for all hosts with a Windows NT based Operating system
64
64
  #
65
65
  # @return [ActiveRecord::Relation] with the query results
66
66
  def not_os_windows_nt
67
67
  where("os NOT LIKE '%Windows NT%'")
68
68
  end
69
-
69
+
70
70
  # Queries for hosts with a Windows 2000 based Operating System
71
71
  #
72
72
  # @return [ActiveRecord::Relation] with the query results
73
73
  def os_windows_2k
74
74
  where("os LIKE '%Windows 2000%'")
75
75
  end
76
-
76
+
77
77
  # Negation query for all hosts with a Windows 2000 based Operating system
78
78
  #
79
79
  # @return [ActiveRecord::Relation] with the query results
@@ -87,7 +87,7 @@ module Risu
87
87
  def os_windows_xp
88
88
  where("os LIKE '%Windows XP%'")
89
89
  end
90
-
90
+
91
91
  # Negation query for all hosts with a Windows XP based Operating system
92
92
  #
93
93
  # @return [ActiveRecord::Relation] with the query results
@@ -101,7 +101,7 @@ module Risu
101
101
  def os_windows_2k3
102
102
  where("os LIKE '%Windows Server 2003%'")
103
103
  end
104
-
104
+
105
105
  # Negation query for all hosts with a Windows Server 2003 based Operating system
106
106
  #
107
107
  # @return [ActiveRecord::Relation] with the query results
@@ -115,7 +115,7 @@ module Risu
115
115
  def os_windows_vista
116
116
  where("os LIKE '%Windows Vista%'")
117
117
  end
118
-
118
+
119
119
  # Negation query for all hosts with a Windows Vista based Operating system
120
120
  #
121
121
  # @return [ActiveRecord::Relation] with the query results
@@ -129,7 +129,7 @@ module Risu
129
129
  def os_windows_2k8
130
130
  where("os LIKE '%Windows Server 2008%'")
131
131
  end
132
-
132
+
133
133
  def not_os_windows_2k8
134
134
  where("os NOT LIKE '%Windows Server 2008%'")
135
135
  end
@@ -140,7 +140,7 @@ module Risu
140
140
  def os_windows_7
141
141
  where("os LIKE '%Windows 7%'")
142
142
  end
143
-
143
+
144
144
  # Negation query for all hosts with a Windows 7 based Operating system
145
145
  #
146
146
  # @return [ActiveRecord::Relation] with the query results
@@ -155,14 +155,14 @@ module Risu
155
155
  def os_windows_other
156
156
  not_os_windows_7.not_os_windows_2k8.not_os_windows_vista.not_os_windows_2k3.not_os_windows_xp.not_os_windows_2k.not_os_windows_nt
157
157
  end
158
-
158
+
159
159
  # Queries for all hosts with a Linux based Operating system
160
160
  #
161
161
  # @return [ActiveRecord::Relation] with the query results
162
162
  def os_linux
163
163
  where("os LIKE '%Linux%'")
164
164
  end
165
-
165
+
166
166
  # Negation query for all hosts with a Linux based Operating system
167
167
  #
168
168
  # @return [ActiveRecord::Relation] with the query results
@@ -176,7 +176,7 @@ module Risu
176
176
  def os_freebsd
177
177
  where("os LIKE '%FreeBSD%'")
178
178
  end
179
-
179
+
180
180
  # Negation query for all hosts with a FreeBSD based Operating system
181
181
  #
182
182
  # @return [ActiveRecord::Relation] with the query results
@@ -190,7 +190,7 @@ module Risu
190
190
  def os_netbsd
191
191
  where("os LIKE '%NetBsd%'")
192
192
  end
193
-
193
+
194
194
  # Negation query for all hosts with a NETbsd based Operating system
195
195
  #
196
196
  # @return [ActiveRecord::Relation] with the query results
@@ -204,7 +204,7 @@ module Risu
204
204
  def os_cisco
205
205
  where("os LIKE '%CISCO%'")
206
206
  end
207
-
207
+
208
208
  # Negation query for all hosts with a Cisco based Operating system
209
209
  #
210
210
  # @return [ActiveRecord::Relation] with the query results
@@ -218,7 +218,7 @@ module Risu
218
218
  def os_vxworks
219
219
  where("os LIKE '%VxWorks%'")
220
220
  end
221
-
221
+
222
222
  # Negation query for all hosts with a VXWorks based Operating system
223
223
  #
224
224
  # @return [ActiveRecord::Relation] with the query results
@@ -232,21 +232,21 @@ module Risu
232
232
  def os_vmware_esx
233
233
  where("os LIKE '%VMware ESX%'")
234
234
  end
235
-
235
+
236
236
  # Negation query for all hosts with a VMware ESX based Operating system
237
237
  #
238
238
  # @return [ActiveRecord::Relation] with the query results
239
239
  def not_os_vmware_esx
240
240
  where("os NOT LIKE '%VMware ESX%'")
241
241
  end
242
-
242
+
243
243
  # Queries for all hosts with a Mac OSX based Operating system
244
244
  #
245
245
  # @return [ActiveRecord::Relation] with the query results
246
246
  def os_osx
247
247
  where("os LIKE '%Mac OS X%'")
248
248
  end
249
-
249
+
250
250
  # Negation query for all hosts with a Mac OSX based Operating system
251
251
  #
252
252
  # @return [ActiveRecord::Relation] with the query results
@@ -254,11 +254,19 @@ module Risu
254
254
  where("os NOT LIKE '%Mac OS X%'")
255
255
  end
256
256
 
257
+ def os_aix
258
+ where("os LIKE '%AIX%'")
259
+ end
260
+
261
+ def not_os_aix
262
+ where("os NOT LIKE '%AIX%'")
263
+ end
264
+
257
265
  # Queries for all hosts with a Unknown Operating system
258
266
  #
259
267
  # @return [ActiveRecord::Relation] with the query results
260
268
  def os_other
261
- not_os_osx.not_os_linux.not_os_netbsd.not_os_freebsd.not_os_cisco.not_os_vxworks.not_os_vmware_esx.not_os_windows
269
+ not_os_osx.not_os_linux.not_os_netbsd.not_os_freebsd.not_os_cisco.not_os_vxworks.not_os_vmware_esx.not_os_windows.not_os_aix
262
270
  end
263
271
 
264
272
  # Generates a graph of the high and medium findings count per host
@@ -269,7 +277,7 @@ module Risu
269
277
  g.title = sprintf "Top %d High/Medium Finding Count Per Host ", Item.risks_by_host(limit).all.count
270
278
  g.sort = false
271
279
  g.theme = {
272
- :colors => %w(red green blue orange yellow purple black grey brown pink),
280
+ :colors => %w(red orange yellow blue green purple black grey brown pink),
273
281
  :background_colors => %w(white white)
274
282
  }
275
283
 
@@ -291,7 +299,7 @@ module Risu
291
299
  g.title = "Other Operating Systems Percentage"
292
300
  g.sort = false
293
301
  g.theme = {
294
- :colors => %w(red green blue orange yellow purple black grey brown pink),
302
+ :colors => %w(red orange yellow blue green purple black grey brown pink),
295
303
  :background_colors => %w(white white)
296
304
  }
297
305
 
@@ -302,6 +310,7 @@ module Risu
302
310
  cisco = Host.os_cisco.all.count
303
311
  vxworks = Host.os_vxworks.all.count
304
312
  esx = Host.os_vmware_esx.all.count
313
+ aix = Host.os_aix.all.count
305
314
  other = Host.os_other.all.count
306
315
 
307
316
  g.data("Linux", linux) unless linux == 0
@@ -311,11 +320,12 @@ module Risu
311
320
  g.data("Cisco ISO", cisco) unless cisco == 0
312
321
  g.data("VxWorks", vxworks) unless vxworks == 0
313
322
  g.data("VMware", esx) unless esx == 0
323
+ g.data("AIX", aix) unless aix == 0
314
324
  g.data("Other", other) unless other == 0
315
325
 
316
326
  #Creates very odd graphs
317
327
  #Host.os_other.each do |host|
318
- # g.data(host.os, Host.where(:os => host.os).count) unless host.os == nil
328
+ # g.data(host.os, Host.where(:os => host.os).count) unless host.os == nil
319
329
  #end
320
330
 
321
331
  StringIO.new(g.to_blob)
@@ -329,7 +339,7 @@ module Risu
329
339
  g.title = "Windows Operating Systems By Percentage"
330
340
  g.sort = false
331
341
  g.theme = {
332
- :colors => %w(red green blue orange yellow purple black grey brown pink),
342
+ :colors => %w(red orange yellow blue green purple black grey brown pink),
333
343
  :background_colors => %w(white white)
334
344
  }
335
345
 
@@ -353,6 +363,120 @@ module Risu
353
363
 
354
364
  StringIO.new(g.to_blob)
355
365
  end
366
+
367
+ #
368
+ #
369
+ def windows_os_graph_text
370
+ nt = Host.os_windows_nt.all.count
371
+ w2k = Host.os_windows_2k.all.count
372
+ xp = Host.os_windows_xp.all.count
373
+ w2k3 = Host.os_windows_2k3.all.count
374
+ vista = Host.os_windows_vista.all.count
375
+ w2k8 = Host.os_windows_2k8.all.count
376
+ w7 = Host.os_windows_7.all.count
377
+ other = (Host.os_windows.os_windows_other).all.count
378
+
379
+ windows_os_count = nt + w2k + xp + w2k3 + vista + w7 + w2k8
380
+
381
+ nt_percent = (nt.to_f / windows_os_count.to_f) * 100
382
+ w2k_percent = (w2k.to_f / windows_os_count.to_f) * 100
383
+ xp_percent = (xp.to_f / windows_os_count.to_f) * 100
384
+ w2k3_percent = (w2k3.to_f / windows_os_count.to_f) * 100
385
+ vista_percent = (vista.to_f / windows_os_count.to_f) * 100
386
+ w2k8_percent = (w2k8.to_f / windows_os_count.to_f) * 100
387
+ w7_percent = (w7.to_f / windows_os_count.to_f) * 100
388
+
389
+ text = "This graph shows the percentage of the different Microsoft Windows based operating systems " +
390
+ "found on the #{Report.title} network.\n\n"
391
+
392
+ text << "#{nt_percent.round.to_i}% of the network is Windows NT. " if nt > 0
393
+ text << "#{w2k_percent.round.to_i}% of the network is Windows 2000. " if w2k > 0
394
+ text << "#{xp_percent.round.to_i}% of the network is Windows XP. " if xp > 0
395
+ text << "#{w2k3_percent.round.to_i}% of the network is Windows Server 2003. " if w2k3 > 0
396
+ text << "#{vista_percent.round.to_i}% of the network is Windows Vista. " if vista > 0
397
+ text << "#{w2k8_percent.round.to_i}% of the network is Windows Server 2008. " if w2k8 > 0
398
+ text << "#{w7_percent.round.to_i}% of the network is Windows 7. " if w7 > 0
399
+
400
+ text << "\n\n" << unsupported_os_windows if nt > 0 or w2k > 0
401
+
402
+ return text
403
+ end
404
+
405
+ # @todo add plural check
406
+ #
407
+ def unsupported_os_text
408
+ aix_text = unsupported_os_aix
409
+ win_text = unsupported_os_windows
410
+
411
+ unsupported_os_text = "Several unsupported operating systems were also discovered on the network. " +
412
+ "These operating systems are no longer updated by the specific vendor. These operating systems should be " +
413
+ "updated and replaced as soon as possible.\n\n"
414
+
415
+ unsupported_os_text << "#{win_text}" if win_text != ""
416
+ unsupported_os_text << "#{aix_text}" if aix_text != ""
417
+
418
+ return unsupported_os_text
419
+ end
420
+
421
+ def unsupported_os_windows
422
+ win_nt_text = ""
423
+ win_2000_text = ""
424
+ win_nt = Host.os_windows_nt
425
+ win_2000 = Host.os_windows_2k
426
+
427
+ #Host.os_windows.not_os_windows_7.not_os_windows_2008.not_os_windows_vista.not_os_windows_2003.not_os_windows_xp
428
+
429
+ win_nt_text = "Windows NT is an unsupported sperating system since Microsoft has stopped support as of June 2004. " +
430
+ "Please see http://windows.microsoft.com/en-us/windows/products/lifecycle for more information.\n\n" if win_nt.count >= 1
431
+
432
+ win_2000_text = "Windows 2000 is an unsupported operating system since Microsoft has stopped support as of June 2004. " +
433
+ "Please see http://windows.microsoft.com/en-us/windows/products/lifecycle for more information.\n\n" if win_2000.count >= 1
434
+
435
+ return "#{win_nt_text}#{win_2000_text}"
436
+
437
+ end
438
+
439
+ #
440
+ #
441
+ def unsupported_os_aix
442
+ text = ""
443
+ aix = Host.os_aix.where("OS LIKE 'AIX 5.%'")
444
+
445
+ text = "AIX 5.x is an unsupported operating system since IBM has stopped support as of April 2011. " +
446
+ "Please see http://www-03.ibm.com/systems/power/software/aix/ for more information " +
447
+ "about obtaining a newer supported version.\n\n" if aix.count >= 1
448
+
449
+ return text
450
+ end
451
+
452
+ def other_os_graph_text
453
+ text = "This graph shows the percentage of the different Non-Windows based operating systems " +
454
+ "found on the #{Report.title} network.\n\n"
455
+
456
+ linux = Host.os_linux.all.count
457
+ osx = Host.os_osx.all.count
458
+ freebsd = Host.os_freebsd.all.count
459
+ netbsd = Host.os_netbsd.all.count
460
+ cisco = Host.os_cisco.all.count
461
+ vxworks = Host.os_vxworks.all.count
462
+ esx = Host.os_vmware_esx.all.count
463
+ aix = Host.os_aix.all.count
464
+ other = Host.os_other.all.count
465
+
466
+ other_os_count = linux + osx + freebsd + netbsd + cisco + vxworks + esx + aix + other
467
+
468
+ linux_percent = (linux.to_f / other_os_count.to_f) * 100
469
+ aix_percent = (aix.to_f / other_os_count.to_f) * 100
470
+
471
+ #todo add other os's here
472
+
473
+
474
+ text << "#{linux_percent.to_i}% of the network is running Linux based operating systems. " if linux > 0
475
+ text << "#{aix_percent.to_i}% of the network is running AIX based operating systems. " if aix > 0
476
+ text << "\n\n"<< unsupported_os_aix if aix > 0
477
+
478
+ return text
479
+ end
356
480
  end
357
481
  end
358
482
  end