#!/bin/bash shellfu import jat_dump shellfu import preupg shellfu import preupg_fupath shellfu import xcase #shellcheck disable=SC2034 { PREUPG__RULE="xccdf_preupg_rule_api_severity_check" PREUPG__UPATH="RHEL6_7/all-xccdf.xml" PREUPG__VALID_ES='0-15' T_MSCRIPT="RHEL6_7/api/severity/check" } # ...................... # # # CASE GENERATOR HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # '''''''''''''''''''''' # # dec_event() { # # Decode numerical event id # case $1 in # the prefix is collation class decorator; gen_eseq will # sort|uniq the result, so here you can define forced # order. (Due to uniq, this also means that events in same # class will be "squashed" into one if found.) # log messages # 0) echo ;; 1) echo A.log_debug;; 2) echo A.log_info ;; 3) echo A.log_error ;; 4) echo A.log_warning ;; # risks # 10) echo ;; 11) echo A.log_slight_risk ;; 12) echo A.log_medium_risk ;; 13) echo A.log_high_risk ;; 14) echo A.log_extreme_risk ;; # exits # 20) echo ;; 21) echo Z.exit_pass ;; 22) echo Z.exit_fail ;; 23) echo Z.exit_error ;; 24) echo Z.exit_not_applicable ;; 25) echo Z.exit_informational ;; 26) echo Z.exit_fixed ;; esac } echoln() { # # Echo each argument separately # for ln in "$@"; do echo "$ln" done } mkesg() { # # Make event sequence generator # local patt=$1 local eclass # event class echo -n 'echoln ' grep -o . <<<"$patt" \ | while read -r eclass; do case $eclass in m) echo -n 'm{0..4}' ;; r) echo -n 'm{10..14}' ;; x) echo -n 'x{20..28}' ;; esac done } gen_eseq() { # # Get all possible programs in pattern $1 # # Usage: gen_eseq PATT # # The PATT has format C[C..], where C is a "event class" and can # be one of following: # # 'm' for log message, # 'r' for risk log, # 'x' for exit_* call, # # Result is all possible unique event sequences (one per line) # conforming to PATT, where: # # * order between 'm' and 'r' is not preserved, # * 'x' is always last, # * each event can happen at least zero times and at most that # many times how many times the class was seen. # # Few examples to shed some light. Programs generated by following # PATTs may have certain properties: # # * 'mrx' can have 0-1 log messages, 0-1 risks and 0-1 exits, # * 'mmrx' can have 0-2 log messages, 0-1 risks and 0-1 exits # * 'mrmx' is the same because log/risk order is not significant, # * 'mrxm' is still the same because 'x' is forced to be last, # * 'mrxx' would have 0-2 exit calls, # # Note that these are not real programs but just lists of events # (named as API functions just for convenience); you will have to # parse the list (comma-separated) and append arguments where needed. # local patt=$1 # event pattern local eseq # event id sequence local eid # event id local esg # sequence generator (makes use of '{..}' Bash syntax) esg=$(mkesg "$patt") eval "$esg" \ | while read -r eseq; do grep -oE '[[:alpha:]][[:digit:]]+' <<<"$eseq" \ | while read -0r eid; do dec_event "${eid:1}" done \ | grep . \ | sort \ | uniq \ | colrm 1 2 \ | paste -sd, done \ | grep . \ | sort \ | uniq } # ............. # # # SETUP HELPERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # ''''''''''''' # # mkcode() { # # Make body of module # xcase__id \ | tr , '\n' \ | while read -r event; do case $event in log_*_risk) echo "$event risk.by.$event" ;; log_*) echo "$event message.from.$event" ;; exit_*) echo "$event" ;; esac done } # ............. # # # INTROSPECTION # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # ''''''''''''' # # risksort() { # # Sort risk log calls based on severity (decorated sort) # local call # the risk call local args # ... args (finally ignored) while read -r call args; do case $call in log_slight_risk) echo -n '1 ' ;; log_medium_risk) echo -n '2 ' ;; log_high_risk) echo -n '3 ' ;; log_extreme_risk) echo -n '4 ' ;; esac echo "$call $args" done \ | sort -n \ | cut -d' ' -f2 } logmsort() { # # Sort log message calls based on severity (decorated sort) # local call # the log call local args # ... args (finally ignored) while read -r call args; do case $call in log_debug) echo -n '1 ' ;; log_info) echo -n '2 ' ;; log_warning) echo -n '3 ' ;; log_error) echo -n '4 ' ;; esac echo "$call $args" done \ | sort -n \ | cut -d' ' -f2 } get_worst_risk() { grep '^log_[a-z]*_risk' "$T_MSCRIPT" \ | risksort \ | tail -1 } get_first_exit() { grep ^exit_ "$T_MSCRIPT" \ | head -1 } get_risknum() { grep -c '^log_[a-z]*_risk' "$T_MSCRIPT" } get_worst_logm() { grep '^log_' "$T_MSCRIPT" \ | grep -v '_risk\b' \ | logmsort \ | tail -1 } # .............. # # # XCASE HANDLERS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # '''''''''''''' # # xcase__enum() { gen_eseq rx #FIXME: add larger modes such as 'rrx', 'mrx' or 'rxx' } xcase__setup() { { echo '[MODULE]' echo 'GROUP = api' echo 'NAME = severity' mkcode | sed 's/^/CODE = /' } > module.mdef preupg_fupath RHEL6_7 "module.mdef" } xcase__test() { local o_es # oracle: exit status local o_result # oracle: assessment result # set up oracles # case $(get_first_exit):$(get_worst_risk) in # obviously error # :*) o_es=2; o_result=error ;; exit_error:*) o_es=2; o_result=error ;; # valid calls to exit_fail # exit_fail:log_slight_risk) o_es=0; o_result=needs_inspection ;; exit_fail:log_medium_risk) o_es=0; o_result=needs_inspection ;; exit_fail:log_high_risk) o_es=1; o_result=needs_action ;; exit_fail:log_extreme_risk) o_es=2; o_result=fail ;; # (mostly in)valid calls to other exit_* # exit_pass:*) o_es=0; o_result=pass ;; exit_not_applicable:*) o_es=0; o_result=notapplicable ;; exit_informational:*) o_es=0; o_result=informational ;; exit_fixed:*) o_es=0; o_result=fixed ;; exit_fail:) o_es=2; o_result=fail ;; esac # run preupg # PREUPG__VALID_ES=$o_es \ preupg__run1 --skip-common preupg__assert result "$o_result" } xcase__diag() { jat_dump__file module.mdef "$T_MSCRIPT" preupg__get_risks | jat_dump__pipe RESULT_RISKS preupg__get_node | jat_dump__pipe RESULT_NODE } xcase__cleanup() { jat__cmd rm -rf RHEL6_7 preupg__rmresult } # ............ # # # MAIN() STUFF # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # '''''''''''' # # PREUPG__UPATH=@pass \ preupg__Run1 xcase__run preupg__Cleanup