262 lines
8.2 KiB
Bash
262 lines
8.2 KiB
Bash
#!/bin/bash
|
|
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
|
|
#
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# library-prefix = scapCommon
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# Variables
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
true <<'=cut'
|
|
=pop
|
|
|
|
=item scapCommonDISTRO
|
|
|
|
Name of distribution which is set based on the host system. Variable is set by
|
|
scapCommonGetDistroName function.
|
|
|
|
=item scapCommonDS
|
|
|
|
Full path to datastream file from scap-security-guide package based
|
|
on the host system. Variable is set by scapCommonGetDSPath function.
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
scapCommonDISTRO=""
|
|
scapCommonDS=""
|
|
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# Functions
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
scapCommonLibraryLoaded() {
|
|
return 0
|
|
}
|
|
|
|
|
|
true <<'=cut'
|
|
=pod
|
|
|
|
=head2 scapCommonGetDistroName
|
|
|
|
Prints a name of the host distro.
|
|
Supported distros:
|
|
- Fedora
|
|
- RHEL
|
|
- CentOS Stream
|
|
Usage:
|
|
DISTRO=$(scapCommonGetDistroName)
|
|
|
|
=cut
|
|
function scapCommonGetDistroName() {
|
|
if rlIsRHEL; then
|
|
echo "rhel$(rlGetDistroRelease)"
|
|
elif rlIsCentOS; then
|
|
if rlIsCentOS "<=8"; then
|
|
echo "centos$(rlGetDistroRelease)"
|
|
elif rlIsCentOS ">=9"; then
|
|
echo "cs$(rlGetDistroRelease)"
|
|
fi
|
|
else
|
|
echo "fedora"
|
|
fi
|
|
}
|
|
|
|
scapCommonDISTRO=$(scapCommonGetDistroName)
|
|
|
|
|
|
true <<'=cut'
|
|
=pod
|
|
|
|
=head2 scapCommonGetDSPath
|
|
|
|
Prints a path to a datastream file from the scap-security-guide package based
|
|
on the host distro. Function accepts one optional argument DS_PREFIX_PATH -
|
|
a prefix directory path where a datastream for the host distro is located and
|
|
has a file name of "ssg-$(scapCommonGetDistroName)-ds.xml".
|
|
Supported distros:
|
|
- Fedora
|
|
- RHEL
|
|
- CentOS Stream
|
|
Usage:
|
|
DS=$(scapCommonGetDSPath)
|
|
or
|
|
DS=$(scapCommonGetDSPath <DS_PREFIX_PATH>)
|
|
|
|
=cut
|
|
function scapCommonGetDSPath() {
|
|
local ds_prefix_path="$1"
|
|
|
|
if [ -z "$ds_prefix_path" ]; then
|
|
rpm -ql scap-security-guide | grep "ssg-$(scapCommonGetDistroName)-ds.xml"
|
|
else
|
|
echo "${ds_prefix_path}/ssg-$(scapCommonGetDistroName)-ds.xml"
|
|
fi
|
|
}
|
|
|
|
scapCommonDS=$(scapCommonGetDSPath)
|
|
|
|
|
|
true <<'=cut'
|
|
=pod
|
|
|
|
=head2 scapCommonIsProfileInDS
|
|
|
|
Tries to find a PROFILE in DS.
|
|
Returns 0, if PROFILE is in DS. Otherwise returns 1.
|
|
Usage:
|
|
scapCommonIsProfileInDS <DS> <PROFILE> || rlLog "Profile is not in datastream"
|
|
|
|
=cut
|
|
function scapCommonIsProfileInDS() {
|
|
local datastream="$1"
|
|
local profile="$2"
|
|
|
|
if [[ $profile != xccdf_org.ssgproject.content_profile_* ]]; then
|
|
profile="xccdf_org.ssgproject.content_profile_"$profile
|
|
fi
|
|
|
|
local query="string(//*[local-name()=\"Profile\"][@id=\"$profile\"]/*)"
|
|
local result="$(xmllint --xpath "$query" $datastream)"
|
|
|
|
if [ -z "$result" ]; then
|
|
rlLog "scapCommonIsProfileInDS: $profile profile is not in $datastream"
|
|
return 1
|
|
fi
|
|
|
|
rlLog "scapCommonIsProfileInDS: $profile profile is in $datastream"
|
|
return 0
|
|
}
|
|
|
|
|
|
true <<'=cut'
|
|
=pod
|
|
|
|
=head2 scapCommonIsRuleInProfile
|
|
|
|
Tries to find RULES in a PROFILE from DS. If PROFILE is 'all', then
|
|
it will try to find the rules in datastream regardless of the profile.
|
|
Returns 0, if all RULES are in PROFILE. Otherwise (rules not in profile,
|
|
or profile not in ds) returns 1.
|
|
Usage:
|
|
scapCommonIsRuleInProfile <DS> <RULES> <PROFILE> || rlLog "Rules not in profile"
|
|
|
|
Note: Rule prefix can be used, e.g. "dconf_" - will be checked
|
|
by "grep "xccdf_org.ssgproject.content_rule_dconf_" ds" or
|
|
"xmllint --xpath ...[starts-with(@idref, rule)].. ds"
|
|
=cut
|
|
function scapCommonIsRuleInProfile() {
|
|
local datastream="$1"
|
|
local rules="$2"
|
|
local profile="$3"
|
|
local ret_val=0
|
|
|
|
if [[ $profile == all ]]; then
|
|
for rule in ${rules}; do
|
|
if [[ $rule != xccdf_org.ssgproject.content_rule_* ]]; then
|
|
rule="xccdf_org.ssgproject.content_rule_"$rule
|
|
fi
|
|
if ! grep -q "$rule" "$datastream"; then
|
|
rlLog "scapCommonIsRuleInProfile: $rule rule is not in $datastream"
|
|
ret_val=1
|
|
else
|
|
rlLog "scapCommonIsRuleInProfile: $rule is in $profile profile from $datastream"
|
|
fi
|
|
done
|
|
return $ret_val
|
|
fi
|
|
|
|
if [[ $profile != xccdf_org.ssgproject.content_profile_* ]]; then
|
|
profile="xccdf_org.ssgproject.content_profile_"$profile
|
|
fi
|
|
|
|
scapCommonIsProfileInDS "$datastream" "$profile" || return 1
|
|
local query=""
|
|
for rule in ${rules}; do
|
|
if [[ $rule != xccdf_org.ssgproject.content_rule_* ]]; then
|
|
rule="xccdf_org.ssgproject.content_rule_"$rule
|
|
fi
|
|
query="count(//*[local-name()=\"Profile\"][@id=\"$profile\"]/*[local-name()=\"select\"][starts-with(@idref, \"$rule\")][@selected=\"true\"])"
|
|
local result="$(xmllint --xpath "$query" $datastream)"
|
|
if [ $result -eq 0 ]; then
|
|
rlLog "scapCommonIsRuleInProfile: $rule is not in $profile profile from $datastream"
|
|
ret_val=1
|
|
else
|
|
rlLog "scapCommonIsRuleInProfile: $rule is in $profile profile from $datastream"
|
|
fi
|
|
done
|
|
|
|
return $ret_val
|
|
}
|
|
|
|
|
|
true <<'=cut'
|
|
=pod
|
|
|
|
=head2 scapCommonInstallAnsible
|
|
|
|
Installs Ansible packages needed by Ansible remediations shipped in the
|
|
scap-security-guide package and returns 0 if installation is successful,
|
|
otherwise returns 1.
|
|
Usage:
|
|
scapCommonInstallAnsible || rlDie "Failed to install Ansible"
|
|
|
|
Note: Function utilizes Cleanup library and in the test using this function
|
|
it is expected that CleanupDo function is called in its cleanup phase.
|
|
|
|
=cut
|
|
function scapCommonInstallAnsible() {
|
|
if rlIsFedora; then
|
|
rlRun "dnf install -y ansible" || return 1
|
|
rlAssertRpm ansible
|
|
elif rlIsRHEL 7 || rlIsCentOS 7; then
|
|
if ! rpm -q epel-release &>/dev/null; then
|
|
rlRun "yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm"
|
|
CleanupRegister "rlRun 'yum remove -y epel-release'"
|
|
fi
|
|
rlRun "yum install --enablerepo=epel -y ansible" || return 1
|
|
CleanupRegister "rlRun 'yum remove -y ansible'"
|
|
rlAssertRpm ansible
|
|
else
|
|
rlRun "dnf install -y ansible-core" || return 1
|
|
CleanupRegister "rlRun 'yum remove -y ansible-core'"
|
|
rlAssertRpm ansible-core
|
|
rlRun "dnf install -y rhc-worker-playbook" 0-255
|
|
if [ $? -ne 0 ]; then
|
|
rlLog "rhc-worker-playbook RPM not found, installing required collections from Ansible Galaxy"
|
|
# ansible-galaxy does not support removal of collections through CLI.
|
|
CleanupRegister "rlRun 'rm -rf /root/.ansible/collections/ansible_collections/community/general'"
|
|
CleanupRegister "rlRun 'rm -rf /root/.ansible/collections/ansible_collections/ansible/posix/'"
|
|
for i in $(seq 1 10); do
|
|
local rv=0
|
|
rlLog "Install required collections from Ansible Galaxy (attempt: $i)"
|
|
rlRun "ansible-galaxy collection install community.general" 0-255 || rv=1
|
|
rlRun "ansible-galaxy collection install ansible.posix" 0-255 || rv=1
|
|
if [ $rv -eq 0 ]; then
|
|
break
|
|
else
|
|
if [ $i -eq 10 ]; then
|
|
rlFail "Failed to install required collections from Ansible Galaxy (attempt: $i)"
|
|
return 1
|
|
fi
|
|
rlLogWarning "Failed to install required collections from Ansible Galaxy (attempt: $i)"
|
|
rlLog "Waiting 1m before another attempt.."
|
|
sleep 1m
|
|
fi
|
|
done
|
|
rlRun "ansible-galaxy collection list -v" 0 "List installed Ansible collections"
|
|
else
|
|
CleanupRegister "rlRun 'yum remove -y rhc-worker-playbook'"
|
|
rlAssertRpm rhc-worker-playbook
|
|
rlRun "export ANSIBLE_COLLECTIONS_PATH=/usr/share/rhc-worker-playbook/ansible/collections/ansible_collections/" \
|
|
0 "Export path to Ansible collections from rhc-worker-playbook RPM"
|
|
fi
|
|
fi
|
|
return 0
|
|
}
|