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,5 @@
1
+ ID: VAR_LIST_HOME_DIRECTORIES
2
+ Depends: [USERS_INIT_1, HAS_CAT, HAS_TR, HAS_CUT, HAS_SED]
3
+ Description: Export colon-separated home directory list from /etc/passwd.
4
+ Type: [export]
5
+ Script: "export HOME_DIRS_LIST=$(${CAT} /etc/passwd | ${CUT} -d: -f6 | ${TR} '\n' ':' | ${SED} -e 's/:$//')"
@@ -0,0 +1,6 @@
1
+ ID: BENCHMARK
2
+ Children:
3
+ - APACHE2
4
+ - SSH
5
+ - LYNIS_AUTH
6
+ - VARIOUS
@@ -0,0 +1,12 @@
1
+ EXIT_CODE=$?
2
+ %%SCRIPT_ID%%_EXITCODE=${EXIT_CODE}
3
+ if [ ${EXIT_CODE} -eq 0 ]
4
+ then
5
+ script_return "pass"
6
+ else
7
+ script_return "fail"
8
+ fi
9
+ else
10
+ %%SCRIPT_ID%%_EXITCODE=2
11
+ script_return "notchecked"
12
+ fi
@@ -0,0 +1,10 @@
1
+
2
+
3
+ #################################
4
+ ### %%SCRIPT_ID%%
5
+ #################################
6
+
7
+ MY_SCRIPT_ID="%%SCRIPT_ID%%"
8
+ IFS=$( printf ' \t\n+' ); IFS=${IFS%+}
9
+ if [ 0 -eq 0 %%DEPENDS_CONDITION%% ]
10
+ then
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+
3
+ if [ "${1##--}" = "version" ]
4
+ then
5
+ echo "internal helper"
6
+ exit 0
7
+ fi
8
+
9
+
10
+ NB_LINES=${1##-}
11
+
12
+ #test if number of lines parameter is really numerical
13
+ NB_LINES_FILTERED=${NB_LINES##[0-9]}
14
+ NB_LINES_FILTERED=${NB_LINES_FILTERED##[0-9]}
15
+ NB_LINES_FILTERED=${NB_LINES_FILTERED##[0-9]}
16
+ if [ -z "${NB_LINES_FILTERED}" ]
17
+ then
18
+ shift
19
+ else
20
+ NB_LINES=10
21
+ fi
22
+
23
+ #if 0 lines of head, simply return
24
+ if [ "${NB_LINES}" -le 0 ]
25
+ then
26
+ return 0
27
+ fi
28
+
29
+ # test if second parameter is given
30
+ if [ -z "$1" ]
31
+ then
32
+ INPUT_FILE=/dev/stdin
33
+ else
34
+ TEMPFILE=/tmp/$$
35
+ mkfifo ${TEMPFILE}
36
+ cat "$1" > ${TEMPFILE} &
37
+ INPUT_FILE=${TEMPFILE}
38
+ fi
39
+
40
+ #read each line and count down the line counter
41
+ while read LINE < ${INPUT_FILE}
42
+ do
43
+ echo ${LINE}
44
+ NB_LINES=$((${NB_LINES}-1))
45
+ #if line counter reaches zero, it's finished
46
+ if [ "${NB_LINES}" -le 0 ]
47
+ then
48
+ if [ ! -z "${TEMPFILE}" ]
49
+ then
50
+ rm ${TEMPFILE}
51
+ fi
52
+ return 0
53
+ fi
54
+ done
55
+
56
+ if [ ! -z "${TEMPFILE}" ]
57
+ then
58
+ rm ${TEMPFILE}
59
+ fi
@@ -0,0 +1,69 @@
1
+
2
+ ###################################################
3
+ # Auditor scanning script #########################
4
+ ###################################################
5
+ # (C) 2010 SecludIT, Jonas Zaddach ################
6
+ ###################################################
7
+
8
+ script_raw_message() {
9
+ msg="%% ${MY_SCRIPT_ID}"
10
+ for val in "$@"
11
+ do
12
+ if [ ! val = "" ]
13
+ then
14
+ msg="${msg} %% ${val}"
15
+ fi
16
+ done
17
+ echo "${msg}"
18
+ }
19
+
20
+ script_message() {
21
+ script_raw_message "$1" "MESSAGE" "$2"
22
+ }
23
+
24
+ script_info_message() {
25
+ script_message "INFO" "$1"
26
+ }
27
+
28
+ script_warn_message() {
29
+ script_message "WARN" "$1"
30
+ }
31
+
32
+ script_error_message() {
33
+ script_message "ERROR" "$1"
34
+ }
35
+
36
+ script_return() {
37
+ script_raw_message "INFO" "CHECK_FINISHED" "$1"
38
+ }
39
+
40
+ script_program_name() {
41
+ script_raw_message "INFO" "PROGRAM_NAME" "$1" "$2"
42
+ }
43
+
44
+ script_not_found() {
45
+ script_raw_message "ERROR" "NOT_FOUND" "$1"
46
+ }
47
+
48
+ script_data() {
49
+ script_raw_message "INFO" "DATA" "$1" "$2"
50
+ }
51
+
52
+ script_debug() {
53
+ echo "$1" 1>&2
54
+ }
55
+
56
+ script_attach_file() {
57
+ script_raw_message "INFO" "ATTACH_FILE" "$1" "$2"
58
+ }
59
+
60
+
61
+ script_set_exit_code() {
62
+ /bin/sh -c "exit $1"
63
+ }
64
+
65
+ # create directory that can be used to store audit files
66
+ AUDIT_DIRECTORY="/tmp/audit"
67
+ rm -Rf ${AUDIT_DIRECTORY}
68
+ mkdir -p ${AUDIT_DIRECTORY}
69
+
@@ -0,0 +1,93 @@
1
+ #!/bin/bash
2
+
3
+ BENCHMARK_FILE=$1
4
+ ZIP_FILE=$2
5
+ MISC_FILES="script_header.template header.template footer.template"
6
+ REPOSIT="checks"
7
+
8
+ if [ "${BENCHMARK_FILE}" = "" ] || [ "${ZIP_FILE}" = "" ]
9
+ then
10
+ echo "USAGE: "$0" <benchmark group file> <target zip file>"
11
+ exit 1
12
+ fi
13
+
14
+ #check that identifiers are unique
15
+ DUPLICATE_IDENTIFIERS=$( cd $REPOSIT && ls -1 *.check *.group | sed -e 's/\.[^.]*$//' | sort | uniq -d )
16
+
17
+ if [ ! "${DUPLICATE_IDENTIFIERS}" = "" ]
18
+ then
19
+ for f in $( echo ${DUPLICATE_IDENTIFIERS} )
20
+ do
21
+ echo "WARNING: There exist several files with the same identifier: $f"
22
+ done
23
+ fi
24
+
25
+ #check for identifiers that do not correspond to file names
26
+ WRONG_IDENTIFIERS=""
27
+
28
+ cd $REPOSIT
29
+ for f in *.check *.group
30
+ do
31
+ FILENAME_ID=$( echo $f | sed -e 's/.[^.]*$//' )
32
+ INTERNAL_ID=$( grep "ID:" $f | sed -e 's/^ID:\s*//' )
33
+
34
+ if [ ! "${FILENAME_ID}" = "${INTERNAL_ID}" ]
35
+ then
36
+ echo "WARNING: ID in file $f is different from file name"
37
+ fi
38
+ done
39
+
40
+ #if zip file exists already, delete it
41
+ rm -f ../${ZIP_FILE}
42
+
43
+ #build list of tests required by benchmark
44
+ CHECKS_FIFO="${BENCHMARK_FILE%.group}"
45
+ DONE_CHECKS=""
46
+
47
+ while [ ! "${CHECKS_FIFO}" = "" ]
48
+ do
49
+ CURRENT_CHECK=$( echo ${CHECKS_FIFO} | cut -d" " -f1 )
50
+ CHECKS_FIFO=$( echo ${CHECKS_FIFO} | sed -e "s/${CURRENT_CHECK}//" )
51
+ DONE_CHECKS="${DONE_CHECKS} ${CURRENT_CHECK}"
52
+
53
+ echo "adding check: ${CURRENT_CHECK}"
54
+
55
+ if [ -f "${CURRENT_CHECK}.group" ]
56
+ then
57
+ CHILDREN=$( ruby -r "yaml" -e "File.open('${CURRENT_CHECK}.group') {|f| x = YAML::load(f)['Children']; print x ? x.join(' ') : '' }" )
58
+ #add child if it is not already in benchmark
59
+ for f in $( echo ${CHILDREN} )
60
+ do
61
+ if ( ! echo ${CHECKS_FIFO} | grep $f 2>/dev/null 1>/dev/null ) && ( ! echo ${DONE_CHECKS} | grep $f 2>/dev/null 1>/dev/null )
62
+ then
63
+ CHECKS_FIFO="${CHECKS_FIFO} $f"
64
+ fi
65
+ done
66
+
67
+ zip -9 ../${ZIP_FILE} "${CURRENT_CHECK}.group" 2>/dev/null 1>/dev/null
68
+ elif [ -f "${CURRENT_CHECK}.check" ]
69
+ then
70
+ # get list of dependencies
71
+ DEPENDENCIES=$( ruby -r "yaml" -e "File.open('${CURRENT_CHECK}.check') {|f| x = YAML::load(f)['Depends']; print x ? x.join(' ') : '' }" )
72
+
73
+ for f in $( echo ${DEPENDENCIES} )
74
+ do
75
+ if ( ! echo ${CHECKS_FIFO} | grep $f 2>/dev/null 1>/dev/null ) && ( ! echo ${DONE_CHECKS} | grep $f 2>/dev/null 1>/dev/null )
76
+ then
77
+ CHECKS_FIFO="${CHECKS_FIFO} $f"
78
+ fi
79
+ done
80
+
81
+ zip -9 ../${ZIP_FILE} "${CURRENT_CHECK}.check" 2>/dev/null 1>/dev/null
82
+ else
83
+ echo "WARNING: Unsatisfied dependency: ${CURRENT_CHECK}"
84
+ fi
85
+ done
86
+
87
+ for f in $( echo ${MISC_FILES} )
88
+ do
89
+ echo "adding file: $f"
90
+ zip -9 ../${ZIP_FILE} $f 2>/dev/null 1>/dev/null
91
+ done
92
+
93
+ cd -
@@ -0,0 +1,136 @@
1
+ require 'logger'
2
+
3
+ require 'connection/connection_factory'
4
+ require 'benchmark/benchmark_factory'
5
+ require 'linear_script_generator'
6
+ require 'parser/script_output_parser'
7
+ require 'util/random_string'
8
+ require 'benchmark/benchmark_result'
9
+ require 'lazy'
10
+
11
+ class Audit
12
+ attr_reader :benchmark
13
+ attr_reader :connection
14
+ attr_reader :start_time
15
+ attr_reader :end_time
16
+ attr_reader :results
17
+ attr_reader :exceptions
18
+
19
+ # Create a new audit.
20
+ # The audit will be initialized, but not started.
21
+ # * <em>benchmark</em> is a path string that points to the benchmark file
22
+ # that should be used for the audit.
23
+ # * <em>attachment_dir</em> is a path string that points to the directory where incoming
24
+ # files will be saved (that directory needs to be writable). If a null value
25
+ # is passed, ATTACH_FILE requests will be ignored and no files will be saved.
26
+ # * <em>connection_type</em> is a symbol for the connection type that will be used.
27
+ # Anything that can be given to the ConnectionFactory (connection/ConnectionFactory::create)
28
+ # is valid (:ssh, ...)
29
+ # * <em>connection_params</em> is a dictionary of connection parameters that are
30
+ # specific to the connection type chosen with <em>connection_type</em>. See the
31
+ # ConnectionFactory class for more datails.
32
+ # * <em>logger</em> is an optional logger that the debug output is logged to
33
+ def initialize(options)
34
+ raise "Option :benchmark is required" unless options[:benchmark]
35
+ # raise "Option :attachment_dir is required" unless options[:attachment_dir]
36
+ raise "Option :connection_type is required" unless options[:connection_type]
37
+ raise "Option :connection_params is required" unless options[:connection_params]
38
+
39
+ if options[:logger] then
40
+ @logger = options[:logger]
41
+ else
42
+ @logger = Logger.new(STDOUT)
43
+ end
44
+
45
+ @benchmark = BenchmarkFactory.new(:logger => @logger).load(:benchmark => options[:benchmark])
46
+ @connection = ConnectionFactory.new(:logger => @logger).create(:connection_type => options[:connection_type],
47
+ :connection_params => options[:connection_params])
48
+ @results = {}
49
+ @exceptions = []
50
+ @attachment_dir = options[:attachment_dir]
51
+ end
52
+
53
+ def start(parallel = true)
54
+ @start_time = Time.now.utc
55
+
56
+ launch_audit = Proc.new do
57
+ remote_script_path = "/tmp/" + RandomString::generate() + ".sh"
58
+ script = LinearScriptGenerator.generate(@benchmark)
59
+
60
+ @connection.open() do|conn|
61
+ conn.write_to_remote_file(script, remote_script_path)
62
+ @response_parser = ScriptOutputParser.new(:benchmark => @benchmark,
63
+ :connection => conn,
64
+ :attachment_dir => @attachment_dir,
65
+ :logger => @logger)
66
+ @response_parser.on_check_completed() do|rule_result|
67
+ @results[rule_result.rule_idref] = rule_result
68
+ @check_completed_handler.call(rule_result) unless @check_completed_handler.nil?
69
+ end
70
+ @response_parser.on_finished() do|benchmark, rule_results|
71
+ @end_time = Time.now.utc
72
+ @finished_handler.call(benchmark, rule_results) unless @finished_handler.nil?
73
+ end
74
+
75
+ conn.exec("/bin/sh " + remote_script_path)
76
+ end
77
+ end
78
+
79
+ if (parallel) then
80
+ begin
81
+ Thread.new {launch_audit.call}
82
+ rescue Exception => ex
83
+ exceptions << ex
84
+ @logger.error {"Exception type: #{ex.class.name}"}
85
+ @logger.error {"=== stack trace of exception #{ex.message}"}
86
+ ex.backtrace.each do|line|
87
+ @logger.error {line}
88
+ end
89
+ @logger.error {"=== end stack trace"}
90
+ end
91
+ else
92
+ launch_audit.call
93
+ end
94
+ return self
95
+ end
96
+
97
+ def on_check_completed(&block)
98
+ @check_completed_handler = block
99
+ end
100
+
101
+ def on_finished(&block)
102
+ @finished_handler = block
103
+ end
104
+
105
+ def progress()
106
+ return ((@response_parser.progress() unless @response_parser.nil?) or 0.0)
107
+ end
108
+
109
+ def abort()
110
+ @connection.abort() if @connection
111
+ end
112
+
113
+ def finished?()
114
+ return !end_time.nil?
115
+ end
116
+
117
+ def name()
118
+ return (@benchmark.name || @benchmark.id) + "#" + @connection.to_s() + (@start_time ? "#" + @start_time.to_s() : "")
119
+ end
120
+
121
+ def remaining_time()
122
+ return @benchmark.duration() if @response_parser.nil?
123
+ return @response_parser.remaining_time()
124
+ end
125
+
126
+ def to_hash()
127
+ return {
128
+ :type => :AUDIT,
129
+ :start_time => @start_time,
130
+ :end_time => @end_time,
131
+ :connection => @connection.to_hash(),
132
+ :benchmark => @benchmark.to_hash(),
133
+ :results => Lazy.new(@results.values(), :map) {|x| Lazy.new(x, :to_hash)}
134
+ }
135
+ end
136
+ end
@@ -0,0 +1,5 @@
1
+ class AuditFacade
2
+ def start_audit(parameters, &block)
3
+ return Audit.new(parameters, block).start
4
+ end
5
+ end
@@ -0,0 +1,165 @@
1
+ require 'benchmark/check'
2
+ require 'benchmark/item_exception'
3
+ require 'lazy'
4
+
5
+ class AuditBenchmark
6
+ attr_reader :item_repository
7
+
8
+ def execution_order()
9
+ # resolve dependencies between checks based on the depends-tag of the checks.
10
+ # In a first pass, all dependencies are discovered iteratively popping checks
11
+ # from a queue of checks with unresolved dependencies, pushing them onto a resolved
12
+ # queue and pushing the check's dependencies onto the unresolved queue if they
13
+ # are not yet in the resolved or unresolved queue. Also, the reversed dependencies
14
+ # (which check is needed by which) are stored for the second pass.
15
+ #
16
+ # In a second pass, starting from checks which do not depend on any other checks,
17
+ # all checks are labelled with the dependency level they're in. Checks without dependencies
18
+ # have dependency level 0, checks which rely on checks from level 0 have level 1,
19
+ # and so on. This is not the optimal solution for the problem ... but I have forgot why,
20
+ # so figure this out yourself.
21
+ #
22
+ # You might wonder why I don't do dependency tracking with the Imports and Exports
23
+ # declarations: If there are two scripts which provide a variable (alternatives),
24
+ # it is very easy to write a mediating script, which chooses one of the provider scripts,
25
+ # and then can be depended on, but it is very hard to do the resolution based on
26
+ # imports and exports. So imagine this like the linker, which uses library/object
27
+ # names to include dependencies, but still checks that all symbols are resolved
28
+ # correctly (TODO: Add a check that all Imports are satisfied by Exports)
29
+
30
+ #find all dependencies
31
+ items = @children.dup
32
+
33
+ unresolved = []
34
+ while not items.empty?
35
+ item = items.shift
36
+ if item.class == Group
37
+ item.children.each do|x|
38
+ items << x unless items.include? x or unresolved.include? x
39
+ end
40
+ elsif item.class == Check
41
+ unresolved << item
42
+ end
43
+ end
44
+
45
+ resolved = []
46
+ dependency_root = []
47
+ reversed_dependencies = {}
48
+ iterations = 0
49
+
50
+ while !unresolved.empty? and iterations < @item_repository.length
51
+ cur = unresolved.shift
52
+
53
+ dependency_root.push(cur) if cur.dependencies.empty? and not dependency_root.include? cur
54
+
55
+ cur.dependencies.each do|dep|
56
+ unresolved.push dep unless unresolved.include? dep or resolved.include? dep
57
+ reversed_dependencies[dep] = [] if reversed_dependencies[dep].nil?
58
+ reversed_dependencies[dep] << cur
59
+ end
60
+ end
61
+
62
+ untagged = []
63
+ tagged = []
64
+
65
+ dependency_root.each {|x| untagged.push(x)}
66
+ untagged.push(:NEXT_LEVEL)
67
+
68
+ level = 0
69
+ while untagged.length > 1
70
+ cur = untagged.shift
71
+
72
+ if cur == :NEXT_LEVEL then
73
+ level = level + 1
74
+ untagged.push(:NEXT_LEVEL)
75
+ next
76
+ end
77
+
78
+ tag = tagged.select {|x| x[:check] == cur}
79
+ if tag.empty? then
80
+ tagged << {:level => level, :check => cur}
81
+ else
82
+ raise "multiple tags for check #{cur.id} found" if tag.length != 1
83
+
84
+ tag[0][:level] = level
85
+ end
86
+
87
+ unless reversed_dependencies[cur].nil? then
88
+ reversed_dependencies[cur].each {|x| untagged.push(x)}
89
+ end
90
+ end
91
+
92
+ retval = []
93
+ (0 .. level).each {|i| retval.push(tagged.select {|x| x[:level] == i}.map {|x| x[:check]})}
94
+
95
+ return retval
96
+ end
97
+
98
+ def element(name)
99
+ @elements = {} unless @elements
100
+ @elements[name] = element_impl(name) unless @elements[name]
101
+
102
+ return @elements[name]
103
+ end
104
+
105
+ def rules()
106
+ untraversed = @children.dup
107
+ rules = []
108
+
109
+ while untraversed.length > 0
110
+ item = untraversed.shift
111
+
112
+ if item.kind_of? Group then
113
+ untraversed = untraversed + item.children
114
+ elsif item.kind_of? Check then
115
+ rules << item
116
+ end
117
+ end
118
+
119
+ return rules.uniq
120
+ end
121
+
122
+ def dependencies()
123
+ return (rules().map {|x| x.dependencies }.flatten()).uniq
124
+ end
125
+
126
+ def automatic_dependencies()
127
+ return dependencies() - rules()
128
+ end
129
+
130
+ # def checks()
131
+ # checks = []
132
+ # not_traversed = @children.dup
133
+ #
134
+ # while !not_traversed.empty? do
135
+ # item = not_traversed.shift
136
+ #
137
+ # if (item.class == Group) then
138
+ # item.children.each do |child|
139
+ # not_traversed << child unless not_traversed.include? child
140
+ # end
141
+ # elsif item.class == Check then
142
+ # checks << item
143
+ # item.dependencies.each do |dep|
144
+ # not_traversed << dep unless not_traversed.include? dep
145
+ # end
146
+ # end
147
+ # end
148
+ #
149
+ # return checks
150
+ # end
151
+
152
+ def duration()
153
+ execution_order().flatten().each().inject(0) {|result, element| result + element.duration}
154
+ end
155
+
156
+ def to_hash()
157
+ return {
158
+ :type => :BENCHMARK,
159
+ :id => @id,
160
+ :name => @name,
161
+ :description => @description,
162
+ :children => Lazy.new(Lazy.new(@children, :reject) {|x| !x.in_report?}, :map) {|child| Lazy.new(child, :to_hash)}
163
+ }
164
+ end
165
+ end