Skip to content

Commit

Permalink
Resolve and replace subs with set-values (#27)
Browse files Browse the repository at this point in the history
* Resolve and replace subs with set-values

Fix may have multiple sub elements that
reference set-values containing part
of the full fix.

We need to replace sub with a text node
of the corresponding set-value to parse
the whole fix script.

* Use include instead of prepend
  • Loading branch information
xprazak2 authored and akofink committed Jan 7, 2020
1 parent 4561090 commit 7249abd
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/openscap_parser/fix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ def strategy
@strategy ||= @parsed_xml['strategy']
end

def full_text(set_values)
full_text_lines(set_values).join('')
end

def full_text_lines(set_values)
map_child_nodes(set_values).map do |text_node|
text_node.respond_to?(:text) ? text_node.text : ''
end
end

def map_child_nodes(set_values = [])
map_sub_nodes @parsed_xml.children, set_values
end

def to_h
{
:id => id,
Expand Down
16 changes: 16 additions & 0 deletions lib/openscap_parser/subs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ def subs
def sub_nodes(xpath = './/sub')
@sub_nodes ||= xpath_nodes(xpath)
end

def map_sub_nodes(children, set_values)
children.map do |child|
next child if child.name == 'text'
next replace_sub(Sub.new(parsed_xml: child), set_values) if child.name == 'sub'
child
end
end

private

def replace_sub(sub, set_values)
set_value = set_values.find { |set_value| set_value.id == sub.id }
return unless set_value
set_value.parsed_xml.children.first
end
end
end
end
Expand Down
63 changes: 63 additions & 0 deletions test/fixtures/files/selinux_full_fix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

var_selinux_state="enforcing"

function replace_or_append {
local config_file=$1
local key=$2
local value=$3
local cce=$4
local format=$5

# Check sanity of the input
if [ $# -lt "3" ]
then
echo "Usage: replace_or_append 'config_file_location' 'key_to_search' 'new_value'"
echo
echo "If symlinks need to be taken into account, add yes/no to the last argument"
echo "to allow to 'follow_symlinks'."
echo "Aborting."
exit 1
fi

# Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
# Otherwise, regular sed command will do.
if test -L $config_file; then
sed_command="sed -i --follow-symlinks"
else
sed_command="sed -i"
fi

# Test that the cce arg is not empty or does not equal @CCENUM@.
# If @CCENUM@ exists, it means that there is no CCE assigned.
if ! [ "x$cce" = x ] && [ "$cce" != '@CCENUM@' ]; then
cce="CCE-${cce}"
else
cce="CCE"
fi

# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed "s/[\^=\$,;+]*//g" <<< $key)

# If there is no print format specified in the last arg, use the default format.
if ! [ "x$format" = x ] ; then
printf -v formatted_output "$format" "$stripped_key" "$value"
else
formatted_output="$stripped_key = $value"
fi

# If the key exists, change it. Otherwise, add it to the config_file.
if `grep -qi $key $config_file` ; then
$sed_command "s/$key.*/$formatted_output/g" $config_file
else
# \n is precaution for case where file ends without trailing newline
echo -e "\n# Per $cce: Set $formatted_output in $config_file" >> $config_file
echo -e "$formatted_output" >> $config_file
fi

}

replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state 'CCE-27334-2' '%s=%s'

fixfiles onboot
fixfiles -f relabel
18 changes: 18 additions & 0 deletions test/openscap_parser/test_result_file_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,24 @@ def setup
assert sub.text
assert sub.use
end

test "should resolve set-values for subs" do
set_values = @arf_result_file.test_result.set_values
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" }
rule.fixes.first.map_child_nodes(set_values).all? { |node| node.is_a? Nokogiri::XML::Text }
end

test "should parse full fix text lines" do
set_values = @arf_result_file.test_result.set_values
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" }
assert_equal 5, rule.fixes.first.full_text_lines(set_values).count
end

test "should compose full fix" do
set_values = @arf_result_file.test_result.set_values
rule = @arf_result_file.benchmark.rules.find { |rule| rule.id == "xccdf_org.ssgproject.content_rule_selinux_state" }
assert_equal file_fixture('selinux_full_fix.sh').read, rule.fixes.first.full_text(set_values)
end
end
end

Expand Down

0 comments on commit 7249abd

Please sign in to comment.