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.
- data/Rakefile +1 -1
- data/lib/audit/checks/APACHE2.group +6 -0
- data/lib/audit/checks/APACHE2_CONFIG_01.check +36 -0
- data/lib/audit/checks/APACHE2_CONFIG_02.check +34 -0
- data/lib/audit/checks/APACHE2_CONFIG_03.check +60 -0
- data/lib/audit/checks/APACHE2_CONFIG_04.check +23 -0
- data/lib/audit/checks/APACHE2_CONFIG_05.check +23 -0
- data/lib/audit/checks/APACHE2_CONFIG_06.check +30 -0
- data/lib/audit/checks/APACHE2_INIT_1.check +14 -0
- data/lib/audit/checks/APACHE2_INIT_2.check +66 -0
- data/lib/audit/checks/APACHE2_INIT_3.check +13 -0
- data/lib/audit/checks/APACHE2_USER_7.check +17 -0
- data/lib/audit/checks/BACKUP_HOME_DOTFILES.check +26 -0
- data/lib/audit/checks/BACKUP_LOG.check +24 -0
- data/lib/audit/checks/BACKUP_MAIL.check +19 -0
- data/lib/audit/checks/BACKUP_WEB.check +12 -0
- data/lib/audit/checks/CONFIGURATION_BACKUP.check +14 -0
- data/lib/audit/checks/DIRECTORY_LISTING.check +14 -0
- data/lib/audit/checks/DISTRIBUTION_FACTS.check +60 -0
- data/lib/audit/checks/DMESG_OUTPUT.check +14 -0
- data/lib/audit/checks/FIND_GROUP_FILE.check +6 -0
- data/lib/audit/checks/FIND_PASSWD_FILE.check +8 -0
- data/lib/audit/checks/FIND_SHADOW_FILE.check +5 -0
- data/lib/audit/checks/FIND_SUDOERS_FILE.check +6 -0
- data/lib/audit/checks/FREE_SPACE.check +26 -0
- data/lib/audit/checks/HAS_AWK.check +30 -0
- data/lib/audit/checks/HAS_BASE.check +21 -0
- data/lib/audit/checks/HAS_CAT.check +18 -0
- data/lib/audit/checks/HAS_COMPRESSOR.check +30 -0
- data/lib/audit/checks/HAS_CUT.check +18 -0
- data/lib/audit/checks/HAS_DF.check +19 -0
- data/lib/audit/checks/HAS_DPKG.check +18 -0
- data/lib/audit/checks/HAS_FILE_DOWNLOADER.check +32 -0
- data/lib/audit/checks/HAS_FIND.check +18 -0
- data/lib/audit/checks/HAS_GREP.check +19 -0
- data/lib/audit/checks/HAS_GROUPCHECK.check +23 -0
- data/lib/audit/checks/HAS_GROUPS.check +19 -0
- data/lib/audit/checks/HAS_HOSTNAME.check +7 -0
- data/lib/audit/checks/HAS_ID.check +7 -0
- data/lib/audit/checks/HAS_LSB_RELEASE.check +16 -0
- data/lib/audit/checks/HAS_MOUNT.check +19 -0
- data/lib/audit/checks/HAS_NETSTAT.check +20 -0
- data/lib/audit/checks/HAS_PASSWD_CHECK.check +17 -0
- data/lib/audit/checks/HAS_PS.check +19 -0
- data/lib/audit/checks/HAS_ROUTE.check +19 -0
- data/lib/audit/checks/HAS_SH.check +19 -0
- data/lib/audit/checks/HAS_SORT.check +17 -0
- data/lib/audit/checks/HAS_STAT.check +17 -0
- data/lib/audit/checks/HAS_SUPERUSER.check +11 -0
- data/lib/audit/checks/HAS_TAIL.check +16 -0
- data/lib/audit/checks/HAS_TAR.check +7 -0
- data/lib/audit/checks/HAS_TR.check +22 -0
- data/lib/audit/checks/HAS_UNAME.check +7 -0
- data/lib/audit/checks/HAS_UNIQ.check +17 -0
- data/lib/audit/checks/HAS_WC.check +16 -0
- data/lib/audit/checks/HAS_WHO.check +18 -0
- data/lib/audit/checks/HAS_YUM.check +18 -0
- data/lib/audit/checks/LASTLOG.check +28 -0
- data/lib/audit/checks/LIST_ROUTES.check +33 -0
- data/lib/audit/checks/LIST_USER_ACCOUNTS.check +25 -0
- data/lib/audit/checks/LOADED_MODULES.check +22 -0
- data/lib/audit/checks/LOCAL_NMAP.check +97 -0
- data/lib/audit/checks/LOGGED_USERS.check +28 -0
- data/lib/audit/checks/LYNIS_AUTH.group +9 -0
- data/lib/audit/checks/LYNIS_AUTH_9204.check +43 -0
- data/lib/audit/checks/LYNIS_AUTH_9208.check +35 -0
- data/lib/audit/checks/LYNIS_AUTH_9216.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9222.check +25 -0
- data/lib/audit/checks/LYNIS_AUTH_9226.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9228.check +24 -0
- data/lib/audit/checks/LYNIS_AUTH_9252.check +19 -0
- data/lib/audit/checks/MAYBE_HAS_BZIP2.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_CURL.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_DU.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_HOSTNAME.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_ID.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_LSB_RELEASE.check +15 -0
- data/lib/audit/checks/MAYBE_HAS_SUPERUSER.check +36 -0
- data/lib/audit/checks/MAYBE_HAS_TAR.check +19 -0
- data/lib/audit/checks/MAYBE_HAS_UNAME.check +17 -0
- data/lib/audit/checks/MAYBE_HAS_WGET.check +17 -0
- data/lib/audit/checks/MOUNTED_DEVICES.check +22 -0
- data/lib/audit/checks/MYSQL_HISTORY_1.check +29 -0
- data/lib/audit/checks/MYSQL_INIT_1.check +9 -0
- data/lib/audit/checks/MYSQL_INIT_2.check +12 -0
- data/lib/audit/checks/MYSQL_INIT_3.check +7 -0
- data/lib/audit/checks/PACKAGES_INSTALLED_DPKG.check +38 -0
- data/lib/audit/checks/PACKAGES_INSTALLED_YUM.check +36 -0
- data/lib/audit/checks/PASSWORD_INFORMATION.check +33 -0
- data/lib/audit/checks/PLATFORM_FACTS.check +35 -0
- data/lib/audit/checks/PORTS_OPEN_NETSTAT.check +121 -0
- data/lib/audit/checks/PROCESS_LIST.check +87 -0
- data/lib/audit/checks/SLOW.group +7 -0
- data/lib/audit/checks/SLOW_1.check +4 -0
- data/lib/audit/checks/SLOW_2.check +4 -0
- data/lib/audit/checks/SLOW_3.check +4 -0
- data/lib/audit/checks/SSH.group +14 -0
- data/lib/audit/checks/SSH_CONFIG_01.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_02.check +15 -0
- data/lib/audit/checks/SSH_CONFIG_03.check +13 -0
- data/lib/audit/checks/SSH_CONFIG_04.check +11 -0
- data/lib/audit/checks/SSH_CONFIG_05.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_06.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_07.check +11 -0
- data/lib/audit/checks/SSH_CONFIG_08.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_09.check +12 -0
- data/lib/audit/checks/SSH_CONFIG_10.check +15 -0
- data/lib/audit/checks/SSH_CONFIG_11.check +14 -0
- data/lib/audit/checks/SSH_INIT_1.check +9 -0
- data/lib/audit/checks/SSH_INIT_2.check +12 -0
- data/lib/audit/checks/SSH_KEYS_1.check +32 -0
- data/lib/audit/checks/USERS_INIT_1.check +9 -0
- data/lib/audit/checks/USERS_INIT_2.check +5 -0
- data/lib/audit/checks/USERS_INIT_3.check +5 -0
- data/lib/audit/checks/USERS_INIT_4.check +9 -0
- data/lib/audit/checks/USERS_INIT_5.check +10 -0
- data/lib/audit/checks/USER_INFORMATION.check +29 -0
- data/lib/audit/checks/VARIOUS.group +19 -0
- data/lib/audit/checks/VAR_LIST_HOME_DIRECTORIES.check +5 -0
- data/lib/audit/checks/benchmark.group +6 -0
- data/lib/audit/checks/footer.template +12 -0
- data/lib/audit/checks/header.template +10 -0
- data/lib/audit/checks/helpers/head.sh +59 -0
- data/lib/audit/checks/script_header.template +69 -0
- data/lib/audit/create_benchmark.sh +93 -0
- data/lib/audit/lib/audit.rb +136 -0
- data/lib/audit/lib/audit_facade.rb +5 -0
- data/lib/audit/lib/benchmark/audit_benchmark.rb +165 -0
- data/lib/audit/lib/benchmark/automatic_dependencies.rb +13 -0
- data/lib/audit/lib/benchmark/benchmark_factory.rb +23 -0
- data/lib/audit/lib/benchmark/benchmark_result.rb +25 -0
- data/lib/audit/lib/benchmark/check.rb +34 -0
- data/lib/audit/lib/benchmark/group.rb +30 -0
- data/lib/audit/lib/benchmark/item_exception.rb +13 -0
- data/lib/audit/lib/benchmark/result_code.rb +11 -0
- data/lib/audit/lib/benchmark/rule_result.rb +42 -0
- data/lib/audit/lib/benchmark/rule_role.rb +5 -0
- data/lib/audit/lib/benchmark/rule_severity.rb +13 -0
- data/lib/audit/lib/benchmark/yaml_benchmark.rb +133 -0
- data/lib/audit/lib/connection/ami_connection.rb +4 -0
- data/lib/audit/lib/connection/connection_factory.rb +27 -0
- data/lib/audit/lib/connection/ssh_connection.rb +243 -0
- data/lib/audit/lib/ec2_utils.rb +245 -0
- data/lib/audit/lib/http_fingerprint.rb +116 -0
- data/lib/audit/lib/lazy.rb +37 -0
- data/lib/audit/lib/linear_script_generator.rb +31 -0
- data/lib/audit/lib/main.rb +13 -0
- data/lib/audit/lib/my_option_parser.rb +106 -0
- data/lib/audit/lib/nessus_new.rb +290 -0
- data/lib/audit/lib/nessus_utils.rb +102 -0
- data/lib/audit/lib/parser/command/abstract_command.rb +32 -0
- data/lib/audit/lib/parser/command/abstract_command_result.rb +30 -0
- data/lib/audit/lib/parser/command/attach_file_command.rb +63 -0
- data/lib/audit/lib/parser/command/check_finished_command.rb +45 -0
- data/lib/audit/lib/parser/command/cpe_name_command.rb +37 -0
- data/lib/audit/lib/parser/command/data_command.rb +43 -0
- data/lib/audit/lib/parser/command/listening_port_command.rb +46 -0
- data/lib/audit/lib/parser/command/message_command.rb +21 -0
- data/lib/audit/lib/parser/command/program_name_command.rb +42 -0
- data/lib/audit/lib/parser/parse_exception.rb +2 -0
- data/lib/audit/lib/parser/result_type.rb +13 -0
- data/lib/audit/lib/parser/script_output_parser.rb +201 -0
- data/lib/audit/lib/parser/stdout_line_buffer.rb +43 -0
- data/lib/audit/lib/ssh_fingerprint.rb +220 -0
- data/lib/audit/lib/ssh_fingerprint2.rb +170 -0
- data/lib/audit/lib/ssh_utils.rb +292 -0
- data/lib/audit/lib/transformers/web_view_transformer.rb +171 -0
- data/lib/audit/lib/transformers/yaml_transformer.rb +50 -0
- data/lib/audit/lib/util/random_string.rb +22 -0
- data/lib/audit/lib/version.rb +7 -0
- data/lib/help/ec2_helper.rb +65 -2
- data/lib/help/remote_command_handler.rb +17 -0
- data/lib/help/state_transition_helper.rb +8 -0
- data/lib/scripts/ec2/open_port_checker.rb +112 -0
- data/lib/scripts/ec2/port_range_detector.rb +0 -1
- 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,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,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,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
|