test 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #!/bin/bash
  2. shellfu import jat_dump
  3. shellfu import preupg
  4. shellfu import preupg_fupath
  5. shellfu import xcase
  6. #shellcheck disable=SC2034
  7. {
  8. PREUPG__RULE="xccdf_preupg_rule_api_severity_check"
  9. PREUPG__UPATH="RHEL6_7/all-xccdf.xml"
  10. PREUPG__VALID_ES='0-15'
  11. T_MSCRIPT="RHEL6_7/api/severity/check"
  12. }
  13. # ...................... # #
  14. # CASE GENERATOR HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  15. # '''''''''''''''''''''' # #
  16. dec_event() {
  17. #
  18. # Decode numerical event id
  19. #
  20. case $1 in
  21. # the prefix is collation class decorator; gen_eseq will
  22. # sort|uniq the result, so here you can define forced
  23. # order. (Due to uniq, this also means that events in same
  24. # class will be "squashed" into one if found.)
  25. # log messages
  26. #
  27. 0) echo ;;
  28. 1) echo A.log_debug;;
  29. 2) echo A.log_info ;;
  30. 3) echo A.log_error ;;
  31. 4) echo A.log_warning ;;
  32. # risks
  33. #
  34. 10) echo ;;
  35. 11) echo A.log_slight_risk ;;
  36. 12) echo A.log_medium_risk ;;
  37. 13) echo A.log_high_risk ;;
  38. 14) echo A.log_extreme_risk ;;
  39. # exits
  40. #
  41. 20) echo ;;
  42. 21) echo Z.exit_pass ;;
  43. 22) echo Z.exit_fail ;;
  44. 23) echo Z.exit_error ;;
  45. 24) echo Z.exit_not_applicable ;;
  46. 25) echo Z.exit_informational ;;
  47. 26) echo Z.exit_fixed ;;
  48. esac
  49. }
  50. echoln() {
  51. #
  52. # Echo each argument separately
  53. #
  54. for ln in "$@";
  55. do
  56. echo "$ln"
  57. done
  58. }
  59. mkesg() {
  60. #
  61. # Make event sequence generator
  62. #
  63. local patt=$1
  64. local eclass # event class
  65. echo -n 'echoln '
  66. grep -o . <<<"$patt" \
  67. | while read -r eclass;
  68. do
  69. case $eclass in
  70. m) echo -n 'm{0..4}' ;;
  71. r) echo -n 'm{10..14}' ;;
  72. x) echo -n 'x{20..28}' ;;
  73. esac
  74. done
  75. }
  76. gen_eseq() {
  77. #
  78. # Get all possible programs in pattern $1
  79. #
  80. # Usage: gen_eseq PATT
  81. #
  82. # The PATT has format C[C..], where C is a "event class" and can
  83. # be one of following:
  84. #
  85. # 'm' for log message,
  86. # 'r' for risk log,
  87. # 'x' for exit_* call,
  88. #
  89. # Result is all possible unique event sequences (one per line)
  90. # conforming to PATT, where:
  91. #
  92. # * order between 'm' and 'r' is not preserved,
  93. # * 'x' is always last,
  94. # * each event can happen at least zero times and at most that
  95. # many times how many times the class was seen.
  96. #
  97. # Few examples to shed some light. Programs generated by following
  98. # PATTs may have certain properties:
  99. #
  100. # * 'mrx' can have 0-1 log messages, 0-1 risks and 0-1 exits,
  101. # * 'mmrx' can have 0-2 log messages, 0-1 risks and 0-1 exits
  102. # * 'mrmx' is the same because log/risk order is not significant,
  103. # * 'mrxm' is still the same because 'x' is forced to be last,
  104. # * 'mrxx' would have 0-2 exit calls,
  105. #
  106. # Note that these are not real programs but just lists of events
  107. # (named as API functions just for convenience); you will have to
  108. # parse the list (comma-separated) and append arguments where needed.
  109. #
  110. local patt=$1 # event pattern
  111. local eseq # event id sequence
  112. local eid # event id
  113. local esg # sequence generator (makes use of '{..}' Bash syntax)
  114. esg=$(mkesg "$patt")
  115. eval "$esg" \
  116. | while read -r eseq;
  117. do
  118. grep -oE '[[:alpha:]][[:digit:]]+' <<<"$eseq" \
  119. | while read -0r eid;
  120. do
  121. dec_event "${eid:1}"
  122. done \
  123. | grep . \
  124. | sort \
  125. | uniq \
  126. | colrm 1 2 \
  127. | paste -sd,
  128. done \
  129. | grep . \
  130. | sort \
  131. | uniq
  132. }
  133. # ............. # #
  134. # SETUP HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  135. # ''''''''''''' # #
  136. mkcode() {
  137. #
  138. # Make body of module
  139. #
  140. xcase__id \
  141. | tr , '\n' \
  142. | while read -r event;
  143. do
  144. case $event in
  145. log_*_risk) echo "$event risk.by.$event" ;;
  146. log_*) echo "$event message.from.$event" ;;
  147. exit_*) echo "$event" ;;
  148. esac
  149. done
  150. }
  151. # ............. # #
  152. # INTROSPECTION # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  153. # ''''''''''''' # #
  154. risksort() {
  155. #
  156. # Sort risk log calls based on severity (decorated sort)
  157. #
  158. local call # the risk call
  159. local args # ... args (finally ignored)
  160. while read -r call args;
  161. do
  162. case $call in
  163. log_slight_risk) echo -n '1 ' ;;
  164. log_medium_risk) echo -n '2 ' ;;
  165. log_high_risk) echo -n '3 ' ;;
  166. log_extreme_risk) echo -n '4 ' ;;
  167. esac
  168. echo "$call $args"
  169. done \
  170. | sort -n \
  171. | cut -d' ' -f2
  172. }
  173. logmsort() {
  174. #
  175. # Sort log message calls based on severity (decorated sort)
  176. #
  177. local call # the log call
  178. local args # ... args (finally ignored)
  179. while read -r call args;
  180. do
  181. case $call in
  182. log_debug) echo -n '1 ' ;;
  183. log_info) echo -n '2 ' ;;
  184. log_warning) echo -n '3 ' ;;
  185. log_error) echo -n '4 ' ;;
  186. esac
  187. echo "$call $args"
  188. done \
  189. | sort -n \
  190. | cut -d' ' -f2
  191. }
  192. get_worst_risk() {
  193. grep '^log_[a-z]*_risk' "$T_MSCRIPT" \
  194. | risksort \
  195. | tail -1
  196. }
  197. get_first_exit() {
  198. grep ^exit_ "$T_MSCRIPT" \
  199. | head -1
  200. }
  201. get_risknum() {
  202. grep -c '^log_[a-z]*_risk' "$T_MSCRIPT"
  203. }
  204. get_worst_logm() {
  205. grep '^log_' "$T_MSCRIPT" \
  206. | grep -v '_risk\b' \
  207. | logmsort \
  208. | tail -1
  209. }
  210. # .............. # #
  211. # XCASE HANDLERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  212. # '''''''''''''' # #
  213. xcase__enum() {
  214. gen_eseq rx
  215. #FIXME: add larger modes such as 'rrx', 'mrx' or 'rxx'
  216. }
  217. xcase__setup() {
  218. {
  219. echo '[MODULE]'
  220. echo 'GROUP = api'
  221. echo 'NAME = severity'
  222. mkcode | sed 's/^/CODE = /'
  223. } > module.mdef
  224. preupg_fupath RHEL6_7 "module.mdef"
  225. }
  226. xcase__test() {
  227. local o_es # oracle: exit status
  228. local o_result # oracle: assessment result
  229. # set up oracles
  230. #
  231. case $(get_first_exit):$(get_worst_risk) in
  232. # obviously error
  233. #
  234. :*) o_es=2; o_result=error ;;
  235. exit_error:*) o_es=2; o_result=error ;;
  236. # valid calls to exit_fail
  237. #
  238. exit_fail:log_slight_risk) o_es=0; o_result=needs_inspection ;;
  239. exit_fail:log_medium_risk) o_es=0; o_result=needs_inspection ;;
  240. exit_fail:log_high_risk) o_es=1; o_result=needs_action ;;
  241. exit_fail:log_extreme_risk) o_es=2; o_result=fail ;;
  242. # (mostly in)valid calls to other exit_*
  243. #
  244. exit_pass:*) o_es=0; o_result=pass ;;
  245. exit_not_applicable:*) o_es=0; o_result=notapplicable ;;
  246. exit_informational:*) o_es=0; o_result=informational ;;
  247. exit_fixed:*) o_es=0; o_result=fixed ;;
  248. exit_fail:) o_es=2; o_result=fail ;;
  249. esac
  250. # run preupg
  251. #
  252. PREUPG__VALID_ES=$o_es \
  253. preupg__run1 --skip-common
  254. preupg__assert result "$o_result"
  255. }
  256. xcase__diag() {
  257. jat_dump__file module.mdef "$T_MSCRIPT"
  258. preupg__get_risks | jat_dump__pipe RESULT_RISKS
  259. preupg__get_node | jat_dump__pipe RESULT_NODE
  260. }
  261. xcase__cleanup() {
  262. jat__cmd rm -rf RHEL6_7
  263. preupg__rmresult
  264. }
  265. # ............ # #
  266. # MAIN() STUFF # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
  267. # '''''''''''' # #
  268. PREUPG__UPATH=@pass \
  269. preupg__Run1
  270. xcase__run
  271. preupg__Cleanup