CloudyScripts 1.6.1 → 1.7.27

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.
Files changed (176) hide show
  1. data/Rakefile +1 -1
  2. data/lib/audit/checks/APACHE2.group +6 -0
  3. data/lib/audit/checks/APACHE2_CONFIG_01.check +36 -0
  4. data/lib/audit/checks/APACHE2_CONFIG_02.check +34 -0
  5. data/lib/audit/checks/APACHE2_CONFIG_03.check +60 -0
  6. data/lib/audit/checks/APACHE2_CONFIG_04.check +23 -0
  7. data/lib/audit/checks/APACHE2_CONFIG_05.check +23 -0
  8. data/lib/audit/checks/APACHE2_CONFIG_06.check +30 -0
  9. data/lib/audit/checks/APACHE2_INIT_1.check +14 -0
  10. data/lib/audit/checks/APACHE2_INIT_2.check +66 -0
  11. data/lib/audit/checks/APACHE2_INIT_3.check +13 -0
  12. data/lib/audit/checks/APACHE2_USER_7.check +17 -0
  13. data/lib/audit/checks/BACKUP_HOME_DOTFILES.check +26 -0
  14. data/lib/audit/checks/BACKUP_LOG.check +24 -0
  15. data/lib/audit/checks/BACKUP_MAIL.check +19 -0
  16. data/lib/audit/checks/BACKUP_WEB.check +12 -0
  17. data/lib/audit/checks/CONFIGURATION_BACKUP.check +14 -0
  18. data/lib/audit/checks/DIRECTORY_LISTING.check +14 -0
  19. data/lib/audit/checks/DISTRIBUTION_FACTS.check +60 -0
  20. data/lib/audit/checks/DMESG_OUTPUT.check +14 -0
  21. data/lib/audit/checks/FIND_GROUP_FILE.check +6 -0
  22. data/lib/audit/checks/FIND_PASSWD_FILE.check +8 -0
  23. data/lib/audit/checks/FIND_SHADOW_FILE.check +5 -0
  24. data/lib/audit/checks/FIND_SUDOERS_FILE.check +6 -0
  25. data/lib/audit/checks/FREE_SPACE.check +26 -0
  26. data/lib/audit/checks/HAS_AWK.check +30 -0
  27. data/lib/audit/checks/HAS_BASE.check +21 -0
  28. data/lib/audit/checks/HAS_CAT.check +18 -0
  29. data/lib/audit/checks/HAS_COMPRESSOR.check +30 -0
  30. data/lib/audit/checks/HAS_CUT.check +18 -0
  31. data/lib/audit/checks/HAS_DF.check +19 -0
  32. data/lib/audit/checks/HAS_DPKG.check +18 -0
  33. data/lib/audit/checks/HAS_FILE_DOWNLOADER.check +32 -0
  34. data/lib/audit/checks/HAS_FIND.check +18 -0
  35. data/lib/audit/checks/HAS_GREP.check +19 -0
  36. data/lib/audit/checks/HAS_GROUPCHECK.check +23 -0
  37. data/lib/audit/checks/HAS_GROUPS.check +19 -0
  38. data/lib/audit/checks/HAS_HOSTNAME.check +7 -0
  39. data/lib/audit/checks/HAS_ID.check +7 -0
  40. data/lib/audit/checks/HAS_LSB_RELEASE.check +16 -0
  41. data/lib/audit/checks/HAS_MOUNT.check +19 -0
  42. data/lib/audit/checks/HAS_NETSTAT.check +20 -0
  43. data/lib/audit/checks/HAS_PASSWD_CHECK.check +17 -0
  44. data/lib/audit/checks/HAS_PS.check +19 -0
  45. data/lib/audit/checks/HAS_ROUTE.check +19 -0
  46. data/lib/audit/checks/HAS_SH.check +19 -0
  47. data/lib/audit/checks/HAS_SORT.check +17 -0
  48. data/lib/audit/checks/HAS_STAT.check +17 -0
  49. data/lib/audit/checks/HAS_SUPERUSER.check +11 -0
  50. data/lib/audit/checks/HAS_TAIL.check +16 -0
  51. data/lib/audit/checks/HAS_TAR.check +7 -0
  52. data/lib/audit/checks/HAS_TR.check +22 -0
  53. data/lib/audit/checks/HAS_UNAME.check +7 -0
  54. data/lib/audit/checks/HAS_UNIQ.check +17 -0
  55. data/lib/audit/checks/HAS_WC.check +16 -0
  56. data/lib/audit/checks/HAS_WHO.check +18 -0
  57. data/lib/audit/checks/HAS_YUM.check +18 -0
  58. data/lib/audit/checks/LASTLOG.check +28 -0
  59. data/lib/audit/checks/LIST_ROUTES.check +33 -0
  60. data/lib/audit/checks/LIST_USER_ACCOUNTS.check +25 -0
  61. data/lib/audit/checks/LOADED_MODULES.check +22 -0
  62. data/lib/audit/checks/LOCAL_NMAP.check +97 -0
  63. data/lib/audit/checks/LOGGED_USERS.check +28 -0
  64. data/lib/audit/checks/LYNIS_AUTH.group +9 -0
  65. data/lib/audit/checks/LYNIS_AUTH_9204.check +43 -0
  66. data/lib/audit/checks/LYNIS_AUTH_9208.check +35 -0
  67. data/lib/audit/checks/LYNIS_AUTH_9216.check +24 -0
  68. data/lib/audit/checks/LYNIS_AUTH_9222.check +25 -0
  69. data/lib/audit/checks/LYNIS_AUTH_9226.check +24 -0
  70. data/lib/audit/checks/LYNIS_AUTH_9228.check +24 -0
  71. data/lib/audit/checks/LYNIS_AUTH_9252.check +19 -0
  72. data/lib/audit/checks/MAYBE_HAS_BZIP2.check +17 -0
  73. data/lib/audit/checks/MAYBE_HAS_CURL.check +17 -0
  74. data/lib/audit/checks/MAYBE_HAS_DU.check +17 -0
  75. data/lib/audit/checks/MAYBE_HAS_HOSTNAME.check +17 -0
  76. data/lib/audit/checks/MAYBE_HAS_ID.check +17 -0
  77. data/lib/audit/checks/MAYBE_HAS_LSB_RELEASE.check +15 -0
  78. data/lib/audit/checks/MAYBE_HAS_SUPERUSER.check +36 -0
  79. data/lib/audit/checks/MAYBE_HAS_TAR.check +19 -0
  80. data/lib/audit/checks/MAYBE_HAS_UNAME.check +17 -0
  81. data/lib/audit/checks/MAYBE_HAS_WGET.check +17 -0
  82. data/lib/audit/checks/MOUNTED_DEVICES.check +22 -0
  83. data/lib/audit/checks/MYSQL_HISTORY_1.check +29 -0
  84. data/lib/audit/checks/MYSQL_INIT_1.check +9 -0
  85. data/lib/audit/checks/MYSQL_INIT_2.check +12 -0
  86. data/lib/audit/checks/MYSQL_INIT_3.check +7 -0
  87. data/lib/audit/checks/PACKAGES_INSTALLED_DPKG.check +38 -0
  88. data/lib/audit/checks/PACKAGES_INSTALLED_YUM.check +36 -0
  89. data/lib/audit/checks/PASSWORD_INFORMATION.check +33 -0
  90. data/lib/audit/checks/PLATFORM_FACTS.check +35 -0
  91. data/lib/audit/checks/PORTS_OPEN_NETSTAT.check +121 -0
  92. data/lib/audit/checks/PROCESS_LIST.check +87 -0
  93. data/lib/audit/checks/SLOW.group +7 -0
  94. data/lib/audit/checks/SLOW_1.check +4 -0
  95. data/lib/audit/checks/SLOW_2.check +4 -0
  96. data/lib/audit/checks/SLOW_3.check +4 -0
  97. data/lib/audit/checks/SSH.group +14 -0
  98. data/lib/audit/checks/SSH_CONFIG_01.check +12 -0
  99. data/lib/audit/checks/SSH_CONFIG_02.check +15 -0
  100. data/lib/audit/checks/SSH_CONFIG_03.check +13 -0
  101. data/lib/audit/checks/SSH_CONFIG_04.check +11 -0
  102. data/lib/audit/checks/SSH_CONFIG_05.check +12 -0
  103. data/lib/audit/checks/SSH_CONFIG_06.check +12 -0
  104. data/lib/audit/checks/SSH_CONFIG_07.check +11 -0
  105. data/lib/audit/checks/SSH_CONFIG_08.check +12 -0
  106. data/lib/audit/checks/SSH_CONFIG_09.check +12 -0
  107. data/lib/audit/checks/SSH_CONFIG_10.check +15 -0
  108. data/lib/audit/checks/SSH_CONFIG_11.check +14 -0
  109. data/lib/audit/checks/SSH_INIT_1.check +9 -0
  110. data/lib/audit/checks/SSH_INIT_2.check +12 -0
  111. data/lib/audit/checks/SSH_KEYS_1.check +32 -0
  112. data/lib/audit/checks/USERS_INIT_1.check +9 -0
  113. data/lib/audit/checks/USERS_INIT_2.check +5 -0
  114. data/lib/audit/checks/USERS_INIT_3.check +5 -0
  115. data/lib/audit/checks/USERS_INIT_4.check +9 -0
  116. data/lib/audit/checks/USERS_INIT_5.check +10 -0
  117. data/lib/audit/checks/USER_INFORMATION.check +29 -0
  118. data/lib/audit/checks/VARIOUS.group +19 -0
  119. data/lib/audit/checks/VAR_LIST_HOME_DIRECTORIES.check +5 -0
  120. data/lib/audit/checks/benchmark.group +6 -0
  121. data/lib/audit/checks/footer.template +12 -0
  122. data/lib/audit/checks/header.template +10 -0
  123. data/lib/audit/checks/helpers/head.sh +59 -0
  124. data/lib/audit/checks/script_header.template +69 -0
  125. data/lib/audit/create_benchmark.sh +93 -0
  126. data/lib/audit/lib/audit.rb +136 -0
  127. data/lib/audit/lib/audit_facade.rb +5 -0
  128. data/lib/audit/lib/benchmark/audit_benchmark.rb +165 -0
  129. data/lib/audit/lib/benchmark/automatic_dependencies.rb +13 -0
  130. data/lib/audit/lib/benchmark/benchmark_factory.rb +23 -0
  131. data/lib/audit/lib/benchmark/benchmark_result.rb +25 -0
  132. data/lib/audit/lib/benchmark/check.rb +34 -0
  133. data/lib/audit/lib/benchmark/group.rb +30 -0
  134. data/lib/audit/lib/benchmark/item_exception.rb +13 -0
  135. data/lib/audit/lib/benchmark/result_code.rb +11 -0
  136. data/lib/audit/lib/benchmark/rule_result.rb +42 -0
  137. data/lib/audit/lib/benchmark/rule_role.rb +5 -0
  138. data/lib/audit/lib/benchmark/rule_severity.rb +13 -0
  139. data/lib/audit/lib/benchmark/yaml_benchmark.rb +133 -0
  140. data/lib/audit/lib/connection/ami_connection.rb +4 -0
  141. data/lib/audit/lib/connection/connection_factory.rb +27 -0
  142. data/lib/audit/lib/connection/ssh_connection.rb +243 -0
  143. data/lib/audit/lib/ec2_utils.rb +245 -0
  144. data/lib/audit/lib/http_fingerprint.rb +116 -0
  145. data/lib/audit/lib/lazy.rb +37 -0
  146. data/lib/audit/lib/linear_script_generator.rb +31 -0
  147. data/lib/audit/lib/main.rb +13 -0
  148. data/lib/audit/lib/my_option_parser.rb +106 -0
  149. data/lib/audit/lib/nessus_new.rb +290 -0
  150. data/lib/audit/lib/nessus_utils.rb +102 -0
  151. data/lib/audit/lib/parser/command/abstract_command.rb +32 -0
  152. data/lib/audit/lib/parser/command/abstract_command_result.rb +30 -0
  153. data/lib/audit/lib/parser/command/attach_file_command.rb +63 -0
  154. data/lib/audit/lib/parser/command/check_finished_command.rb +45 -0
  155. data/lib/audit/lib/parser/command/cpe_name_command.rb +37 -0
  156. data/lib/audit/lib/parser/command/data_command.rb +43 -0
  157. data/lib/audit/lib/parser/command/listening_port_command.rb +46 -0
  158. data/lib/audit/lib/parser/command/message_command.rb +21 -0
  159. data/lib/audit/lib/parser/command/program_name_command.rb +42 -0
  160. data/lib/audit/lib/parser/parse_exception.rb +2 -0
  161. data/lib/audit/lib/parser/result_type.rb +13 -0
  162. data/lib/audit/lib/parser/script_output_parser.rb +201 -0
  163. data/lib/audit/lib/parser/stdout_line_buffer.rb +43 -0
  164. data/lib/audit/lib/ssh_fingerprint.rb +220 -0
  165. data/lib/audit/lib/ssh_fingerprint2.rb +170 -0
  166. data/lib/audit/lib/ssh_utils.rb +292 -0
  167. data/lib/audit/lib/transformers/web_view_transformer.rb +171 -0
  168. data/lib/audit/lib/transformers/yaml_transformer.rb +50 -0
  169. data/lib/audit/lib/util/random_string.rb +22 -0
  170. data/lib/audit/lib/version.rb +7 -0
  171. data/lib/help/ec2_helper.rb +65 -2
  172. data/lib/help/remote_command_handler.rb +17 -0
  173. data/lib/help/state_transition_helper.rb +8 -0
  174. data/lib/scripts/ec2/open_port_checker.rb +112 -0
  175. data/lib/scripts/ec2/port_range_detector.rb +0 -1
  176. metadata +175 -16
