CloudyScripts 1.6.1 → 1.7.27

Sign up to get free protection for your applications and to get access to all the features.
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