Blame SOURCES/scap-security-guide-0.1.58-sshd_directory_config-PR_6926.patch

9be3b2
From b951a896d3ef1e678e5d6b580521053e7a076ab0 Mon Sep 17 00:00:00 2001
9be3b2
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
9be3b2
Date: Thu, 29 Apr 2021 16:54:03 +0200
9be3b2
Subject: [PATCH 1/6] Updated checks and remediations of the sshd template.
9be3b2
9be3b2
Configuration of sshd moves from one config file to a config directory.
9be3b2
Therefore, checks should consider all those files, and the remediation should aim
9be3b2
to deliver fixes to one of those files in the config directory.
9be3b2
9be3b2
Tests that interact with this behavior have been added and are applicable for Fedora and RHEL9 products.
9be3b2
---
9be3b2
 .../tests/commented.fail.sh                   |  7 ++
9be3b2
 .../tests/conflict.fail.sh                    | 15 ++++
9be3b2
 .../tests/correct_value_directory.pass.sh     | 14 ++++
9be3b2
 shared/macros-bash.jinja                      |  9 +++
9be3b2
 shared/macros-oval.jinja                      | 61 +++++++++++------
9be3b2
 .../templates/sshd_lineinfile/bash.template   | 22 ++++++
9be3b2
 .../templates/sshd_lineinfile/oval.template   | 68 +++++++++++++++++--
9be3b2
 7 files changed, 168 insertions(+), 28 deletions(-)
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/commented.fail.sh
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/conflict.fail.sh
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/correct_value_directory.pass.sh
9be3b2
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/commented.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/commented.fail.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..484c2165532
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/commented.fail.sh
9be3b2
@@ -0,0 +1,7 @@
9be3b2
+#!/bin/bash
9be3b2
+
9be3b2
+if grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config; then
9be3b2
+	sed -i "s/^PubkeyAuthentication.*/# PubkeyAuthentication no/" /etc/ssh/sshd_config
9be3b2
+else
9be3b2
+	echo "# PubkeyAuthentication no" >> /etc/ssh/sshd_config
9be3b2
+fi
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/conflict.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/conflict.fail.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..177a99e0b82
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/conflict.fail.sh
9be3b2
@@ -0,0 +1,15 @@
9be3b2
+#!/bin/bash
9be3b2
+
9be3b2
+# platform = Fedora,Red Hat Enterprise Linux 9
9be3b2
+
9be3b2
+mkdir -p /etc/ssh/sshd_config.d
9be3b2
+touch /etc/ssh/sshd_config.d/nothing
9be3b2
+
9be3b2
+if grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* ; then
9be3b2
+	sed -i "s/^PubkeyAuthentication.*/# PubkeyAuthentication no/" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
9be3b2
+else
9be3b2
+	echo "# PubkeyAuthentication no" >> /etc/ssh/sshd_config
9be3b2
+fi
9be3b2
+
9be3b2
+echo "PubkeyAuthentication no" > /etc/ssh/sshd_config.d/good_config
9be3b2
+echo "PubkeyAuthentication yes" > /etc/ssh/sshd_config.d/rogue_config
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/correct_value_directory.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/correct_value_directory.pass.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..0aa2e775dbe
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_disable_pubkey_auth/tests/correct_value_directory.pass.sh
9be3b2
@@ -0,0 +1,14 @@
9be3b2
+#!/bin/bash
9be3b2
+
9be3b2
+# platform = Fedora,Red Hat Enterprise Linux 9
9be3b2
+
9be3b2
+mkdir -p /etc/ssh/sshd_config.d
9be3b2
+touch /etc/ssh/sshd_config.d/nothing
9be3b2
+
9be3b2
+if grep -q "^PubkeyAuthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* ; then
9be3b2
+	sed -i "s/^PubkeyAuthentication.*/# PubkeyAuthentication no/" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
9be3b2
+else
9be3b2
+	echo "# PubkeyAuthentication no" >> /etc/ssh/sshd_config
9be3b2
+fi
9be3b2
+
9be3b2
+echo "PubkeyAuthentication no" > /etc/ssh/sshd_config.d/correct
9be3b2
diff --git a/shared/macros-bash.jinja b/shared/macros-bash.jinja
9be3b2
index 1cd2c62b5e0..b4518d83c19 100644
9be3b2
--- a/shared/macros-bash.jinja
9be3b2
+++ b/shared/macros-bash.jinja
9be3b2
@@ -471,6 +471,15 @@ fi
9be3b2
 LC_ALL=C sed -i "/{{{ regex }}}/{{{ modifier }}}" "{{{ path }}}"
9be3b2
 {{%- endmacro -%}}
9be3b2
 
