Skip to content

Commit 22e46de

Browse files
committed
Add runtime SSHD config checking for OpenShift
Add runtime SSHD config checking for OpenShift compliance operatorThe compliance operator fetches runtime SSHD config from the cluster andfeeds it to the scanner before scans. Adds `sshd_runtime_check` option(default: false, true for RHCOS4), updates OVAL macros, and sets default
1 parent 946c13c commit 22e46de

File tree

5 files changed

+82
-13
lines changed

5 files changed

+82
-13
lines changed

products/rhcos4/product.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ groups:
2020

2121
sshd_distributed_config: "true"
2222

23+
# Enable runtime sshd configuration checking for compliance operator scans
24+
sshd_runtime_check: "true"
25+
2326
cpes_root: "../../shared/applicability"
2427
cpes:
2528
- rhcos4:

shared/macros/10-oval.jinja

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,9 +1033,10 @@ Generates the :code:`<affected>` tag for OVAL check using correct product platfo
10331033
:type datatype: str
10341034

10351035
#}}
1036-
{{%- macro sshd_oval_check(parameter, value, missing_parameter_pass, config_is_distributed, xccdf_variable="", datatype="", rule_id=None, rule_title=None) -%}}
1036+
{{%- macro sshd_oval_check(parameter, value, missing_parameter_pass, config_is_distributed, runtime_check="false", xccdf_variable="", datatype="", rule_id=None, rule_title=None) -%}}
10371037
{{%- set sshd_config_path = "/etc/ssh/sshd_config" %}}
10381038
{{%- set sshd_config_dir = "/etc/ssh/sshd_config.d" -%}}
1039+
{{%- set sshd_runtime_path = "/etc/compliance-operator/runtime/sshd_effective_config" -%}}
10391040
{{%- if xccdf_variable -%}}
10401041
{{%- set description = "Ensure '" ~ parameter ~ "' is configured with value configured in " ~ xccdf_variable ~ " variable in " ~ sshd_config_path %}}
10411042
{{%- else -%}}
@@ -1071,19 +1072,30 @@ Generates the :code:`<affected>` tag for OVAL check using correct product platfo
10711072
<extend_definition comment="rpm package openssh-server installed"
10721073
definition_ref="package_openssh-server_installed" />
10731074
{{% endif %}}
1074-
<criteria comment="sshd is configured correctly" operator="AND">
1075-
<criteria comment="the configuration is correct if it exists" operator="AND">
1076-
{{{- oval_line_in_file_criterion(sshd_config_path, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(10)}}}
1077-
{{%- if config_is_distributed == "true" %}}
1078-
{{{- oval_line_in_directory_criterion(sshd_config_dir, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(10) }}}
1075+
<criteria comment="sshd is configured correctly" operator="OR">
1076+
{{%- if runtime_check == "true" %}}
1077+
<criteria comment="runtime configuration exists and is correct" operator="AND">
1078+
<criterion comment="runtime config file exists" test_ref="test_runtime_config_present_{{{ rule_id }}}" />
1079+
<criterion comment="runtime config matches expected value" test_ref="test_runtime_{{{ parameter }}}_{{{ rule_id }}}" />
1080+
</criteria>
1081+
{{%- endif %}}
1082+
<criteria comment="static configuration is correct (when runtime config doesn't exist or runtime check disabled)" operator="AND">
1083+
{{%- if runtime_check == "true" %}}
1084+
<criterion comment="runtime config file does not exist" test_ref="test_runtime_config_absent_{{{ rule_id }}}" />
10791085
{{%- endif %}}
1080-
{{% if product in ["ol8", "ol9"] %}}
1081-
{{{- oval_line_in_file_criterion("sshd_config included", parameter, id_stem=rule_id ~ "_sshd_included_files", avoid_conflicting=true, rule_id=rule_id) | indent(10)}}}
1086+
<criteria comment="the configuration is correct if it exists" operator="AND">
1087+
{{{- oval_line_in_file_criterion(sshd_config_path, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(12)}}}
1088+
{{%- if config_is_distributed == "true" %}}
1089+
{{{- oval_line_in_directory_criterion(sshd_config_dir, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(12) }}}
1090+
{{%- endif %}}
1091+
{{% if product in ["ol8", "ol9"] %}}
1092+
{{{- oval_line_in_file_criterion("sshd_config included", parameter, id_stem=rule_id ~ "_sshd_included_files", avoid_conflicting=true, rule_id=rule_id) | indent(12)}}}
1093+
{{% endif %}}
1094+
</criteria>
1095+
{{%- if not missing_parameter_pass %}}
1096+
<criterion comment="the configuration exists" test_ref="test_{{{ parameter }}}_present_{{{ rule_id }}}" />
10821097
{{% endif %}}
10831098
</criteria>
1084-
{{%- if not missing_parameter_pass %}}
1085-
<criterion comment="the configuration exists" test_ref="test_{{{ parameter }}}_present_{{{ rule_id }}}" />
1086-
{{% endif %}}
10871099
</criteria>
10881100
</criteria>
10891101
</criteria>
@@ -1162,6 +1174,55 @@ Generates the :code:`<affected>` tag for OVAL check using correct product platfo
11621174
</ind:textfilecontent54_test>
11631175

11641176
{{% endif %}}
1177+
1178+
{{%- if runtime_check == "true" %}}
1179+
<!-- Runtime configuration checks -->
1180+
<ind:textfilecontent54_test id="test_runtime_config_absent_{{{ rule_id }}}" version="1"
1181+
check="none satisfy" check_existence="none_exist"
1182+
comment="Check if runtime config file exists">
1183+
<ind:object object_ref="obj_runtime_config_file_{{{ rule_id }}}" />
1184+
</ind:textfilecontent54_test>
1185+
1186+
<ind:textfilecontent54_test id="test_runtime_config_present_{{{ rule_id }}}" version="1"
1187+
check="all" check_existence="at_least_one_exists"
1188+
comment="Check if runtime config file exists">
1189+
<ind:object object_ref="obj_runtime_config_file_{{{ rule_id }}}" />
1190+
</ind:textfilecontent54_test>
1191+
1192+
<ind:textfilecontent54_object id="obj_runtime_config_file_{{{ rule_id }}}" version="1">
1193+
<ind:filepath>{{{ sshd_runtime_path }}}</ind:filepath>
1194+
<ind:pattern operation="pattern match">.*</ind:pattern>
1195+
<ind:instance datatype="int">1</ind:instance>
1196+
</ind:textfilecontent54_object>
1197+
1198+
<ind:textfilecontent54_test id="test_runtime_{{{ parameter }}}_{{{ rule_id }}}" version="1"
1199+
check="all" check_existence="at_least_one_exists"
1200+
comment="Check runtime {{{ parameter }}} value">
1201+
<ind:object object_ref="obj_runtime_{{{ parameter }}}_{{{ rule_id }}}" />
1202+
{{%- if xccdf_variable -%}}
1203+
<ind:state state_ref="state_runtime_{{{ parameter }}}_{{{ rule_id }}}_xccdf" />
1204+
{{%- else -%}}
1205+
<ind:state state_ref="state_runtime_{{{ parameter }}}_{{{ rule_id }}}" />
1206+
{{%- endif -%}}
1207+
</ind:textfilecontent54_test>
1208+
1209+
<ind:textfilecontent54_object id="obj_runtime_{{{ parameter }}}_{{{ rule_id }}}" version="1">
1210+
<ind:filepath>{{{ sshd_runtime_path }}}</ind:filepath>
1211+
<ind:pattern operation="pattern match">^[\s]*{{{ parameter | lower }}}[\s]+(.*)$</ind:pattern>
1212+
<ind:instance datatype="int">1</ind:instance>
1213+
</ind:textfilecontent54_object>
1214+
1215+
{{%- if xccdf_variable -%}}
1216+
<ind:textfilecontent54_state id="state_runtime_{{{ parameter }}}_{{{ rule_id }}}_xccdf" version="1">
1217+
<ind:subexpression operation="equals" datatype="{{{ datatype }}}" var_ref="{{{ xccdf_variable }}}" />
1218+
</ind:textfilecontent54_state>
1219+
{{%- else -%}}
1220+
<ind:textfilecontent54_state id="state_runtime_{{{ parameter }}}_{{{ rule_id }}}" version="1">
1221+
<ind:subexpression operation="{{{ 'pattern match' if datatype == 'string' else 'equals' }}}" datatype="{{{ datatype }}}">{{{ value }}}</ind:subexpression>
1222+
</ind:textfilecontent54_state>
1223+
{{%- endif -%}}
1224+
{{%- endif %}}
1225+
11651226
</def-group>
11661227
{{%- endmacro %}}
11671228

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{%- if XCCDF_VARIABLE -%}}
2-
{{{ sshd_oval_check(parameter=PARAMETER, xccdf_variable=XCCDF_VARIABLE, missing_parameter_pass=MISSING_PARAMETER_PASS, config_is_distributed=sshd_distributed_config, datatype=DATATYPE, rule_id=rule_id, rule_title=rule_title) }}}
2+
{{{ sshd_oval_check(parameter=PARAMETER, xccdf_variable=XCCDF_VARIABLE, missing_parameter_pass=MISSING_PARAMETER_PASS, config_is_distributed=sshd_distributed_config, runtime_check=sshd_runtime_check, datatype=DATATYPE, rule_id=rule_id, rule_title=rule_title) }}}
33
{{%- else -%}}
4-
{{{ sshd_oval_check(parameter=PARAMETER, value=VALUE, missing_parameter_pass=MISSING_PARAMETER_PASS, config_is_distributed=sshd_distributed_config, datatype=DATATYPE, rule_id=rule_id, rule_title=rule_title) }}}
4+
{{{ sshd_oval_check(parameter=PARAMETER, value=VALUE, missing_parameter_pass=MISSING_PARAMETER_PASS, config_is_distributed=sshd_distributed_config, runtime_check=sshd_runtime_check, datatype=DATATYPE, rule_id=rule_id, rule_title=rule_title) }}}
55
{{%- endif -%}}

ssg/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@
462462
DEFAULT_RSYSLOG_CAFILE = '/etc/pki/tls/cert.pem'
463463
DEFAULT_FAILLOCK_PATH = '/var/run/faillock'
464464
DEFAULT_SSH_DISTRIBUTED_CONFIG = 'false'
465+
DEFAULT_SSH_RUNTIME_CHECK = 'false'
465466
DEFAULT_PRODUCT = 'example'
466467
DEFAULT_CHRONY_CONF_PATH = '/etc/chrony.conf'
467468
DEFAULT_CHRONY_D_PATH = '/etc/chrony.d/'

ssg/products.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
DEFAULT_AUDIT_WATCHES_STYLE,
1818
DEFAULT_RSYSLOG_CAFILE,
1919
DEFAULT_SSH_DISTRIBUTED_CONFIG,
20+
DEFAULT_SSH_RUNTIME_CHECK,
2021
DEFAULT_CHRONY_CONF_PATH,
2122
DEFAULT_CHRONY_D_PATH,
2223
DEFAULT_AUDISP_CONF_PATH,
@@ -108,6 +109,9 @@ def _get_implied_properties(existing_properties):
108109
if "sshd_distributed_config" not in existing_properties:
109110
result["sshd_distributed_config"] = DEFAULT_SSH_DISTRIBUTED_CONFIG
110111

112+
if "sshd_runtime_check" not in existing_properties:
113+
result["sshd_runtime_check"] = DEFAULT_SSH_RUNTIME_CHECK
114+
111115
if "product" not in existing_properties:
112116
result["product"] = DEFAULT_PRODUCT
113117

0 commit comments

Comments
 (0)