@@ -0,0 +1,13 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ class AutomaticDependencies < Group
5
+ def initialize(childs)
6
+ super("AUTOMATIC_DEPENDENCIES", "automatic dependencies", "checks which are not contained in the benchmark, but neccessary to execute checks in the benchmark")
7
+ @children = childs
8
+ end
9
+
10
+ def in_report?()
11
+ false
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ require 'benchmark/yaml_benchmark'
2
+
3
+ class BenchmarkFactory
4
+ def initialize(options)
5
+ if options[:logger] then
6
+ @logger = options[:logger]
7
+ else
8
+ @logger = Logger.new(STDOUT)
9
+ end
10
+ end
11
+
12
+ def load(options)
13
+ raise "Need option :benchmark" unless options[:benchmark]
14
+
15
+ if options[:benchmark] =~ /\.xml$/ then
16
+ return XccdfBenchmark.new({:benchmark => options[:benchmark], :logger => @logger})
17
+ elsif options[:benchmark] =~ /\.zip$/ then
18
+ return YamlBenchmark.new({:benchmark => options[:benchmark], :logger => @logger})
19
+ else
20
+ raise "Unknown benchmark type"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ # To change this template, choose Tools | Templates
2
+ # and open the template in the editor.
3
+
4
+ class BenchmarkResult
5
+ attr_reader :audit
6
+
7
+ def initialize(audit)
8
+ @audit = audit
9
+ @document = {}
10
+ end
11
+
12
+ def add(rule_result)
13
+ @document[rule_result.rule.id] = rule_result
14
+ end
15
+
16
+ def get(id)
17
+ return @benchmark if id == :root || id == 'BENCHMARK'
18
+
19
+ return @document[id] || @benchmark.get_item(id)
20
+ end
21
+
22
+ def get_root()
23
+ return get(:root)
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ require 'lazy'
2
+
3
+ class Check
4
+ attr_reader :id # The ID by which this check is referenced from other elements
5
+ attr_reader :name # A human-readable name for this check
6
+ attr_reader :description # A short description of the goals of this check
7
+ attr_reader :script # The actual sh script that will be executed to gather values
8
+ attr_reader :dependencies # An array if ID string, which contain references to required Check (not Group!)
9
+ # objects that must be executed before this check
10
+ attr_reader :duration # duration of this check in seconds; per default, one second is assumed
11
+
12
+ def initialize(id, script, name = nil, dependencies = [], description = nil, duration = 1)
13
+ @id = id
14
+ @name = name
15
+ @dependencies = dependencies || []
16
+ @description = description
17
+ @script = script
18
+ @duration = (duration or 1)
19
+ end
20
+
21
+ def to_hash()
22
+ return {
23
+ :type => :CHECK,
24
+ :id => @id,
25
+ :name => @name,
26
+ :dependencies => Lazy.new(@dependencies, :map) {|check| check.id},
27
+ :description => @description
28
+ }
29
+ end
30
+
31
+ def in_report?()
32
+ return true
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ require 'lazy'
2
+
3
+
4
+ class Group
5
+ attr_reader :id # The unique ID by which this group is referenced from other elements
6
+ attr_reader :name # A human-readable name for this group
7
+ attr_reader :description # A descriptive string for this group
8
+ attr_accessor :children # Allowed children are Check and Group objects
9
+
10
+ def initialize(id, name = nil, description = nil)
11
+ @id = id
12
+ @name = name
13
+ @description = description
14
+ @children = []
15
+ end
16
+
17
+ def to_hash()
18
+ return {
19
+ :type => :GROUP,
20
+ :id => @id,
21
+ :name => @name,
22
+ :description => @description,
23
+ :children => Lazy.new(Lazy.new(@children, :reject) {|x| !x.in_report?}, :map) {|child| Lazy.new(child, :to_hash)}
24
+ }
25
+ end
26
+
27
+ def in_report?()
28
+ true
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ class ItemException < Exception
2
+ end
3
+
4
+ class ItemNotFoundException < ItemException
5
+ attr_reader :missing_item
6
+
7
+ def initialize(missing_item)
8
+ @missing_item = missing_item
9
+ end
10
+ end
11
+
12
+ class BadItemClassException < ItemException
13
+ end
@@ -0,0 +1,11 @@
1
+ class ResultCode
2
+ PASS = "pass"
3
+ FAIL = "fail"
4
+ ERROR = "error"
5
+ UNKNOWN = "unknown"
6
+ NOTAPPLICABLE = "notapplicable"
7
+ NOTCHECKED = "notchecked"
8
+ NOTSELECTED = "notselected"
9
+ INFORMATIONAL = "informational"
10
+ FIXED = "fixed"
11
+ end
@@ -0,0 +1,42 @@
1
+ require 'benchmark/result_code'
2
+ require 'lazy'
3
+
4
+ class RuleResult
5
+ attr_reader :rule
6
+ attr_reader :check
7
+ attr_reader :rule_idref
8
+ attr_reader :result
9
+ attr_reader :version
10
+ attr_reader :timestamp
11
+ attr_reader :severity
12
+
13
+ def initialize(rule, results)
14
+ @timestamp = Time.now.utc
15
+ # @severity = rule.severity
16
+ # @version = rule.version
17
+
18
+ return_codes = results.reject {|x| x.type != ResultType::CHECK_FINISHED}
19
+ raise "Each rule should have exacty one return code" if return_codes.length != 1
20
+ return_code = return_codes[0]
21
+
22
+ if return_code.exit_code.downcase == "pass" then
23
+ @result = ResultCode::PASS
24
+ else
25
+ @result = ResultCode::FAIL
26
+ end
27
+
28
+ @rule_idref = rule.id
29
+ @rule = rule
30
+ @check = results
31
+ end
32
+
33
+ def to_hash()
34
+ return {
35
+ :type => :RULE_RESULT,
36
+ :timestamp => @timestamp,
37
+ :rule => @rule_idref,
38
+ :checks => Lazy.new(@check, :map) {|result| Lazy.new(result, :to_hash)},
39
+ :result => @result
40
+ }
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ class RuleRole
2
+ FULL = "full"
3
+ UNSCORED = "unscored"
4
+ UNCHECKED = "unchecked"
5
+ end
@@ -0,0 +1,13 @@
1
+ class RuleSeverity
2
+ UNKNOWN = "unknown"
3
+ INFO = "info"
4
+ LOW = "low"
5
+ MEDIUM = "medium"
6
+ HIGH = "high"
7
+
8
+ SEVERITIES = [UNKNOWN, INFO, LOW, MEDIUM, HIGH]
9
+
10
+ def self.parse(str)
11
+ return ((SEVERITIES.include? str.downcase) ? str.downcase : UNKNOWN)
12
+ end
13
+ end
@@ -0,0 +1,133 @@
1
+ require 'yaml'
2
+ require 'logger'
3
+ require 'zip/zip'
4
+
5
+ require 'benchmark/group'
6
+ require 'benchmark/item_exception'
7
+ require 'benchmark/check'
8
+ require 'benchmark/audit_benchmark'
9
+ require 'benchmark/automatic_dependencies'
10
+
11
+
12
+
13
+ class YamlBenchmark < AuditBenchmark
14
+ CHECK_FILE_EXTENSION=".check"
15
+ GROUP_FILE_EXTENSION=".group"
16
+ GROUP_ID="ID"
17
+ GROUP_NAME="Name"
18
+ GROUP_DESCRIPTION="Description"
19
+ GROUP_CHILDREN="Children"
20
+ CHECK_ID="ID"
21
+ CHECK_SCRIPT="Script"
22
+ CHECK_NAME="Name"
23
+ CHECK_DEPENDENCIES="Depends"
24
+ CHECK_DESCRIPTION="Description"
25
+ CHECK_DURATION="Duration"
26
+ BENCHMARK_ID="BENCHMARK"
27
+
28
+ attr_reader :id
29
+ attr_reader :name
30
+ attr_reader :description
31
+ attr_reader :children
32
+
33
+ def initialize(options)
34
+ raise "Need option :benchmark" unless options[:benchmark]
35
+
36
+ if options[:logger]
37
+ @logger = options[:logger]
38
+ else
39
+ @logger = Logger.new(STDOUT)
40
+ end
41
+
42
+ if !File.exist?(options[:benchmark]) then
43
+ @logger.error("Specified benchmark file '#{options[:benchmark]}' does not exist")
44
+ raise "Specified benchmark file '#{options[:benchmark]}' does not exist"
45
+ end
46
+
47
+ @logger.info("Loading benchmark '#{options[:benchmark]}'")
48
+
49
+ @item_repository = {}
50
+ @benchmark_file = options[:benchmark]
51
+ group_hashes = []
52
+ check_hashes = []
53
+ Zip::ZipFile.open(@benchmark_file, Zip::ZipFile::CREATE) do|zipfile|
54
+ zipfile.each do|file|
55
+ if file.name =~ /\.group$/ then
56
+ @logger.debug {"Loading group '#{file.name}'"}
57
+
58
+ hash = YAML::load( file.get_input_stream )
59
+ raise "The group file '#{group_file}' does not contain the group's ID" unless hash[GROUP_ID]
60
+ raise "The group file '#{group_file}' does not contain any children" unless hash[GROUP_CHILDREN]
61
+
62
+ @item_repository[hash[CHECK_ID]] = Group.new(hash[GROUP_ID],
63
+ hash[GROUP_NAME],
64
+ hash[GROUP_DESCRIPTION])
65
+ group_hashes << hash # keep group hash for later, because we still need to add children to the group
66
+ elsif file.name =~ /\.check$/ then
67
+ @logger.debug {"Loading check '#{file.name}'"}
68
+
69
+ hash = YAML::load( file.get_input_stream )
70
+ raise "The check file '#{file.name}' does not contain the check's ID" unless hash[CHECK_ID]
71
+ raise "The check file '#{file.name}' does not contain a check script" unless hash[CHECK_SCRIPT]
72
+
73
+ @item_repository[hash[CHECK_ID]] = Check.new(hash[CHECK_ID],
74
+ hash[CHECK_SCRIPT],
75
+ hash[CHECK_NAME],
76
+ [],
77
+ hash[CHECK_DESCRIPTION],
78
+ hash[CHECK_DURATION])
79
+ check_hashes << hash
80
+ else
81
+ @logger.info {"Ignoring unknown file '#{file.name}' in benchmark '#{@benchmark_file}'"}
82
+ # unknown file, ignore
83
+ end
84
+ end
85
+ end
86
+
87
+ group_hashes.each do|group_hash|
88
+ group = @item_repository[group_hash[GROUP_ID]]
89
+ group_hash[GROUP_CHILDREN]. each do|child|
90
+ raise ItemNotFoundException.new(child), "Item '#{child}' from group '#{group.id}' not found" unless @item_repository[child]
91
+ item = @item_repository[child]
92
+ raise BadItemClassErooxception, "Item '#{child}' from group '#{group.id}' has wrong item class '#{item.class.name}'" unless item.class == Check || item.class == Group
93
+
94
+ group.children << item
95
+ end
96
+ end
97
+
98
+ # set dependencies
99
+ check_hashes.each do|check_hash|
100
+ check = @item_repository[check_hash[CHECK_ID]]
101
+ if check_hash[CHECK_DEPENDENCIES] then
102
+ check_hash[CHECK_DEPENDENCIES].each do|dep|
103
+ raise ItemNotFoundException.new(dep), "Item '#{dep}' which is depended on by check '#{check.id}' not found" unless @item_repository[dep]
104
+ check.dependencies << @item_repository[dep]
105
+ end
106
+ end
107
+ end
108
+
109
+ benchmark = @item_repository[BENCHMARK_ID] or raise ItemNotFoundException.new("benchmark.group"), "Benchmark file benchmark.group not found in benchmark zipfile '#{benchmark_file}'"
110
+ raise BadItemClassException, "Benchmark has wrong item class #{benchmark.class.name}, expected is Group" unless benchmark.class == Group
111
+ @item_repository.delete(BENCHMARK_ID) #The benchmark group is not really an item, so remove it from the item set
112
+
113
+ @id = benchmark.id
114
+ @name = benchmark.name
115
+ @description = benchmark.description
116
+ @children = benchmark.children
117
+ auto_deps = AutomaticDependencies.new(automatic_dependencies())
118
+ @item_repository[auto_deps.id] = auto_deps
119
+ @children = [auto_deps] + benchmark.children
120
+
121
+ end
122
+
123
+ #get a raw benchmark element by name. This is used by other classes like script generators
124
+ #to retrieve information from the benchmark that was stored there for them.
125
+ def element_impl(name)
126
+ return Zip::ZipFile.open(@benchmark_file, Zip::ZipFile::CREATE) {|zipfile| zipfile.read(name)}
127
+ end
128
+
129
+ def get_item(id)
130
+ raise ItemNotFoundException.new(id), "Item #{id} not found" if @item_repository[id].nil?
131
+ return @item_repository[id]
132
+ end
133
+ end
@@ -0,0 +1,4 @@
1
+ require 'ssh_connection'
2
+
3
+ class AmiConnection < SshConnection
4
+ end
@@ -0,0 +1,27 @@
1
+ require 'connection/ssh_connection'
2
+
3
+
4
+ class ConnectionFactory
5
+ def initialize(options)
6
+ if options[:logger] then
7
+ @logger = options[:logger]
8
+ else
9
+ @logger = Logger.new(STDOUT)
10
+ end
11
+ end
12
+
13
+ def create(options)
14
+ raise "Need option :connection_type" unless options[:connection_type]
15
+ raise "Need option :connection_params" unless options[:connection_params]
16
+
17
+ case options[:connection_type]
18
+ when :ssh
19
+ return SshConnection.new({:connection_params => options[:connection_params], :logger => @logger})
20
+ when :ami
21
+ return AmiConnection.new({:connection_params => options[:connection_params], :logger => @logger})
22
+ else
23
+ raise "Unknown connection type"
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,243 @@
1
+ require 'net/ssh'
2
+ require 'net/scp'
3
+ require 'net/sftp'
4
+ require 'logger'
5
+
6
+ class SshConnection
7
+ @@logger = Logger.new(STDOUT)
8
+
9
+ def initialize(parameters)
10
+ raise "Need parameter :connection_params" unless parameters[:connection_params]
11
+
12
+ if parameters[:logger] then
13
+ @@logger = parameters[:logger]
14
+ end
15
+
16
+ @parameters = parameters[:connection_params]
17
+ @parameters[:user] = 'root' unless @parameters[:user]
18
+ raise "No target host specified" unless @parameters[:host]
19
+ end
20
+
21
+ # open the ssh connection to the remote host
22
+ def open(&block)
23
+ if @ssh_session && !@ssh_session.closed? then
24
+ @@logger.warn("trying to open an already opened ssh connection")
25
+ raise "trying to open an already opened ssh connection"
26
+ end
27
+
28
+ @@logger.info("opening ssh connection with parameters: " + @parameters.to_s)
29
+
30
+ parameters = @parameters.clone()
31
+ host = @parameters[:host]
32
+ user = @parameters[:user]
33
+
34
+ parameters.delete(:host)
35
+ parameters.delete(:user)
36
+
37
+ if @parameters[:keys] then
38
+ @@logger.info("Starting SSH session with public key authentication")
39
+ elsif @parameters[:key_data] then
40
+ @@logger.info("Starting SSH session with public key authentication")
41
+ elsif @parameters[:password] then
42
+ @@logger.info("Starting SSH session with password authentication")
43
+ else
44
+ @@logger.error("No SSH authentication method found in parameters")
45
+ raise "No authentication method found"
46
+ end
47
+
48
+ @ssh_session = Net::SSH.start(host, user, parameters)
49
+
50
+ if block then
51
+ yield self
52
+ close
53
+ end
54
+ end
55
+
56
+ def close
57
+ @ssh_session.close
58
+ end
59
+
60
+ def <<(command)
61
+ exec(command)
62
+ end
63
+
64
+ # remote execute a command
65
+ def exec(command, stdin = nil)
66
+ exit_status = 0 # define variable so that it will be available in the block at method scope
67
+ @ssh_session.open_channel do |ch|
68
+ @@logger.info("Executing command '#{command}'")
69
+ ch.exec(command) do|ch, success|
70
+
71
+ if success then
72
+ @@logger.debug("Command sucessfully executed")
73
+ ch.on_data() do|ch, data|
74
+ #process_stdout(data) unless data
75
+ @stdout_handler.call(data) unless @stdout_handler.nil? or data.nil?
76
+ end
77
+ ch.on_extended_data() do|ch, type, data|
78
+ @stderr_handler.call(data) unless @stderr_handler.nil? or data.nil?
79
+ end
80
+ ch.on_request "exit-status" do|ch, data|
81
+ exit_status = data.read_long unless data.nil?
82
+ end
83
+ ch.on_close do |ch|
84
+ @close_handler.call() unless @close_handler.nil?
85
+ end
86
+ ch.on_eof do |ch|
87
+ @close_handler.call() unless @close_handler.nil?
88
+ end
89
+
90
+ ch.send_data stdin if stdin
91
+ else
92
+ @@logger.debug("")
93
+ exit_status = 127
94
+ end
95
+ end
96
+ ch.wait
97
+ end
98
+
99
+ return exit_status
100
+ end
101
+
102
+ #XXX: new remote execute a command
103
+ def exec_new(command, stdin = nil)
104
+ exit_status = 0 # define variable so that it will be available in the block at method scope
105
+ channel = @ssh_session.open_channel do |ch|
106
+ ch.exec(command) do|ch, success|
107
+
108
+ if success then
109
+ @@logger.info("SshConnection: starts executing '#{command}'")
110
+ ch.on_data() do|ch, data|
111
+ #process_stdout(data) unless data
112
+ @stdout_handler.call(data) unless @stdout_handler.nil? or data.nil?
113
+ end
114
+ ch.on_extended_data() do|ch, type, data|
115
+ @stderr_handler.call(data) unless @stderr_handler.nil? or data.nil?
116
+ end
117
+ ch.on_request "exit-status" do|ch, data|
118
+ exit_status = data.read_long unless data.nil?
119
+ @@logger.info("SshConnection.on_request: process terminated with exit-status: #{exit_status}")
120
+ if exit_status != 0
121
+ @@logger.error("SshConnection.on_request: Remote command execution failed with code: #{exit_status}")
122
+ end
123
+ end
124
+ ch.on_request "exit-signal" do |ch, data|
125
+ @@logger.info("SshConnection.on_request: process terminated with exit-signal: #{data.read_string}")
126
+ end
127
+ ch.on_close do |ch|
128
+ @@logger.info("SshConnection.on_close: remote end is closing!")
129
+ #@close_handler.call() unless @close_handler.nil?
130
+ end
131
+ ch.on_eof do |ch|
132
+ @@logger.info("SshConnection.on_eof: remote end is done sending data")
133
+ #@close_handler.call() unless @close_handler.nil?
134
+ end
135
+ ch.on_open_failed do |ch, code, desc|
136
+ @@logger.info("SshConnection.on_open_failed: code=#{code} desc=#{desc}")
137
+ end
138
+ ch.on_process do |ch|
139
+ #@@logger.debug("SshConnection.on_process; send line-feed/sleep")
140
+ ch.send_data("\n")
141
+ end
142
+
143
+ #ch.send_data stdin if stdin
144
+ else
145
+ @@logger.debug("SshConnection: the remote command could not be invoked!")
146
+ exit_status = 127
147
+ end
148
+ end
149
+ #ch.wait
150
+ end
151
+ channel.wait
152
+ return exit_status
153
+ end
154
+
155
+
156
+ #copy local file to remote path
157
+ def copy_to_remote(local_file, remote_path)
158
+ @ssh_session.scp.upload! local_file, remote_path
159
+ end
160
+
161
+ #copy remote file to local path
162
+ def copy_from_remote(remote_file, local_path)
163
+ begin
164
+ @@logger.info { "Copying file from #{remote_file} to #{local_path}" }
165
+ @ssh_session.scp.download!(remote_file, local_path)
166
+ return true
167
+ rescue => err
168
+ @@logger.error { "SCP failed: #{err.message}" }
169
+ @@logger.error { "\t #{err.backtrace}" }
170
+ end
171
+ end
172
+
173
+ #write a string to a remote file
174
+ def write_to_remote_file(string, remote_path)
175
+ #filename = "/tmp/" + Random.srand().to_s() + ".sh"
176
+ filename = "/tmp/" + Kernel::srand().to_s() + ".sh"
177
+ File.open(filename, 'w') {|f| f.write(string)}
178
+ copy_to_remote(filename, remote_path)
179
+ File.delete(filename)
180
+ end
181
+
182
+ #delete remote file
183
+ def delete_remote(remote_file)
184
+ exec("rm #{remote_file}")
185
+ end
186
+
187
+ # copies remote file to local path and deletes remote file afterwards
188
+ def move_from_remote(remote_file, local_path)
189
+ copy_from_remote(remote_file, local_path)
190
+ delete_remote(remote_file)
191
+ end
192
+
193
+ # hook a handler who is called on text on stdout.
194
+ def on_stdout(&block)
195
+ @stdout_handler = block
196
+ end
197
+
198
+ # hook a handler who is called on text on stderr
199
+ def on_stderr(&block)
200
+ @stderr_handler = block
201
+ end
202
+
203
+ # hook a handler who is called on connection close
204
+ def on_close(&block)
205
+ @close_handler = block
206
+ end
207
+
208
+ #if the connection is closed
209
+ def closed?
210
+ return @ssh_session.nil? || @ssh_session.closed?
211
+ end
212
+
213
+ # return a string representation of the connection
214
+ def to_s()
215
+ return "ssh:#{@parameters[:user]}@#{@parameters[:host]}"
216
+ end
217
+
218
+ def to_hash()
219
+ return {
220
+ :type => :CONNECTION,
221
+ :subtype => :ssh,
222
+ :user => @parameters[:user],
223
+ :host => @parameters[:host]
224
+ }
225
+ end
226
+
227
+ #force the connection to close
228
+ def abort()
229
+ if @ssh_session && !@ssh_session.closed? then
230
+ #try to close connection gracefully
231
+ @ssh_session.close
232
+ # and if it won't, send out the hunter to bring in Snowwhite's heart after some time
233
+ Thread.new do
234
+ sleep 5
235
+ @ssh_session.shutdown! unless @ssh_session.nil? || @ssh_session.closed?
236
+ end
237
+ end
238
+ end
239
+
240
+ # def SshConnection.finalize(id)
241
+ #
242
+ # end
243
+ end