9be3b2
+{{%- macro lineinfile_absent_in_directory(dirname, regex, insensitive=true) -%}}
9be3b2
+    {{%- if insensitive -%}}
9be3b2
+        {{%- set modifier="Id" -%}}
9be3b2
+    {{%- else -%}}
9be3b2
+        {{%- set modifier="d" -%}}
9be3b2
+    {{%- endif -%}}
9be3b2
+LC_ALL=C sed -i "/{{{ regex }}}/{{{ modifier }}}" "{{{ dirname }}}"/*
9be3b2
+{{%- endmacro -%}}
9be3b2
+
9be3b2
 {{%- macro lineinfile_present(path, line, insert_after="", insert_before="", insensitive=true) -%}}
9be3b2
     {{%- if insensitive -%}}
9be3b2
         {{%- set grep_args="-q -m 1 -i" -%}}
9be3b2
diff --git a/shared/macros-oval.jinja b/shared/macros-oval.jinja
9be3b2
index be2ac268206..d38db96d9e3 100644
9be3b2
--- a/shared/macros-oval.jinja
9be3b2
+++ b/shared/macros-oval.jinja
9be3b2
@@ -92,15 +92,18 @@
9be3b2
     - parameter (String): The parameter to be checked in the configuration file.
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_criterion(path='', parameter='', missing_parameter_pass=false) -%}}
9be3b2
+{{%- macro oval_line_in_file_criterion(path='', parameter='', missing_parameter_pass=false, comment='', id_stem=rule_id) -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- set prefix_text = "Check the" -%}}
9be3b2
 {{%- if missing_parameter_pass %}}
9be3b2
 {{%- set suffix_id = suffix_id_default_not_overriden -%}}
9be3b2
 {{%- set prefix_text = prefix_text + " absence of" -%}}
9be3b2
 {{%- endif %}}
9be3b2
-      
9be3b2
-      test_ref="test_{{{ rule_id }}}{{{ suffix_id }}}" />
9be3b2
+{{%- if not comment -%}}
9be3b2
+{{%- set comment = prefix_text ~ " " ~ parameter ~ " in " ~ path -%}}
9be3b2
+{{%- endif -%}}
9be3b2
+
9be3b2
+  test_ref="test_{{{ id_stem }}}{{{ suffix_id }}}" />
9be3b2
 {{%- endmacro %}}
9be3b2
 
9be3b2
 {{#
9be3b2
@@ -110,7 +113,7 @@
9be3b2
     - parameter (String): The parameter to be checked in the configuration file.
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_test(path='', parameter='', missing_parameter_pass=false) -%}}
9be3b2
+{{%- macro oval_line_in_file_test(path='', parameter='', missing_parameter_pass=false, id_stem=rule_id) -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- if missing_parameter_pass %}}
9be3b2
 {{%- set check_existence = "none_exist" -%}}
9be3b2
@@ -120,14 +123,14 @@
9be3b2
 {{%- set check_existence = "all_exist" -%}}
9be3b2
 {{%- set prefix_text = "value" -%}}
9be3b2
 {{%- endif %}}
9be3b2
-  
9be3b2
+
9be3b2
   comment="tests the {{{ prefix_text }}} of {{{ parameter }}} setting in the {{{ path }}} file"
9be3b2
-  id="test_{{{ rule_id }}}{{{ suffix_id }}}" version="1">
9be3b2
-  <ind:object object_ref="obj_{{{ rule_id }}}{{{ suffix_id }}}" />
9be3b2
+  id="test_{{{ id_stem }}}{{{ suffix_id }}}" version="1">
9be3b2
+  <ind:object object_ref="obj_{{{ id_stem }}}{{{ suffix_id }}}" />
9be3b2
   {{%- if not missing_parameter_pass %}}
9be3b2
-  <ind:state state_ref="state_{{{ rule_id }}}{{{ suffix_id }}}" />
9be3b2
+  <ind:state state_ref="state_{{{ id_stem }}}{{{ suffix_id }}}" />
9be3b2
   {{%- endif %}}
9be3b2
-  </ind:textfilecontent54_test>
9be3b2
+</ind:textfilecontent54_test>
9be3b2
 {{%- endmacro %}}
9be3b2
 
9be3b2
 {{#
9be3b2
@@ -141,7 +144,7 @@
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
     - multi_value (boolean): If set, it means that the parameter can accept multiple values and the expected value must be present in the current list of values.
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_object(path='', section='', prefix_regex='^[ \\t]*', parameter='', separator_regex='[ \\t]+', missing_parameter_pass=false, multi_value=false, filepath_regex='') -%}}
9be3b2
+{{%- macro oval_line_in_file_object(path='', section='', prefix_regex='^[ \\t]*', parameter='', separator_regex='[ \\t]+', missing_parameter_pass=false, multi_value=false, filepath_regex='', id_stem=rule_id) -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- if multi_value -%}}
9be3b2
 {{%- set group_regex = "([^#]*).*$" -%}}
9be3b2
@@ -173,16 +176,16 @@
9be3b2
 {{%- set regex = prefix_regex+parameter+separator_regex+group_regex -%}}
9be3b2
 {{%- endif %}}
9be3b2
 {{%- endif %}}
9be3b2
-  <ind:textfilecontent54_object id="obj_{{{ rule_id }}}{{{ suffix_id }}}" version="1">
9be3b2
+<ind:textfilecontent54_object id="obj_{{{ id_stem }}}{{{ suffix_id }}}" version="1">
9be3b2
 {{%- if filepath_regex %}}
9be3b2
-    <ind:path>{{{ path }}}</ind:path>
9be3b2
-    <ind:filename operation="pattern match">{{{ filepath_regex }}}</ind:filename>
9be3b2
+  <ind:path>{{{ path }}}</ind:path>
9be3b2
+  <ind:filename operation="pattern match">{{{ filepath_regex }}}</ind:filename>
9be3b2
 {{%- else %}}
9be3b2
-    <ind:filepath>{{{ path }}}</ind:filepath>
9be3b2
+  <ind:filepath>{{{ path }}}</ind:filepath>
9be3b2
 {{%- endif %}}
9be3b2
-    <ind:pattern operation="pattern match">{{{ regex }}}</ind:pattern>
9be3b2
-    <ind:instance operation="greater than or equal" datatype="int">1</ind:instance>
9be3b2
-  </ind:textfilecontent54_object>
9be3b2
+  <ind:pattern operation="pattern match">{{{ regex }}}</ind:pattern>
9be3b2
+  <ind:instance operation="greater than or equal" datatype="int">1</ind:instance>
9be3b2
+</ind:textfilecontent54_object>
9be3b2
 {{%- endmacro %}}
9be3b2
 
9be3b2
 {{#
9be3b2
@@ -193,7 +196,7 @@
9be3b2
     - quotes (String): If non-empty, one level of matching quotes is considered when checking the value. Specify one or more quote types as a string.
9be3b2
       For example, for shell quoting, specify quotes="'\""), which will make sure that value, 'value' and "value" are matched, but 'value" or '"value"' won't be.
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_state(value='', multi_value='', quotes='') -%}}
9be3b2
+{{%- macro oval_line_in_file_state(value='', multi_value='', quotes='', id_stem=rule_id) -%}}
9be3b2
 {{%- set regex = value -%}}
9be3b2
 {{%- if quotes != "" %}}
9be3b2
 {{%- if "\\1" in value > 0 %}}
9be3b2
@@ -206,9 +209,25 @@
9be3b2
 {{%- else %}}
9be3b2
 {{%- set regex = "^"+regex+"$" -%}}
9be3b2
 {{%- endif %}}
9be3b2
-  <ind:textfilecontent54_state id="state_{{{ rule_id }}}" version="1">
9be3b2
-    <ind:subexpression datatype="string" operation="pattern match">{{{ regex }}}</ind:subexpression>
9be3b2
-  </ind:textfilecontent54_state>
9be3b2
+<ind:textfilecontent54_state id="state_{{{ id_stem }}}" version="1">
9be3b2
+  <ind:subexpression datatype="string" operation="pattern match">{{{ regex }}}</ind:subexpression>
9be3b2
+</ind:textfilecontent54_state>
9be3b2
+{{%- endmacro %}}
9be3b2
+
9be3b2
+{{%- macro oval_line_in_directory_criterion(path='', parameter='', missing_parameter_pass=false) -%}}
9be3b2
+{{{- oval_line_in_file_criterion(path, parameter, missing_parameter_pass, id_stem=rule_id ~ "_config_dir") -}}}
9be3b2
+{{%- endmacro %}}
9be3b2
+
9be3b2
+{{%- macro oval_line_in_directory_test(path='', parameter='', missing_parameter_pass=false) -%}}
9be3b2
+{{{ oval_line_in_file_test(path, parameter, missing_parameter_pass, id_stem=rule_id ~ "_config_dir") }}}
9be3b2
+{{%- endmacro %}}
9be3b2
+
9be3b2
+{{%- macro oval_line_in_directory_object(path='', section='', prefix_regex='^[ \\t]*', parameter='', separator_regex='[ \\t]+', missing_parameter_pass=false, multi_value=false) -%}}
9be3b2
+{{{- oval_line_in_file_object(path=path, section=section, prefix_regex=prefix_regex, parameter=parameter, separator_regex=separator_regex, missing_parameter_pass=missing_parameter_pass, multi_value=multi_value, filepath_regex=".*", id_stem=rule_id ~ "_config_dir") -}}}
9be3b2
+{{%- endmacro %}}
9be3b2
+
9be3b2
+{{%- macro oval_line_in_directory_state(value='', multi_value='', quotes='') -%}}
9be3b2
+{{{- oval_line_in_file_state(value, multi_value, quotes, id_stem=rule_id ~ "_config_dir") -}}}
9be3b2
 {{%- endmacro %}}
9be3b2
 
9be3b2
 {{#
9be3b2
diff --git a/shared/templates/sshd_lineinfile/bash.template b/shared/templates/sshd_lineinfile/bash.template
9be3b2
index ca1b512bb3d..eac758e310b 100644
9be3b2
--- a/shared/templates/sshd_lineinfile/bash.template
9be3b2
+++ b/shared/templates/sshd_lineinfile/bash.template
9be3b2
@@ -3,4 +3,26 @@
9be3b2
 # strategy = restrict
9be3b2
 # complexity = low
9be3b2
 # disruption = low
9be3b2
+{{%- if product in ("fedora", "rhel9") %}}
9be3b2
+{{%- set prefix_regex = "^\s*" -%}}
9be3b2
+{{%- set separator_regex = "\s\+" -%}}
9be3b2
+{{%- set line_regex = prefix_regex ~ PARAMETER ~ separator_regex %}}
9be3b2
+mkdir -p /etc/ssh/sshd_config.d
9be3b2
+touch /etc/ssh/sshd_config.d/hardening
9be3b2
+{{{ lineinfile_absent("/etc/ssh/sshd_config", line_regex, insensitive=true) }}}
9be3b2
+{{{ lineinfile_absent_in_directory("/etc/ssh/sshd_config.d", line_regex, insensitive=true) }}}
9be3b2
+{{{ set_config_file(
9be3b2
+        path="/etc/ssh/sshd_config.d/hardening",
9be3b2
+        parameter=PARAMETER,
9be3b2
+        value=VALUE,
9be3b2
+        create=true,
9be3b2
+        insert_after="",
9be3b2
+        insert_before="^Match",
9be3b2
+        insensitive=true,
9be3b2
+        separator=" ",
9be3b2
+        separator_regex=separator_regex,
9be3b2
+        prefix_regex=prefix_regex)
9be3b2
+    }}}
9be3b2
+{{%- else %}}
9be3b2
 {{{ bash_sshd_config_set(parameter=PARAMETER, value=VALUE) }}}
9be3b2
+{{%- endif %}}
9be3b2
diff --git a/shared/templates/sshd_lineinfile/oval.template b/shared/templates/sshd_lineinfile/oval.template
9be3b2
index df63d542505..2cc38776eb2 100644
9be3b2
--- a/shared/templates/sshd_lineinfile/oval.template
9be3b2
+++ b/shared/templates/sshd_lineinfile/oval.template
9be3b2
@@ -1,7 +1,61 @@
9be3b2
-{{{
9be3b2
-oval_sshd_config(
9be3b2
-	parameter=PARAMETER,
9be3b2
-	value=VALUE,
9be3b2
-	missing_parameter_pass=MISSING_PARAMETER_PASS
9be3b2
-)
9be3b2
-}}}
9be3b2
+{{%- set config_path = "/etc/ssh/sshd_config" %}}
9be3b2
+{{%- set config_dir = "/etc/ssh/sshd_config.d" -%}}
9be3b2
+{{%- set products_with_distributed_configuration = ("rhel9", "fedora") -%}}
9be3b2
+{{%- set description = "Ensure '" ~ PARAMETER ~ "' is configured with value '" ~ VALUE ~ "' in " ~ config_path %}}
9be3b2
+{{%- if product in products_with_distributed_configuration %}}
9be3b2
+{{%- set description = description  ~ " and in " ~ config_dir -%}}
9be3b2
+{{%- endif %}}
9be3b2
+{{%- set case_insensitivity_kwargs = dict(prefix_regex="^[ \\t]*(?i)", separator_regex = "(?-i)[ \\t]+") -%}}
9be3b2
+
9be3b2
+<def-group>
9be3b2
+  <definition class="compliance" id="{{{ rule_id }}}" version="1">
9be3b2
+   {{{ oval_metadata(description) }}}
9be3b2
+   <criteria comment="sshd is configured correctly or is not installed" operator="OR">
9be3b2
+     <criteria comment="sshd is not installed" operator="AND">
9be3b2
+        
9be3b2
+          definition_ref="sshd_not_required_or_unset" />
9be3b2
+        
9be3b2
+          definition_ref="package_openssh-server_removed" />
9be3b2
+     </criteria>
9be3b2
+     <criteria comment="sshd is installed and configured" operator="AND">
9be3b2
+        
9be3b2
+          definition_ref="sshd_required_or_unset" />
9be3b2
+        
9be3b2
+          definition_ref="package_openssh-server_installed" />
9be3b2
+        <criteria comment="sshd is configured correctly" operator="OR">
9be3b2
+          {{{- oval_line_in_file_criterion(config_path, PARAMETER) | indent(8) }}}
9be3b2
+          {{%- if MISSING_PARAMETER_PASS %}}
9be3b2
+          <criteria comment="sshd is not configured incorrectly" operator="AND">
9be3b2
+          {{{- oval_line_in_file_criterion(config_path, PARAMETER, MISSING_PARAMETER_PASS) | indent(10)}}}
9be3b2
+          {{%- if product in products_with_distributed_configuration %}}
9be3b2
+          {{{- oval_line_in_directory_criterion(config_dir, PARAMETER, MISSING_PARAMETER_PASS) | indent(10) }}}
9be3b2
+          {{%- endif %}}
9be3b2
+          </criteria>
9be3b2
+          {{%- endif %}}
9be3b2
+          {{%- if product in products_with_distributed_configuration %}}
9be3b2
+          {{{- oval_line_in_directory_criterion(config_dir, PARAMETER) | indent(8) }}}
9be3b2
+          {{%- endif %}}
9be3b2
+        </criteria>
9be3b2
+      </criteria>
9be3b2
+    </criteria> 
9be3b2
+  </definition>
9be3b2
+  {{{ oval_line_in_file_test(config_path, PARAMETER) | indent (2) }}}
9be3b2
+  {{{ oval_line_in_file_object(config_path, parameter=PARAMETER, ** case_insensitivity_kwargs)| indent (2) }}}
9be3b2
+  {{{ oval_line_in_file_state(VALUE) | indent (2) }}}
9be3b2
+
9be3b2
+  {{%- if MISSING_PARAMETER_PASS %}}
9be3b2
+  {{{ oval_line_in_file_test(config_path, PARAMETER, MISSING_PARAMETER_PASS) | indent(2) }}}
9be3b2
+  {{{ oval_line_in_file_object(config_path, parameter=PARAMETER, missing_parameter_pass=MISSING_PARAMETER_PASS, ** case_insensitivity_kwargs) | indent(2) }}}
9be3b2
+  {{%- endif %}}
9be3b2
+
9be3b2
+  {{%- if product in products_with_distributed_configuration %}}
9be3b2
+  {{{ oval_line_in_directory_test(config_dir, PARAMETER) | indent (2) }}}
9be3b2
+  {{{ oval_line_in_directory_object(config_dir, parameter=PARAMETER, ** case_insensitivity_kwargs) | indent (2) }}}
9be3b2
+  {{{ oval_line_in_directory_state(VALUE) | indent (2) }}}
9be3b2
+
9be3b2
+  {{%- if MISSING_PARAMETER_PASS %}}
9be3b2
+  {{{ oval_line_in_directory_test(config_path, PARAMETER, MISSING_PARAMETER_PASS) | indent(2) }}}
9be3b2
+  {{{ oval_line_in_directory_object(config_path, parameter=PARAMETER, missing_parameter_pass=MISSING_PARAMETER_PASS, ** case_insensitivity_kwargs) | indent(2) }}}
9be3b2
+  {{%- endif %}}
9be3b2
+  {{%- endif %}}
9be3b2
+</def-group>
9be3b2
9be3b2
From b0f86c11fa0fb45b32b53833b5d3565c7eb73cfe Mon Sep 17 00:00:00 2001
9be3b2
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
9be3b2
Date: Fri, 30 Apr 2021 11:52:22 +0200
9be3b2
Subject: [PATCH 2/6] Improved the lineinfile template.
9be3b2
9be3b2
It now escapes the text contents if parts of them could be incorrectly interpreted as regexes.
9be3b2
---
9be3b2
 shared/macros-bash.jinja                  | 2 +-
9be3b2
 shared/templates/lineinfile/oval.template | 2 +-
9be3b2
 2 files changed, 2 insertions(+), 2 deletions(-)
9be3b2
9be3b2
diff --git a/shared/macros-bash.jinja b/shared/macros-bash.jinja
9be3b2
index b4518d83c19..d654a0e0e89 100644
9be3b2
--- a/shared/macros-bash.jinja
9be3b2
+++ b/shared/macros-bash.jinja
9be3b2
@@ -445,7 +445,7 @@ printf '%s\n' "{{{ message | replace('"', '\\"') }}}" >&2
9be3b2
 # prefix_regex: regular expression describing allowed leading characters at each line
9be3b2
 #}}
9be3b2
 {{%- macro set_config_file(path, parameter, value, create, insert_after, insert_before, insensitive=true, separator=" ", separator_regex="\s\+", prefix_regex="^\s*") -%}}
9be3b2
-    {{%- set line_regex = prefix_regex+parameter+separator_regex -%}}
9be3b2
+    {{%- set line_regex = prefix_regex + ((parameter | escape_regex) | replace("/", "\/")) + separator_regex -%}}
9be3b2
     {{%- set new_line = parameter+separator+value -%}}
9be3b2
 if [ -e "{{{ path }}}" ] ; then
9be3b2
     {{{ lineinfile_absent(path, line_regex, insensitive) | indent(4) }}}
9be3b2
diff --git a/shared/templates/lineinfile/oval.template b/shared/templates/lineinfile/oval.template
9be3b2
index a38856d9177..644327b7d6e 100644
9be3b2
--- a/shared/templates/lineinfile/oval.template
9be3b2
+++ b/shared/templates/lineinfile/oval.template
9be3b2
@@ -1,4 +1,4 @@
9be3b2
-{{%- set regex = "^[\s]*" + TEXT + "[\s]*$" -%}}
9be3b2
+{{%- set regex = "^[\s]*" ~ (TEXT | escape_regex) ~ "[\s]*$" -%}}
9be3b2
 <def-group>
9be3b2
   <definition class="compliance" id="{{{ rule_id }}}" version="1">
9be3b2
     {{{ oval_metadata("Check presence of " + TEXT + " in " + PATH) }}}
9be3b2
9be3b2
From 6953f74d1ab168e7ccc3f28877621edff317fef2 Mon Sep 17 00:00:00 2001
9be3b2
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
9be3b2
Date: Fri, 30 Apr 2021 11:54:12 +0200
9be3b2
Subject: [PATCH 3/6] Introduced the sshd_use_directory_configuration rule.
9be3b2
9be3b2
The rule makes sure that the sshd configuration is distributed in the
9be3b2
/etc/ssh/sshd_config.d/ directory, and therefore it makes sense to scan that directory
9be3b2
in another rules.
9be3b2
---
9be3b2
 .../bash/shared.sh                            | 15 ++++++++++
9be3b2
 .../oval/shared.xml                           | 29 +++++++++++++++++++
9be3b2
 .../sshd_use_directory_configuration/rule.yml | 26 +++++++++++++++++
9be3b2
 .../tests/match.fail.sh                       |  4 +++
9be3b2
 .../tests/simple.fail.sh                      |  3 ++
9be3b2
 .../tests/simple.pass.sh                      |  4 +++
9be3b2
 shared/references/cce-redhat-avail.txt        |  1 -
9be3b2
 shared/templates/extra_ovals.yml              |  6 ++++
9be3b2
 8 files changed, 87 insertions(+), 1 deletion(-)
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/oval/shared.xml
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/rule.yml
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/match.fail.sh
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.fail.sh
9be3b2
 create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.pass.sh
9be3b2
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..2ff58ec373c
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
@@ -0,0 +1,15 @@
9be3b2
+# platform = multi_platform_all
9be3b2
+
9be3b2
+{{% set target_file = "/etc/ssh/sshd_config.d/sshd_config_original.conf" -%}}
9be3b2
+if test -f {{{ target_file}}}; then
9be3b2
+	{{{ die("Remediation probably already happened, '" ~ target_file ~ "' already exists, not doing anything.", action="false") }}}
9be3b2
+else
9be3b2
+	mkdir -p /etc/ssh/sshd_config.d
9be3b2
+	mv /etc/ssh/sshd_config {{{ target_file }}}
9be3b2
+cat > /etc/ssh/sshd_config << EOF
9be3b2
+# To modify the system-wide sshd configuration, create a  *.conf  file under
9be3b2
+#  /etc/ssh/sshd_config.d/  which will be automatically included below
9be3b2
+
9be3b2
+Include /etc/ssh/sshd_config.d/*.conf
9be3b2
+EOF
9be3b2
+fi
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/oval/shared.xml b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/oval/shared.xml
9be3b2
new file mode 100644
9be3b2
index 00000000000..0ffb429adff
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/oval/shared.xml
9be3b2
@@ -0,0 +1,29 @@
9be3b2
+{{%- set config_path = "/etc/ssh/sshd_config" %}}
9be3b2
+
9be3b2
+<def-group>
9be3b2
+  <definition class="compliance" id="{{{ rule_id }}}" version="1">
9be3b2
+   {{{ oval_metadata("foo") }}}
9be3b2
+   <criteria comment="sshd is configured correctly or is not installed" operator="OR">
9be3b2
+     <criteria comment="sshd is not installed" operator="AND">
9be3b2
+        
9be3b2
+          definition_ref="sshd_not_required_or_unset" />
9be3b2
+        
9be3b2
+          definition_ref="package_openssh-server_removed" />
9be3b2
+     </criteria>
9be3b2
+     <criteria comment="sshd is installed and configured" operator="AND">
9be3b2
+        
9be3b2
+          definition_ref="sshd_required_or_unset" />
9be3b2
+        
9be3b2
+          definition_ref="package_openssh-server_installed" />
9be3b2
+        <criteria comment="sshd is configured correctly" operator="AND">
9be3b2
+          
9be3b2
+            definition_ref="sshd_includes_config_files" />
9be3b2
+          {{{- oval_line_in_file_criterion(config_path, "match", missing_parameter_pass=true) | indent(8) }}}
9be3b2
+        </criteria>
9be3b2
+      </criteria>
9be3b2
+    </criteria> 
9be3b2
+  </definition>
9be3b2
+  {{{ oval_line_in_file_test(config_path, "match", missing_parameter_pass=true) | indent (2) }}}
9be3b2
+  {{{ oval_line_in_file_object(config_path, parameter="match", missing_parameter_pass=true, prefix_regex="^[ \\t]*(?i)", separator_regex="(?-i)\s+\S+") | indent (2) }}}
9be3b2
+</def-group>
9be3b2
+
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/rule.yml b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/rule.yml
9be3b2
new file mode 100644
9be3b2
index 00000000000..8c370036e61
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/rule.yml
9be3b2
@@ -0,0 +1,26 @@
9be3b2
+documentation_complete: true
9be3b2
+
9be3b2
+prodtype: fedora,rhel9
9be3b2
+
9be3b2
+title: 'Distribute the SSH Server configuration to multiple files in a config directory.'
9be3b2
+
9be3b2
+description: |-
9be3b2
+    Make sure to have the <tt>Include /etc/ssh/sshd_config.d/*.conf</tt> line in the <tt>/etc/ssh/sshd_config</tt> file.
9be3b2
+    Ideally, don't have any active configuration directives in that file, and distribute the service configuration
9be3b2
+    to several files in the <tt>/etc/ssh/sshd_config.d</tt> directory.
9be3b2
+
9be3b2
+rationale: |-
9be3b2
+    This form of distributed configuration is considered as a good practice, and as other sshd rules assume that directives in files in the <tt>/etc/ssh/sshd_config.d</tt> config directory are effective, there has to be a rule that ensures this.
9be3b2
+    Aside from that, having multiple configuration files makes the SSH Server configuration changes easier to partition according to the reason that they were introduced, and therefore it should help to perform merges of hardening updates.
9be3b2
+
9be3b2
+severity: medium
9be3b2
+
9be3b2
+identifiers:
9be3b2
+    cce@rhel9: CCE-87681-3
9be3b2
+
9be3b2
+ocil_clause: "you don't include other configuration files from the main configuration file"
9be3b2
+
9be3b2
+ocil: |-
9be3b2
+    To determine whether the SSH server includes configuration files from the right directory, run the following command:
9be3b2
+    
$ sudo grep -i '^Include' /etc/ssh/sshd_config
9be3b2
+    If a line <tt>Include /etc/ssh/sshd_config.d/*.conf</tt> is returned, then the configuration file inclusion is set correctly.
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/match.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/match.fail.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..fa2ee0654f2
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/match.fail.sh
9be3b2
@@ -0,0 +1,4 @@
9be3b2
+# platform = multi_platform_all
9be3b2
+
9be3b2
+echo "Match something" >> /etc/ssh/sshd_config
9be3b2
+echo "Include /etc/ssh/sshd_config.d/*.conf" >> /etc/ssh/sshd_config
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.fail.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..a6013ad7cfa
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.fail.sh
9be3b2
@@ -0,0 +1,3 @@
9be3b2
+# platform = multi_platform_all
9be3b2
+
9be3b2
+echo "include /etc/ssh/sshd_config.d/.*" > /etc/ssh/sshd_config
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.pass.sh
9be3b2
new file mode 100644
9be3b2
index 00000000000..7a26f521415
9be3b2
--- /dev/null
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/tests/simple.pass.sh
9be3b2
@@ -0,0 +1,4 @@
9be3b2
+# platform = multi_platform_all
9be3b2
+
9be3b2
+# Handling of case-insensitivity of include is tricky
9be3b2
+echo "Include /etc/ssh/sshd_config.d/*.conf" > /etc/ssh/sshd_config
9be3b2
diff --git a/shared/references/cce-redhat-avail.txt b/shared/references/cce-redhat-avail.txt
9be3b2
index 73d025484e6..40a2b9b5868 100644
9be3b2
--- a/shared/references/cce-redhat-avail.txt
9be3b2
+++ b/shared/references/cce-redhat-avail.txt
9be3b2
@@ -1780,7 +1780,6 @@ CCE-87677-1
9be3b2
 CCE-87678-9
9be3b2
 CCE-87679-7
9be3b2
 CCE-87680-5
9be3b2
-CCE-87681-3
9be3b2
 CCE-87682-1
9be3b2
 CCE-87683-9
9be3b2
 CCE-87684-7
9be3b2
diff --git a/shared/templates/extra_ovals.yml b/shared/templates/extra_ovals.yml
9be3b2
index 095d911ee1c..69062ebe541 100644
9be3b2
--- a/shared/templates/extra_ovals.yml
9be3b2
+++ b/shared/templates/extra_ovals.yml
9be3b2
@@ -57,3 +57,9 @@ service_syslog_disabled:
9be3b2
   vars:
9be3b2
     servicename: syslog
9be3b2
     packagename: rsyslog
9be3b2
+
9be3b2
+sshd_includes_config_files:
9be3b2
+  name: lineinfile
9be3b2
+  vars:
9be3b2
+    path: /etc/ssh/sshd_config
9be3b2
+    text: "Include /etc/ssh/sshd_config.d/*.conf"
9be3b2
9be3b2
From d7fcab7ad66e77bb7ccba507e3f024bc892c3864 Mon Sep 17 00:00:00 2001
9be3b2
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
9be3b2
Date: Tue, 11 May 2021 16:06:29 +0200
9be3b2
Subject: [PATCH 4/6] Improved error reporting related to macros.
9be3b2
9be3b2
---
9be3b2
 ssg/jinja.py | 22 +++++++++++++---------
9be3b2
 1 file changed, 13 insertions(+), 9 deletions(-)
9be3b2
9be3b2
diff --git a/ssg/jinja.py b/ssg/jinja.py
9be3b2
index a46246ad0fb..28edd9a6dcd 100644
9be3b2
--- a/ssg/jinja.py
9be3b2
+++ b/ssg/jinja.py
9be3b2
@@ -153,16 +153,20 @@ def load_macros(substitutions_dict=None):
9be3b2
 
9be3b2
     add_python_functions(substitutions_dict)
9be3b2
     try:
9be3b2
-        update_substitutions_dict(JINJA_MACROS_BASE_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_HIGHLEVEL_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_ANSIBLE_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_BASH_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_OVAL_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_IGNITION_DEFINITIONS, substitutions_dict)
9be3b2
-        update_substitutions_dict(JINJA_MACROS_KUBERNETES_DEFINITIONS, substitutions_dict)
9be3b2
+        filenames = [
9be3b2
+            JINJA_MACROS_BASE_DEFINITIONS,
9be3b2
+            JINJA_MACROS_HIGHLEVEL_DEFINITIONS,
9be3b2
+            JINJA_MACROS_ANSIBLE_DEFINITIONS,
9be3b2
+            JINJA_MACROS_BASH_DEFINITIONS,
9be3b2
+            JINJA_MACROS_OVAL_DEFINITIONS,
9be3b2
+            JINJA_MACROS_IGNITION_DEFINITIONS,
9be3b2
+            JINJA_MACROS_KUBERNETES_DEFINITIONS,
9be3b2
+        ]
9be3b2
+        for filename in filenames:
9be3b2
+            update_substitutions_dict(filename, substitutions_dict)
9be3b2
     except Exception as exc:
9be3b2
-        msg = ("Error extracting macro definitions: {0}"
9be3b2
-               .format(str(exc)))
9be3b2
+        msg = ("Error extracting macro definitions from '{1}': {0}"
9be3b2
+               .format(str(exc), filename))
9be3b2
         raise RuntimeError(msg)
9be3b2
 
9be3b2
     return substitutions_dict
9be3b2
9be3b2
From df45c3fa295a2dc5a23cc347657964df6453cbae Mon Sep 17 00:00:00 2001
9be3b2
From: =?UTF-8?q?Mat=C4=9Bj=20T=C3=BD=C4=8D?= <matyc@redhat.com>
9be3b2
Date: Tue, 11 May 2021 16:44:50 +0200
9be3b2
Subject: [PATCH 5/6] Removed devault values that are variables from Jinja
9be3b2
9be3b2
Support in older jinja2 packages is not in a good shape.
9be3b2
---
9be3b2
 shared/macros-oval.jinja | 12 ++++++++----
9be3b2
 1 file changed, 8 insertions(+), 4 deletions(-)
9be3b2
9be3b2
diff --git a/shared/macros-oval.jinja b/shared/macros-oval.jinja
9be3b2
index d38db96d9e3..87e0fd7d87d 100644
9be3b2
--- a/shared/macros-oval.jinja
9be3b2
+++ b/shared/macros-oval.jinja
9be3b2
@@ -92,7 +92,8 @@
9be3b2
     - parameter (String): The parameter to be checked in the configuration file.
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_criterion(path='', parameter='', missing_parameter_pass=false, comment='', id_stem=rule_id) -%}}
9be3b2
+{{%- macro oval_line_in_file_criterion(path='', parameter='', missing_parameter_pass=false, comment='', id_stem='') -%}}
9be3b2
+{{%- set id_stem = id_stem or rule_id -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- set prefix_text = "Check the" -%}}
9be3b2
 {{%- if missing_parameter_pass %}}
9be3b2
@@ -113,7 +114,8 @@
9be3b2
     - parameter (String): The parameter to be checked in the configuration file.
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_test(path='', parameter='', missing_parameter_pass=false, id_stem=rule_id) -%}}
9be3b2
+{{%- macro oval_line_in_file_test(path='', parameter='', missing_parameter_pass=false, id_stem='') -%}}
9be3b2
+{{%- set id_stem = id_stem or rule_id -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- if missing_parameter_pass %}}
9be3b2
 {{%- set check_existence = "none_exist" -%}}
9be3b2
@@ -144,7 +146,8 @@
9be3b2
     - missing_parameter_pass (boolean): If set, the check will also pass if the parameter is not present in the configuration file (default is applied).
9be3b2
     - multi_value (boolean): If set, it means that the parameter can accept multiple values and the expected value must be present in the current list of values.
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_object(path='', section='', prefix_regex='^[ \\t]*', parameter='', separator_regex='[ \\t]+', missing_parameter_pass=false, multi_value=false, filepath_regex='', id_stem=rule_id) -%}}
9be3b2
+{{%- macro oval_line_in_file_object(path='', section='', prefix_regex='^[ \\t]*', parameter='', separator_regex='[ \\t]+', missing_parameter_pass=false, multi_value=false, filepath_regex='', id_stem='') -%}}
9be3b2
+{{%- set id_stem = id_stem or rule_id -%}}
9be3b2
 {{%- set suffix_id = "" -%}}
9be3b2
 {{%- if multi_value -%}}
9be3b2
 {{%- set group_regex = "([^#]*).*$" -%}}
9be3b2
@@ -196,7 +199,8 @@
9be3b2
     - quotes (String): If non-empty, one level of matching quotes is considered when checking the value. Specify one or more quote types as a string.
9be3b2
       For example, for shell quoting, specify quotes="'\""), which will make sure that value, 'value' and "value" are matched, but 'value" or '"value"' won't be.
9be3b2
 #}}
9be3b2
-{{%- macro oval_line_in_file_state(value='', multi_value='', quotes='', id_stem=rule_id) -%}}
9be3b2
+{{%- macro oval_line_in_file_state(value='', multi_value='', quotes='', id_stem='') -%}}
9be3b2
+{{%- set id_stem = id_stem or rule_id -%}}
9be3b2
 {{%- set regex = value -%}}
9be3b2
 {{%- if quotes != "" %}}
9be3b2
 {{%- if "\\1" in value > 0 %}}
9be3b2
9be3b2
From a3ec49f75ac3059d7096985e08e10005db96330a Mon Sep 17 00:00:00 2001
9be3b2
From: Matej Tyc <matyc@redhat.com>
9be3b2
Date: Fri, 30 Jul 2021 17:25:25 +0200
9be3b2
Subject: [PATCH 6/6] Don't remediate when it is inappropriate
9be3b2
9be3b2
Don't remediate when the config file already contains the include
9be3b2
directive.
9be3b2
---
9be3b2
 .../sshd_use_directory_configuration/bash/shared.sh        | 7 +++++--
9be3b2
 1 file changed, 5 insertions(+), 2 deletions(-)
9be3b2
9be3b2
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
index 2ff58ec373c..9317b23992d 100644
9be3b2
--- a/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_directory_configuration/bash/shared.sh
9be3b2
@@ -1,12 +1,15 @@
9be3b2
 # platform = multi_platform_all
9be3b2
 
9be3b2
 {{% set target_file = "/etc/ssh/sshd_config.d/sshd_config_original.conf" -%}}
9be3b2
+{{% set base_config = "/etc/ssh/sshd_config" -%}}
9be3b2
 if test -f {{{ target_file}}}; then
9be3b2
 	{{{ die("Remediation probably already happened, '" ~ target_file ~ "' already exists, not doing anything.", action="false") }}}
9be3b2
+elif grep -Eq '^\s*Include\s+/etc/ssh/sshd_config\.d/\*\.conf' {{{ base_config }}} && ! grep -Eq '^\s*Match\s' {{{ base_config }}}; then
9be3b2
+	{{{ die("Remediation probably already happened, '" ~ base_config ~ "' already contains the include directive.", action="false") }}}
9be3b2
 else
9be3b2
 	mkdir -p /etc/ssh/sshd_config.d
9be3b2
-	mv /etc/ssh/sshd_config {{{ target_file }}}
9be3b2
-cat > /etc/ssh/sshd_config << EOF
9be3b2
+	mv {{{ base_config }}} {{{ target_file }}}
9be3b2
+cat > {{{ base_config }}} << EOF
9be3b2
 # To modify the system-wide sshd configuration, create a  *.conf  file under
9be3b2
 #  /etc/ssh/sshd_config.d/  which will be automatically included below
9be3b2