From 07d403e568c2d459d44236217bebac5623087875 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 07:53:15 +0200
Subject: [PATCH 1/9] Make sure oval checks and remediations cover the case
where default sshd config is in /usr subdir
Add macros for ansible, bash and oval to check and set sshd config parameters for case where config can be both in /usr and /etc
---
shared/macros/10-ansible.jinja | 117 ++++++++++++++++++++++++++
shared/macros/10-bash.jinja | 50 +++++++++++
shared/macros/10-oval.jinja | 147 +++++++++++++++++++++++++++++++++
3 files changed, 314 insertions(+)
diff --git a/shared/macros/10-ansible.jinja b/shared/macros/10-ansible.jinja
index fe432b975fc5..7347a88c6775 100644
--- a/shared/macros/10-ansible.jinja
+++ b/shared/macros/10-ansible.jinja
@@ -2387,3 +2387,120 @@ lines will be inserted at the beginning of the profile.
ansible.builtin.command: dconf update
when: dconf_user_profile_blockinfile is changed
{{%- endmacro -%}}
+
+
+{{#
+
+ Set a sshd configuration parameter to a value for system with /usr - located default config
+
+:parameter msg: Message to be set as Task Title, if not set the rule's title will be used instead
+:type msg: str
+:parameter parameter: Parameter to set
+:type parameter: str
+:parameter value: The value to set
+:type value: str
+:param copy_defaults: If true default sshd configuration in /usr/etc/ssh/sshd_config will be
+copied onto /etc/ssh/sshd_config, if /etc/ssh/sshd_config does not exist
+:type copy_defaults: bool
+:parameter config_basename: drop-in filename of sshd configuration file
+:type config_basename: str
+
+#}}
+{{%- macro ansible_sshd_set_usr(msg='', parameter='', value='', copy_defaults=true, config_basename="00-complianceascode-hardening.conf", rule_title=None) %}}
+{{%- set sshd_config_path = "/etc/ssh/sshd_config" %}}
+{{%- set sshd_usr_config_path = "/usr/etc/ssh/sshd_config" %}}
+{{%- set sshd_config_dir = "/etc/ssh/sshd_config.d" -%}}
+{{%- set sshd_usr_config_dir = "/usr/etc/ssh/sshd_config.d" -%}}
+{{%- set ssh_paths = ['/etc/ssh/sshd_config.d', '/usr/etc/ssh/sshd_config.d'] -%}}
+{{%- set config_file = "/etc/ssh/sshd_config.d/" ~ config_basename -%}}
+{{%- set new_line = parameter + ' ' + value -%}}
+{{%- set line_regex = "(?i)^\s*" + "{{ \"" + parameter + "\"| regex_escape }}" + "\s+" -%}}
+{{%- set dir_parameter = "sshd_config_d_has_parameter" -%}}
+{{%- set lineinfile_items = "{{ " + dir_parameter + ".files }}" -%}}
+
+- name: Copy default {{{ sshd_usr_config_path }}} to {{{ sshd_config_path }}}
+ ansible.builtin.copy:
+ src: {{{ sshd_usr_config_path }}}
+ dest: {{{ sshd_config_path }}}
+ force: no
+ mode: '0600'
+- name: {{{ rule_title }}} - Check if the parameter {{{ parameter }}} is configured in sshd configuration(s)
+ ansible.builtin.find:
+ paths:
+ - '/etc/ssh'
+ - '/usr/etc/ssh'
+ - {{{ sshd_config_dir }}}
+ - {{{ sshd_usr_config_dir }}}
+ contains: {{{ line_regex }}}
+ patterns:
+ - '*.conf'
+ - 'sshd_config'
+ register: _sshd_config_has_parameter
+- name: {{{ rule_title }}} - Check if the parameter {{{ parameter }}} is configured correctly in sshd configuration(s)
+ ansible.builtin.find:
+ paths:
+ - '/etc/ssh'
+ - '/usr/etc/ssh'
+ - {{{ sshd_config_dir }}}
+ - {{{ sshd_usr_config_dir }}}
+ contains: {{{ line_regex ~ value ~ "$" }}}
+ patterns:
+ - '*.conf'
+ - 'sshd_config'
+ register: _sshd_config_correctly
+- name: '{{{ msg or rule_title }}}'
+ block:
+ {{{ ansible_lineinfile(
+ "Deduplicate values from " + sshd_config_path,
+ sshd_config_path,
+ regex=line_regex,
+ insensitive='false',
+ create='no',
+ state='absent')|indent }}}
+ {{{ ansible_lineinfile(
+ "Deduplicate values from " + sshd_usr_config_path,
+ sshd_usr_config_path,
+ regex=line_regex,
+ insensitive='false',
+ create='no',
+ state='absent')|indent }}}
+ - name: "Check if the parameter {{{ parameter }}} is present in {{{ sshd_config_dir }}} and in {{{ sshd_usr_config_dir }}}"
+ ansible.builtin.find:
+ paths: {{{ ssh_paths }}}
+ recurse: 'yes'
+ follow: 'no'
+ contains: '(?i)^\s*{{ "{{{ parameter }}}"| regex_escape }}\s+'
+ register: {{{ dir_parameter }}}
+ {{{ ansible_lineinfile(
+ "Remove parameter from files in " + sshd_config_dir,
+ path="{{ item.path }}",
+ regex=line_regex,
+ state="absent",
+ with_items=lineinfile_items)|indent}}}
+ {{{ ansible_lineinfile(
+ "Remove parameter from files in " + sshd_usr_config_dir,
+ path="{{ item.path }}",
+ regex=line_regex,
+ state="absent",
+ with_items=lineinfile_items)|indent }}}
+ {{{ ansible_lineinfile(
+ "Insert correct line to " + config_file,
+ config_file,
+ regex=line_regex,
+ insensitive='false',
+ new_line=new_line,
+ create='yes',
+ state='present',
+ validate='/usr/sbin/sshd -t -f %s',
+ insert_after='',
+ insert_before="BOF" )|indent }}}
+ when: _sshd_config_correctly.matched == 0 or _sshd_config_has_parameter.matched != 1
+
+- name: {{{ rule_title }}} - set file mode for {{{ config_file }}}
+ ansible.builtin.file:
+ path: {{{ config_file }}}
+ mode: '0600'
+ state: touch
+ modification_time: preserve
+ access_time: preserve
+{{%- endmacro %}}
diff --git a/shared/macros/10-bash.jinja b/shared/macros/10-bash.jinja
index 8bcd4bec988c..9d8a759e3b01 100644
--- a/shared/macros/10-bash.jinja
+++ b/shared/macros/10-bash.jinja
@@ -2748,3 +2748,53 @@ This macro creates a Bash conditional which checks the system architecture in /p
{{%- macro bash_arch_conditional(arch) -%}}
( grep -sqE "^.*\.{{{ arch }}}$" /proc/sys/kernel/osrelease || grep -sqE "^{{{ arch }}}$" /proc/sys/kernel/arch; )
{{%- endmacro -%}}
+
+
+{{#
+ Set a sshd configuration parameter to a value for system with default configuration in /usr subdir
+
+:parameter parameter: Parameter to set
+:type parameter: str
+:parameter value: The value to set
+:type value: str
+:param copy_defaults: If true default sshd configuration in /usr/etc/ssh/sshd_config will be
+copied onto /etc/ssh/sshd_config, if /etc/ssh/sshd_config does not exist
+:type copy_defaults: bool
+:parameter config_basename: drop-in filename of sshd configuration file
+:type config_basename: str
+
+#}}
+{{% macro bash_sshd_remediation_usr(parameter, value, copy_defaults="true", config_basename="00-complianceascode-hardening.conf", rule_id=None) -%}}
+{{%- set sshd_config_path = "/etc/ssh/sshd_config" %}}
+{{%- set sshd_config_dir = "/etc/ssh/sshd_config.d" -%}}
+{{%- set sshd_usr_config_path = "/usr/etc/ssh/sshd_config" %}}
+{{%- set sshd_usr_config_dir = "/usr/etc/ssh/sshd_config.d" -%}}
+{{%- set prefix_regex = "^\s*" -%}}
+{{%- set separator_regex = "\s\+" -%}}
+{{%- set hardening_config_basename = config_basename %}}
+{{%- set line_regex = prefix_regex ~ parameter ~ separator_regex %}}
+
+if ! [ -e "{{{ sshd_config_path }}}" ] ; then
+ cp "{{{ sshd_usr_config_path }}}" "{{{ sshd_config_path }}}"
+fi
+
+mkdir -p {{{ sshd_config_dir }}}
+touch {{{ sshd_config_dir }}}/{{{ hardening_config_basename }}}
+chmod 0600 {{{ sshd_config_dir }}}/{{{ hardening_config_basename }}}
+{{{ lineinfile_absent(sshd_config_path, line_regex, insensitive=true, rule_id=rule_id) }}}
+{{{ lineinfile_absent_in_directory(sshd_config_dir, line_regex, insensitive=true, filename_glob="*.conf") }}}
+{{{ lineinfile_absent(sshd_usr_config_path, line_regex, insensitive=true, rule_id=rule_id) }}}
+{{{ lineinfile_absent_in_directory(sshd_usr_config_dir, line_regex, insensitive=true, filename_glob="*.conf") }}}
+{{{ set_config_file(
+ path=sshd_config_dir ~ "/" ~ hardening_config_basename,
+ parameter=parameter,
+ value=value,
+ create=true,
+ insert_after="",
+ insert_before="BOF",
+ insensitive=true,
+ separator=" ",
+ separator_regex=separator_regex,
+ prefix_regex=prefix_regex, rule_id=rule_id)
+ }}}
+{{%- endmacro %}}
diff --git a/shared/macros/10-oval.jinja b/shared/macros/10-oval.jinja
index 6466728189db..a755d21e0593 100644
--- a/shared/macros/10-oval.jinja
+++ b/shared/macros/10-oval.jinja
@@ -1878,3 +1878,150 @@ Macro generates an OVAL test definition to verify that a specified audit tool is
{{%- endmacro -%}}
+
+
+{{#
+ Create a full OVAL check for an sshd parameter and value in /etc/ssh/sshd_config or /usr/etc/ssh/sshd_config.
+ Including /etc/ssh/sshd_config.d/*.conf and /usr/etc/ssh/sshd_config.d/*.conf (default on SUSE Linux Enterprise Server 16)
+
+:param parameter: Parameter to check
+:type parameter: str
+:param value: Value to check
+:type value: str
+:param missing_parameter_pass: If true, the check will pass if the parameter missing.
+:type missing_parameter_pass: bool
+:param xccdf_variable: the name of an XCCDF variable carrying the value, this conflicts with the value parameter
+:type xccdf_variable: str
+:param datatype: a data type of the value
+:type datatype: str
+
+#}}
+{{%- macro sshd_oval_check_usr(parameter, value, missing_parameter_pass, xccdf_variable="", datatype="", rule_id=None, rule_title=None) -%}}
+{{%- set sshd_config_path = "/etc/ssh/sshd_config" %}}
+{{%- set sshd_usr_config_path = "/usr/etc/ssh/sshd_config" -%}}
+{{%- set sshd_config_dir = "/etc/ssh/sshd_config.d" -%}}
+{{%- set sshd_usr_config_dir = "/usr/etc/ssh/sshd_config.d" -%}}
+{{%- if xccdf_variable -%}}
+{{%- set description = "Ensure '" ~ parameter ~ "' is configured with value configured in " ~ xccdf_variable ~ " variable in " ~ sshd_config_path %}}
+{{%- else -%}}
+{{%- set description = "Ensure '" ~ parameter ~ "' is configured with value '" ~ value ~ "' in " ~ sshd_config_path -%}}
+{{%- endif -%}}
+{{%- set description = description ~ " or in " ~ sshd_config_dir -%}}
+{{%- set description = description ~ " or in " ~ sshd_usr_config_path -%}}
+{{%- set description = description ~ " or in " ~ sshd_usr_config_dir -%}}
+{{%- set case_insensitivity_kwargs = dict(prefix_regex="^[ \\t]*(?i)", separator_regex = "(?-i)[ \\t]+") -%}}
+
+
+
+ {{{ oval_metadata(description, rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{{ oval_line_in_file_criterion(sshd_config_path, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(12)}}}
+ {{{ oval_line_in_directory_criterion(sshd_config_dir, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(12) }}}
+ {{{ oval_line_in_file_criterion(sshd_usr_config_dir, parameter, id_stem=rule_id ~ "_sshd_usr_config_dir") | indent(12) }}}
+
+ {{%- if not missing_parameter_pass -%}}
+
+ {{%- endif -%}}
+
+
+
+
+
+
+
+
+
+
+ {{{ oval_line_in_file_criterion(sshd_usr_config_path, parameter, avoid_conflicting=true, id_stem=rule_id ~ "_sshd_usr_config_path") | indent(12)}}}
+ {{{ oval_line_in_directory_criterion(sshd_config_dir, parameter, avoid_conflicting=true, rule_id=rule_id) | indent(12) }}}
+ {{{ oval_line_in_file_criterion(sshd_usr_config_dir, parameter, id_stem=rule_id ~ "_sshd_usr_config_dir") | indent(12) }}}
+
+ {{%- if not missing_parameter_pass -%}}
+
+ {{%- endif -%}}
+
+
+
+
+
+
+ {{{ oval_config_file_exists_test(sshd_config_path, rule_id=rule_id) }}}
+ {{{ oval_config_file_exists_object(sshd_config_path, rule_id=rule_id) }}}
+
+ {{{ oval_line_in_file_test(sshd_config_path, parameter, avoid_conflicting=true, rule_id=rule_id) | indent (2) }}}
+ {{{ oval_line_in_file_object(sshd_config_path, parameter=parameter, rule_id=rule_id, ** case_insensitivity_kwargs)| indent (2) }}}
+
+ {{{ oval_line_in_directory_test(sshd_config_dir, parameter, avoid_conflicting=true, rule_id=rule_id) | indent (2) }}}
+ {{{ oval_line_in_directory_object(sshd_config_dir, parameter=parameter, rule_id=rule_id, ** case_insensitivity_kwargs) | indent (2) }}}
+ {{%- if xccdf_variable -%}}
+ {{{ oval_line_in_file_define_variable(xccdf_variable, datatype) }}}
+ {{{ oval_line_in_file_state_xccdf_variable(xccdf_variable, datatype=datatype, rule_id=rule_id) }}}
+ {{{ oval_line_in_directory_state_xccdf_variable(xccdf_variable, datatype, rule_id=rule_id) | indent (2) }}}
+ {{{ oval_line_in_file_state_xccdf_variable(var_name=xccdf_variable, datatype=datatype, id_stem=rule_id ~ "_sshd_usr_config_path") | indent (2) }}}
+ {{{ oval_line_in_file_state_xccdf_variable(var_name=xccdf_variable, datatype=datatype, id_stem=rule_id ~ "_sshd_usr_config_dir") | indent (2) }}}
+ {{%- else -%}}
+ {{{ oval_line_in_file_state(value, rule_id=rule_id) | indent (2) }}}
+ {{{ oval_line_in_directory_state(value, rule_id=rule_id) | indent (2) }}}
+ {{{ oval_line_in_file_state(value, id_stem=rule_id ~ "_sshd_usr_config_path") | indent (2) }}}
+ {{{ oval_line_in_file_state(value, id_stem=rule_id ~ "_sshd_usr_config_dir") | indent (2) }}}
+ {{%- endif -%}}
+
+ {{{ oval_line_in_file_test(sshd_usr_config_path, parameter, avoid_conflicting=true, id_stem=rule_id ~ "_sshd_usr_config_path") | indent (2) }}}
+ {{{ oval_line_in_file_object(sshd_usr_config_path, parameter=parameter, id_stem=rule_id ~ "_sshd_usr_config_path", ** case_insensitivity_kwargs)| indent (2) }}}
+ {{{ oval_line_in_file_test(sshd_usr_config_dir, parameter, avoid_conflicting=true, id_stem=rule_id ~ "_sshd_usr_config_dir") | indent (2) }}}
+ {{{ oval_line_in_file_object(sshd_usr_config_dir, parameter=parameter, filename_regex=".*\.conf$", id_stem=rule_id ~ "_sshd_usr_config_dir", ** case_insensitivity_kwargs) | indent (2) }}}
+
+ {{%- if not missing_parameter_pass -%}}
+
+
+
+ obj_{{{ rule_id }}}
+ obj_{{{ rule_id }}}_config_dir
+
+
+ obj_{{{ rule_id }}}_sshd_usr_config_dir
+
+
+
+
+
+
+
+
+
+
+
+ obj_{{{ rule_id }}}_config_dir
+
+
+ obj_{{{ rule_id }}}_sshd_usr_config_path
+ obj_{{{ rule_id }}}_sshd_usr_config_dir
+
+
+
+
+
+
+
+ {{%- endif -%}}
+
+{{%- endmacro -%}}
From d094607042fa5635d41f5828622ed88b05bb7593 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 07:57:04 +0200
Subject: [PATCH 2/9] Use the new macros in sshd lineinfile context
---
.../sshd_lineinfile/ansible.template | 53 +++++++++++++-----
.../templates/sshd_lineinfile/bash.template | 18 +++++--
.../templates/sshd_lineinfile/oval.template | 54 +++++++++++++++++--
.../templates/sshd_lineinfile/tests/common.sh | 9 +++-
.../tests/correct_value_directory.pass.sh | 3 +-
.../correct_value_usr_config_dir.pass.sh | 9 ++++
.../correct_value_usr_config_path.pass.sh | 13 +++++
.../tests/duplicated_param.pass.sh | 9 ++--
.../tests/duplicated_param_directory.pass.sh | 11 ++--
.../tests/line_not_there.fail.sh | 5 ++
.../tests/param_conflict_directory.fail.sh | 2 +-
...param_conflict_file_with_directory.fail.sh | 2 +-
.../tests/wrong_value_directory.fail.sh | 2 +-
.../tests/wrong_value_usr_config_dir.fail.sh | 14 +++++
.../tests/wrong_value_usr_config_path.fail.sh | 16 ++++++
15 files changed, 185 insertions(+), 35 deletions(-)
create mode 100644 shared/templates/sshd_lineinfile/tests/correct_value_usr_config_dir.pass.sh
create mode 100644 shared/templates/sshd_lineinfile/tests/correct_value_usr_config_path.pass.sh
create mode 100644 shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_dir.fail.sh
create mode 100644 shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_path.fail.sh
diff --git a/shared/templates/sshd_lineinfile/ansible.template b/shared/templates/sshd_lineinfile/ansible.template
index a5a1f2302d7b..0739450cdf24 100644
--- a/shared/templates/sshd_lineinfile/ansible.template
+++ b/shared/templates/sshd_lineinfile/ansible.template
@@ -6,19 +6,44 @@
{{% if XCCDF_VARIABLE %}}
{{{ ansible_instantiate_variables(XCCDF_VARIABLE) }}}
-{{{
- ansible_sshd_set(
- parameter=PARAMETER,
- value="{{ "+XCCDF_VARIABLE+" }}",
- config_is_distributed=sshd_distributed_config,
- config_basename=CONFIG_BASENAME, rule_title=rule_title)
-}}}
+ {{%- if product == 'sle16' -%}}
+ {{{
+ ansible_sshd_set_usr(
+ parameter=PARAMETER,
+ value="{{ "+XCCDF_VARIABLE+" }}",
+ copy_defaults='true',
+ config_basename=CONFIG_BASENAME,
+ rule_title=rule_title
+ )
+ }}}
+ {{%- else -%}}
+ {{{
+ ansible_sshd_set(
+ parameter=PARAMETER,
+ value="{{ "+XCCDF_VARIABLE+" }}",
+ config_is_distributed=sshd_distributed_config,
+ config_basename=CONFIG_BASENAME, rule_title=rule_title)
+ }}}
+ {{%- endif -%}}
{{% else %}}
-{{{
- ansible_sshd_set(
- parameter=PARAMETER,
- value=VALUE,
- config_is_distributed=sshd_distributed_config,
- config_basename=CONFIG_BASENAME, rule_title=rule_title)
-}}}
+ {{%- if product == 'sle16' -%}}
+ {{{
+ ansible_sshd_set_usr(
+ parameter=PARAMETER,
+ value=VALUE,
+ copy_defaults='true',
+ config_basename=CONFIG_BASENAME,
+ rule_title=rule_title
+ )
+ }}}
+ {{%- else -%}}
+ {{{
+ ansible_sshd_set(
+ parameter=PARAMETER,
+ value=VALUE,
+ config_is_distributed=sshd_distributed_config,
+ config_basename=CONFIG_BASENAME, rule_title=rule_title)
+ }}}
+ {{%- endif -%}}
+
{{% endif %}}
diff --git a/shared/templates/sshd_lineinfile/bash.template b/shared/templates/sshd_lineinfile/bash.template
index aec5c2029a3a..4bec19d82f43 100644
--- a/shared/templates/sshd_lineinfile/bash.template
+++ b/shared/templates/sshd_lineinfile/bash.template
@@ -5,8 +5,16 @@
# disruption = low
{{% if XCCDF_VARIABLE %}}
-{{{ bash_instantiate_variables(XCCDF_VARIABLE) }}}
-{{{ bash_sshd_remediation(parameter=PARAMETER, value="$" ~ XCCDF_VARIABLE, config_is_distributed=sshd_distributed_config, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
-{{% else %}}
-{{{ bash_sshd_remediation(parameter=PARAMETER, value=VALUE, config_is_distributed=sshd_distributed_config, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
-{{% endif %}}
+ {{{- bash_instantiate_variables(XCCDF_VARIABLE) -}}}
+ {{%- if product == 'sle16' -%}}
+ {{{- bash_sshd_remediation_usr(parameter=PARAMETER, value="$" ~ XCCDF_VARIABLE, copy_defaults=true, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
+ {{%- else -%}}
+ {{{- bash_sshd_remediation(parameter=PARAMETER, value="$" ~ XCCDF_VARIABLE, config_is_distributed=sshd_distributed_config, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
+ {{%- endif -%}}
+{{%- else -%}}
+ {{%- if product == 'sle16' -%}}
+ {{{- bash_sshd_remediation_usr(parameter=PARAMETER, value=VALUE, copy_defaults=true, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
+ {{%- else -%}}
+ {{{- bash_sshd_remediation(parameter=PARAMETER, value=VALUE, config_is_distributed=sshd_distributed_config, config_basename=CONFIG_BASENAME, rule_id=rule_id) -}}}
+ {{%- endif -%}}
+{{%- endif -%}}
diff --git a/shared/templates/sshd_lineinfile/oval.template b/shared/templates/sshd_lineinfile/oval.template
index d3f4218ec300..20e9534ff10f 100644
--- a/shared/templates/sshd_lineinfile/oval.template
+++ b/shared/templates/sshd_lineinfile/oval.template
@@ -1,5 +1,53 @@
-{{%- if XCCDF_VARIABLE -%}}
-{{{ 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) }}}
+{{%- if product == 'sle16' -%}}
+ {{%- if XCCDF_VARIABLE -%}}
+ {{{
+ sshd_oval_check_usr(
+ parameter=PARAMETER,
+ xccdf_variable=XCCDF_VARIABLE,
+ missing_parameter_pass=MISSING_PARAMETER_PASS,
+ datatype=DATATYPE,
+ rule_id=rule_id,
+ rule_title=rule_title
+ )
+ }}}
+ {{%- else -%}}
+ {{{
+ sshd_oval_check_usr(
+ parameter=PARAMETER,
+ value=VALUE,
+ missing_parameter_pass=MISSING_PARAMETER_PASS,
+ datatype=DATATYPE,
+ rule_id=rule_id,
+ rule_title=rule_title
+ )
+ }}}
+ {{%- endif -%}}
{{%- else -%}}
-{{{ 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) }}}
+ {{%- if XCCDF_VARIABLE -%}}
+ {{{
+ 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
+ )
+ }}}
+ {{%- else -%}}
+ {{{
+ 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
+ )
+ }}}
+ {{%- endif -%}}
{{%- endif -%}}
diff --git a/shared/templates/sshd_lineinfile/tests/common.sh b/shared/templates/sshd_lineinfile/tests/common.sh
index 2f811821fde2..23d7937088af 100644
--- a/shared/templates/sshd_lineinfile/tests/common.sh
+++ b/shared/templates/sshd_lineinfile/tests/common.sh
@@ -3,8 +3,13 @@
mkdir -p /etc/ssh/sshd_config.d
touch /etc/ssh/sshd_config.d/nothing
-if grep -q "^\s*{{{ PARAMETER }}}" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* ; then
- sed -i "s/^{{{ PARAMETER }}}.*/# {{{ PARAMETER }}} {{{ CORRECT_VALUE }}}/g" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config" /etc/ssh/sshd_config.d/*)
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/*)
+{{% endif %}}
+
+if grep -q "^\s*{{{ PARAMETER }}}" "${SSHD_PATHS[@]}" ; then
+ sed -i "s/^{{{ PARAMETER }}}.*/# {{{ PARAMETER }}} {{{ CORRECT_VALUE }}}/g" "${SSHD_PATHS[@]}"
else
echo "# {{{ PARAMETER }}} {{{ CORRECT_VALUE }}}" >> /etc/ssh/sshd_config
fi
diff --git a/shared/templates/sshd_lineinfile/tests/correct_value_directory.pass.sh b/shared/templates/sshd_lineinfile/tests/correct_value_directory.pass.sh
index 3114b75fe541..c0926871f3a3 100644
--- a/shared/templates/sshd_lineinfile/tests/correct_value_directory.pass.sh
+++ b/shared/templates/sshd_lineinfile/tests/correct_value_directory.pass.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# platform = multi_platform_fedora,Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_ubuntu
+# platform = Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 10,Red Hat Enterprise Linux 9,SUSE Linux Enterprise 16,multi_platform_fedora,multi_platform_ubuntu
{{%- if XCCDF_VARIABLE %}}
# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
{{%- endif %}}
@@ -12,4 +12,3 @@ source common.sh
{{% endif %}}
{{{ bash_sshd_remediation(parameter=PARAMETER, value=CORRECT_VALUE, config_is_distributed=sshd_distributed_config, rule_id=rule_id) -}}}
-
diff --git a/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_dir.pass.sh b/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_dir.pass.sh
new file mode 100644
index 000000000000..b853676b0552
--- /dev/null
+++ b/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_dir.pass.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source common.sh
+
+{{%- if XCCDF_VARIABLE %}}
+# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
+{{%- endif %}}
+
+echo "{{{ PARAMETER }}} {{{ CORRECT_VALUE }}}" >> /usr/etc/ssh/sshd_config.d/oscap-sshd-config.conf
diff --git a/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_path.pass.sh b/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_path.pass.sh
new file mode 100644
index 000000000000..b5dfae159dac
--- /dev/null
+++ b/shared/templates/sshd_lineinfile/tests/correct_value_usr_config_path.pass.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source common.sh
+
+{{%- if XCCDF_VARIABLE %}}
+# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
+{{%- endif %}}
+
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+
+echo "{{{ PARAMETER }}} {{{ CORRECT_VALUE }}}" >> /usr/etc/ssh/sshd_config
diff --git a/shared/templates/sshd_lineinfile/tests/duplicated_param.pass.sh b/shared/templates/sshd_lineinfile/tests/duplicated_param.pass.sh
index aac35afbcad6..8d3d7be24f18 100644
--- a/shared/templates/sshd_lineinfile/tests/duplicated_param.pass.sh
+++ b/shared/templates/sshd_lineinfile/tests/duplicated_param.pass.sh
@@ -1,12 +1,15 @@
#!/bin/bash
-
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config" /etc/ssh/sshd_config.d/*)
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/*)
+{{% endif %}}
mkdir -p /etc/ssh/sshd_config.d
touch /etc/ssh/sshd_config.d/nothing
-if grep -q "^\s*{{{ PARAMETER }}}" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* ; then
- sed -i "/^\s*{{{ PARAMETER }}}.*/Id" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
+if grep -q "^\s*{{{ PARAMETER }}}" "${SSHD_PATHS[@]}" ; then
+ sed -i "/^\s*{{{ PARAMETER }}}.*/Id" "${SSHD_PATHS[@]}"
fi
{{% if XCCDF_VARIABLE %}}
diff --git a/shared/templates/sshd_lineinfile/tests/duplicated_param_directory.pass.sh b/shared/templates/sshd_lineinfile/tests/duplicated_param_directory.pass.sh
index b05adb222229..1b94be25b086 100644
--- a/shared/templates/sshd_lineinfile/tests/duplicated_param_directory.pass.sh
+++ b/shared/templates/sshd_lineinfile/tests/duplicated_param_directory.pass.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# platform = multi_platform_fedora,Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_ubuntu
+# platform = Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 10,Red Hat Enterprise Linux 9,SUSE Linux Enterprise 16,multi_platform_fedora,multi_platform_ubuntu
mkdir -p /etc/ssh/sshd_config.d
touch /etc/ssh/sshd_config.d/nothing
@@ -9,8 +9,13 @@ touch /etc/ssh/sshd_config.d/nothing
{{{ bash_replace_or_append("/etc/ssh/sshd_config", "Include", "/etc/ssh/sshd_config.d/*.conf", "%s %s", cce_identifiers=cce_identifiers) }}}
{{% endif %}}
-if grep -q "^\s*{{{ PARAMETER }}}" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* ; then
- sed -i "/^\s*{{{ PARAMETER }}}.*/Id" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config" /etc/ssh/sshd_config.d/*)
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/*)
+{{% endif %}}
+
+if grep -q "^\s*{{{ PARAMETER }}}" "${SSHD_PATHS[@]}" ; then
+ sed -i "/^\s*{{{ PARAMETER }}}.*/Id" "${SSHD_PATHS[@]}"
fi
{{% if XCCDF_VARIABLE %}}
diff --git a/shared/templates/sshd_lineinfile/tests/line_not_there.fail.sh b/shared/templates/sshd_lineinfile/tests/line_not_there.fail.sh
index 5bc6d1043169..da6e5e46e494 100644
--- a/shared/templates/sshd_lineinfile/tests/line_not_there.fail.sh
+++ b/shared/templates/sshd_lineinfile/tests/line_not_there.fail.sh
@@ -5,4 +5,9 @@ SSHD_PARAM={{{ PARAMETER }}}
mkdir -p /etc/ssh/sshd_config.d
touch /etc/ssh/sshd_config.d/nothing
+{{% if product == 'sle16' %}}
+touch /etc/ssh/sshd_config
+sed -i "/^\s*${SSHD_PARAM}.*/Id" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* /usr/etc/ssh/sshd_config /usr/etc/ssh/sshd_config.d/*
+{{% else %}}
sed -i "/^\s*${SSHD_PARAM}.*/Id" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*
+{{% endif %}}
diff --git a/shared/templates/sshd_lineinfile/tests/param_conflict_directory.fail.sh b/shared/templates/sshd_lineinfile/tests/param_conflict_directory.fail.sh
index d91244f7a08a..73ed7000227b 100644
--- a/shared/templates/sshd_lineinfile/tests/param_conflict_directory.fail.sh
+++ b/shared/templates/sshd_lineinfile/tests/param_conflict_directory.fail.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# platform = multi_platform_fedora,Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_ubuntu
+# platform = Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 10,Red Hat Enterprise Linux 9,SUSE Linux Enterprise 16,multi_platform_fedora,multi_platform_ubuntu
{{% if XCCDF_VARIABLE %}}
diff --git a/shared/templates/sshd_lineinfile/tests/param_conflict_file_with_directory.fail.sh b/shared/templates/sshd_lineinfile/tests/param_conflict_file_with_directory.fail.sh
index 15eb1d87033b..530ffdc2fb14 100644
--- a/shared/templates/sshd_lineinfile/tests/param_conflict_file_with_directory.fail.sh
+++ b/shared/templates/sshd_lineinfile/tests/param_conflict_file_with_directory.fail.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# platform = multi_platform_fedora,Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_ubuntu
+# platform = Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 10,Red Hat Enterprise Linux 9,SUSE Linux Enterprise 16,multi_platform_fedora,multi_platform_ubuntu
{{% if XCCDF_VARIABLE %}}
# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
diff --git a/shared/templates/sshd_lineinfile/tests/wrong_value_directory.fail.sh b/shared/templates/sshd_lineinfile/tests/wrong_value_directory.fail.sh
index c5f2c41e875a..c9bf477b34ca 100644
--- a/shared/templates/sshd_lineinfile/tests/wrong_value_directory.fail.sh
+++ b/shared/templates/sshd_lineinfile/tests/wrong_value_directory.fail.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# platform = multi_platform_fedora,Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_ubuntu
+# platform = Oracle Linux 8,Oracle Linux 9,Red Hat Enterprise Linux 10,Red Hat Enterprise Linux 9,SUSE Linux Enterprise 16,multi_platform_fedora,multi_platform_ubuntu
{{% if XCCDF_VARIABLE %}}
# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
diff --git a/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_dir.fail.sh b/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_dir.fail.sh
new file mode 100644
index 000000000000..a073ad1c0991
--- /dev/null
+++ b/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_dir.fail.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+
+{{% if XCCDF_VARIABLE %}}
+# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
+{{% endif %}}
+
+touch /usr/etc/ssh/sshd_config.d/oscap-sshd-config.conf
+
+if grep -q "^\s*{{{ PARAMETER }}}" /usr/etc/ssh/sshd_config /usr/etc/ssh/sshd_config.d/* ; then
+ sed -i "/^\s*{{{ PARAMETER }}}.*/Id" /usr/etc/ssh/sshd_config /usr/etc/ssh/sshd_config.d/*
+fi
+
+echo "{{{ PARAMETER }}} {{{ WRONG_VALUE }}}" > /usr/etc/ssh/sshd_config.d/oscap-sshd-config.conf
diff --git a/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_path.fail.sh b/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_path.fail.sh
new file mode 100644
index 000000000000..0ff115b7e45e
--- /dev/null
+++ b/shared/templates/sshd_lineinfile/tests/wrong_value_usr_config_path.fail.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+
+{{% if XCCDF_VARIABLE %}}
+# variables = {{{ XCCDF_VARIABLE }}}={{{ CORRECT_VALUE }}}
+{{% endif %}}
+
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+
+if grep -q "^\s*{{{ PARAMETER }}}" /usr/etc/ssh/sshd_config /usr/etc/ssh/sshd_config.d/* ; then
+ sed -i "/^\s*{{{ PARAMETER }}}.*/Id" /usr/etc/ssh/sshd_config /usr/etc/ssh/sshd_config.d/*
+fi
+
+echo "{{{ PARAMETER }}} {{{ WRONG_VALUE }}}" >> /usr/etc/ssh/sshd_config
From 5d65b420049525dd1cb8b849713625758116bad2 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 07:59:10 +0200
Subject: [PATCH 3/9] Use the new macros in sshd_use_strong_kex rule
---
.../sshd_use_strong_kex/ansible/shared.yml | 20 +-
.../sshd_use_strong_kex/bash/shared.sh | 21 ++-
.../sshd_use_strong_kex/oval/sle16.xml | 171 ++++++++++++++++++
...rect_value_etc_sshd_config_drop_in.pass.sh | 7 +
...lue_in_usr_etc_sshd_config_present.fail.sh | 7 +
.../correct_value_usr_etc_sshd_config.pass.sh | 7 +
..._value_usr_etc_sshd_config_drop_in.pass.sh | 6 +
.../sshd_use_strong_kex/tests/include.sh | 15 ++
...rong_value_etc_sshd_config_drop_in.fail.sh | 6 +
.../wrong_value_usr_etc_sshd_config.fail.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.fail.sh | 6 +
11 files changed, 269 insertions(+), 3 deletions(-)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/include.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/ansible/shared.yml b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/ansible/shared.yml
index fc2a78f3d79c..82b732e0e66b 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/ansible/shared.yml
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/ansible/shared.yml
@@ -6,4 +6,22 @@
{{{ ansible_instantiate_variables("sshd_strong_kex") }}}
-{{{ ansible_sshd_set(parameter="KexAlgorithms", value="{{ sshd_strong_kex }}", config_is_distributed=sshd_distributed_config, rule_title=rule_title) }}}
+{{%- if product == 'sle16' -%}}
+ {{{
+ ansible_sshd_set_usr(
+ parameter="KexAlgorithms",
+ value="{{ sshd_strong_kex }}",
+ copy_defaults='true',
+ rule_title=rule_title
+ )
+ }}}
+{{%- else -%}}
+ {{{
+ ansible_sshd_set(
+ parameter="KexAlgorithms",
+ value="{{ sshd_strong_kex }}",
+ config_is_distributed=sshd_distributed_config,
+ rule_title=rule_title
+ )
+ }}}
+{{%- endif -%}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/bash/shared.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/bash/shared.sh
index e5a56dbfc6ec..de205aedd670 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/bash/shared.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/bash/shared.sh
@@ -5,5 +5,22 @@
# disruption = low
{{{ bash_instantiate_variables("sshd_strong_kex") }}}
-{{{ bash_sshd_remediation(parameter="KexAlgorithms", value="$sshd_strong_kex", config_is_distributed=sshd_distributed_config, rule_id=rule_id) }}}
-
+{{%- if product == 'sle16' -%}}
+ {{{
+ bash_sshd_remediation_usr(
+ parameter="KexAlgorithms",
+ value="$sshd_strong_kex",
+ copy_defaults=true,
+ rule_id=rule_id
+ )
+ }}}
+{{%- else -%}}
+ {{{
+ bash_sshd_remediation(
+ parameter="KexAlgorithms",
+ value="$sshd_strong_kex",
+ config_is_distributed=sshd_distributed_config,
+ rule_id=rule_id
+ )
+ }}}
+{{%- endif -%}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/oval/sle16.xml
new file mode 100644
index 000000000000..d6c8fb2432cf
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/oval/sle16.xml
@@ -0,0 +1,171 @@
+
+
+ {{{ oval_metadata("Limit the Key Exchange Algorithms to those which are FIPS-approved.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+ var_sshd_config_kex
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config
+ ^[\s]*(?i)KexAlgorithms(?-i)[\s]+([\w,-@]+)+[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ var_sshd_config_kex_usr
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config
+ ^[\s]*(?i)KexAlgorithms(?-i)[\s]+([\w,-@]+)+[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+ var_sshd_config_kex_config_dir
+
+
+
+
+
+
+
+ ^(/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ .*\.conf$
+ ^[\s]*(?i)KexAlgorithms(?-i)[\s]+([\w,-@]+)+[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ obj_sshd_config_kex
+ obj_sshd_config_kex_config_dir
+
+
+
+
+
+
+
+
+
+ obj_sshd_config_kex_usr
+ obj_sshd_config_kex_config_dir
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..7a794f42a4b1
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+
+source include.sh
+
+echo "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
new file mode 100644
index 000000000000..9c44448054f2
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+source include.sh
+
+touch /etc/ssh/sshd_config
+echo "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config.pass.sh
new file mode 100644
index 000000000000..0577aad9bd14
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config.pass.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+
+source include.sh
+
+echo "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..ab24bed01ba1
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+source include.sh
+
+echo "KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/include.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/include.sh
new file mode 100644
index 000000000000..179b7b36e808
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/include.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^KexAlgorithms.*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..a1a7b95bafff
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+source include.sh
+
+echo "KexAlgorithms diffie-hellman-group-exchange-sha1" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config.fail.sh
new file mode 100644
index 000000000000..df52b52f680d
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+source include.sh
+
+echo "KexAlgorithms diffie-hellman-group-exchange-sha1" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..2a71c2a3bd53
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_use_strong_kex/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_strong_kex=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256
+source include.sh
+
+echo "KexAlgorithms diffie-hellman-group-exchange-sha1" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
From 0258f34e38e2c2e3e3c57d00e632066d1f917326 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:02:20 +0200
Subject: [PATCH 4/9] For sle16 enhance the check and the tests to cover cases
with sshd_config in /usr and subfolders
---
.../sshd_limit_user_access/oval/sle16.xml | 100 ++++++++++++++++++
.../tests/allow_groups.pass.sh | 2 +-
...low_groups_etc_ssh_sshd_config_dir.pass.sh | 4 +
.../tests/allow_users.pass.sh | 2 +-
.../tests/allow_users_groups.pass.sh | 2 +-
...llow_users_usr_etc_ssh_sshd_config.pass.sh | 5 +
.../sshd_limit_user_access/tests/common.sh | 15 +++
.../deny_group_in_usr_etc_missing.fail.sh | 7 ++
.../tests/deny_groups.pass.sh | 2 +-
.../tests/deny_users.pass.sh | 2 +-
.../tests/deny_users_groups.pass.sh | 2 +-
..._users_usr_etc_ssh_sshd_config_dir.pass.sh | 5 +
.../tests/empty_groups.fail.sh | 2 +-
.../tests/empty_users.fail.sh | 2 +-
.../tests/no_entry.fail.sh | 2 +-
15 files changed, 145 insertions(+), 9 deletions(-)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups_etc_ssh_sshd_config_dir.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_usr_etc_ssh_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/common.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_group_in_usr_etc_missing.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_usr_etc_ssh_sshd_config_dir.pass.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/oval/sle16.xml
new file mode 100644
index 000000000000..8dce53384a11
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/oval/sle16.xml
@@ -0,0 +1,100 @@
+{{% macro test_sshd_lineinfile(filepath, param, id) %}}
+{{%- set object_id = filepath | replace("/", "_") | replace("-", "_") | replace(".", "_") -%}}
+
+
+
+
+ ^{{{ filepath }}}
+ (?i)^[ ]*{{{ param }}}[ ]+((?:[^ \n]+[ ]*)+)$
+ 1
+
+{{% endmacro %}}
+
+{{% macro test_sshd_lineindir(filepath, param, id) %}}
+{{%- set object_id = filepath | replace("/", "_") | replace("-", "_") | replace(".", "_") -%}}
+
+
+
+
+ {{{ filepath }}}
+ .*\.conf$
+ (?i)^[ ]*{{{ param }}}[ ]+((?:[^ \n]+[ ]*)+)$
+ 1
+
+{{% endmacro %}}
+
+
+
+ {{{ oval_metadata("One of the following parameters of the sshd configuration file is set: AllowUsers, DenyUsers, AllowGroups, DenyGroups.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+ {{{ test_sshd_lineinfile("/etc/ssh/sshd_config", "AllowUsers", "test_allow_user_is_configured_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/etc/ssh/sshd_config", "AllowGroups", "test_allow_groups_is_configured_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/etc/ssh/sshd_config", "DenyUsers", "test_deny_users_is_configured_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/etc/ssh/sshd_config", "DenyGroups", "test_deny_groups_is_configured_etc_ssh_sshdconfig") }}}
+
+ {{{ test_sshd_lineinfile("/usr/etc/ssh/sshd_config", "AllowUsers", "test_allow_user_is_configured_usr_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/usr/etc/ssh/sshd_config", "AllowGroups", "test_allow_groups_is_configured_usr_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/usr/etc/ssh/sshd_config", "DenyUsers", "test_deny_users_is_configured_usr_etc_ssh_sshdconfig") }}}
+ {{{ test_sshd_lineinfile("/usr/etc/ssh/sshd_config", "DenyGroups", "test_deny_groups_is_configured_usr_etc_ssh_sshdconfig") }}}
+
+ {{{ test_sshd_lineindir("/etc/ssh/sshd_config.d", "AllowUsers", "test_allow_user_is_configured_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/etc/ssh/sshd_config.d", "AllowGroups", "test_allow_groups_is_configured_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/etc/ssh/sshd_config.d", "DenyUsers", "test_deny_users_is_configured_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/etc/ssh/sshd_config.d", "DenyGroups", "test_deny_groups_is_configured_etc_ssh_sshdconfig_dir") }}}
+
+ {{{ test_sshd_lineindir("/usr/etc/ssh/sshd_config.d", "AllowUsers", "test_allow_user_is_configured_usr_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/usr/etc/ssh/sshd_config.d", "AllowGroups", "test_allow_groups_is_configured_usr_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/usr/etc/ssh/sshd_config.d", "DenyUsers", "test_deny_users_is_configured_usr_etc_ssh_sshdconfig_dir") }}}
+ {{{ test_sshd_lineindir("/usr/etc/ssh/sshd_config.d", "DenyGroups", "test_deny_groups_is_configured_usr_etc_ssh_sshdconfig_dir") }}}
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups.pass.sh
index 4a5255dc3c9f..0794a24e80a7 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups.pass.sh
@@ -1,4 +1,4 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "AllowGroups testgroup1 testgroup2 testgroup3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups_etc_ssh_sshd_config_dir.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups_etc_ssh_sshd_config_dir.pass.sh
new file mode 100644
index 000000000000..2f5b763698b1
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_groups_etc_ssh_sshd_config_dir.pass.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source common.sh
+echo "AllowGroups group" >> /etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users.pass.sh
index 9bde6d56cd92..520d0a048faa 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users.pass.sh
@@ -1,4 +1,4 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "AllowUsers testuser1 testuser2 testuser3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_groups.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_groups.pass.sh
index 0b35e7039585..6d6bd04f37b6 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_groups.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_groups.pass.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "AllowUsers testuser1 testuser2 testuser3" >> /etc/ssh/sshd_config
echo "AllowGroups testgroup1 testgroup2 testgroup3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_usr_etc_ssh_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_usr_etc_ssh_sshd_config.pass.sh
new file mode 100644
index 000000000000..04b090c1a148
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/allow_users_usr_etc_ssh_sshd_config.pass.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source common.sh
+
+echo "AllowUsers testuser1 testuser2 testuser3" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/common.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/common.sh
new file mode 100644
index 000000000000..3c936c2321ce
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/common.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^(Allow|Deny)(Users|Groups).*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_group_in_usr_etc_missing.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_group_in_usr_etc_missing.fail.sh
new file mode 100644
index 000000000000..6d23da947c9d
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_group_in_usr_etc_missing.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# remediation = none
+# platform = SUSE Linux Enterprise 16
+source common.sh
+
+touch /etc/ssh/sshd_config
+echo "DenyGroups testgroup" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_groups.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_groups.pass.sh
index a324d89e397d..16f6e9d3d58f 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_groups.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_groups.pass.sh
@@ -1,4 +1,4 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "DenyGroups testgroup1 testgroup2 testgroup3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users.pass.sh
index 35c7f65d7514..adb157baddd2 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users.pass.sh
@@ -1,4 +1,4 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "DenyUsers testuser1 testuser2 testuser3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_groups.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_groups.pass.sh
index fc55098614a0..ebe08fb81dea 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_groups.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_groups.pass.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "DenyUsers testuser1 testuser2 testuser3" >> /etc/ssh/sshd_config
echo "DenyGroups testgroup1 testgroup2 testgroup3" >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_usr_etc_ssh_sshd_config_dir.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_usr_etc_ssh_sshd_config_dir.pass.sh
new file mode 100644
index 000000000000..bee5f9991a7c
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/deny_users_usr_etc_ssh_sshd_config_dir.pass.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source common.sh
+
+echo "DenyUsers user" >> /usr/etc/ssh/sshd_config.d/01-complianceascode-reinforce-os-defaults.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_groups.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_groups.fail.sh
index 2f735305d2c5..1f6c11f7a4d1 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_groups.fail.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_groups.fail.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# remediation = none
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "AllowGroups " >> /etc/ssh/sshd_config
echo "DenyGroups " >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_users.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_users.fail.sh
index 4affe4b4d598..55ea7d01cde3 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_users.fail.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/empty_users.fail.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# remediation = none
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
echo "AllowUsers " >> /etc/ssh/sshd_config
echo "DenyUsers " >> /etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/no_entry.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/no_entry.fail.sh
index bc8a67e7fbad..8ab213a16a18 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/no_entry.fail.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_limit_user_access/tests/no_entry.fail.sh
@@ -1,4 +1,4 @@
#!/bin/bash
# remediation = none
-find /etc/ssh/sshd_config* -type f -print0 | xargs -0 sed -i '/^(Allow|Deny)(Users|Groups).*/d'
+source common.sh
From 4e938f74b8afb37879c54fc39ab2bccdfbb6e4b6 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:04:26 +0200
Subject: [PATCH 5/9] For sle16 enhance the check to cover cases with
sshd_config in /usr and subfolders for sshd_set_idle_timeout rule
---
.../sshd_set_idle_timeout/oval/sle16.xml | 153 ++++++++++++++++++
1 file changed, 153 insertions(+)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_idle_timeout/oval/sle16.xml
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_idle_timeout/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_set_idle_timeout/oval/sle16.xml
new file mode 100644
index 000000000000..9c2ae2f9a78a
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_idle_timeout/oval/sle16.xml
@@ -0,0 +1,153 @@
+
+
+ {{{ oval_metadata("The SSH idle timeout interval should be set to an appropriate value.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config
+ ^[\s]*(?i)ClientAliveInterval[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config
+ ^[\s]*(?i)ClientAliveInterval[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)ClientAliveInterval[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)ClientAliveInterval[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ object_sshd_idle_timeout_etc
+
+
+ object_sshd_idle_timeout_config_dir
+ object_sshd_idle_timeout_usr_config_dir
+
+
+
+
+
+
+
+
+
+
+
+ object_sshd_idle_timeout_usr
+
+
+ object_sshd_idle_timeout_config_dir
+ object_sshd_idle_timeout_usr_config_dir
+
+
+
+
+
+
+
From 5aedfa62ddff7f6a175ee39f885ad66435255493 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:05:10 +0200
Subject: [PATCH 6/9] For sle16 enhance the check to cover cases with
sshd_config in /usr and subfolders for sshd_set_login_grace_time rule
---
.../sshd_set_login_grace_time/oval/sle16.xml | 153 ++++++++++++++++++
...rect_value_etc_sshd_config_drop_in.pass.sh | 5 +
...lue_in_usr_etc_sshd_config_present.fail.sh | 6 +
.../correct_value_usr_etc_sshd_config.pass.sh | 5 +
..._value_usr_etc_sshd_config_drop_in.pass.sh | 5 +
.../tests/include.sh | 15 ++
.../tests/lower_bound.pass.sh | 2 +-
.../tests/no_limit.fail.sh | 2 +-
.../tests/too_high.fail.sh | 2 +-
.../too_high_etc_sshd_config_drop_in.fail.sh | 5 +
.../too_high_usr_etc_sshd_config.fail.sh | 5 +
...o_high_usr_etc_sshd_config_drop_in.fail.sh | 5 +
12 files changed, 207 insertions(+), 3 deletions(-)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/include.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_etc_sshd_config_drop_in.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config_drop_in.fail.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/oval/sle16.xml
new file mode 100644
index 000000000000..23137efd78b8
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/oval/sle16.xml
@@ -0,0 +1,153 @@
+
+
+ {{{ oval_metadata("The SSH number seconds for login grace time should be set to an appropriate value.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config
+ ^[\s]*(?i)LoginGraceTime[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config
+ ^[\s]*(?i)LoginGraceTime[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)LoginGraceTime[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)LoginGraceTime[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ object_sshd_login_grace_time_etc
+
+
+ object_sshd_login_grace_time_config_dir
+ object_sshd_login_grace_time_usr_config_dir
+
+
+
+
+
+
+
+
+
+
+
+ object_sshd_login_grace_time_usr
+
+
+ object_sshd_login_grace_time_config_dir
+ object_sshd_login_grace_time_usr_config_dir
+
+
+
+
+
+
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..a0f68b4a5ccb
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 60" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
new file mode 100644
index 000000000000..b80e3832b591
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+touch /etc/ssh/sshd_config
+echo "LoginGraceTime 1" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config.pass.sh
new file mode 100644
index 000000000000..3ed15582de0b
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config.pass.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 1" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..1e72b109d85e
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 60" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/include.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/include.sh
new file mode 100644
index 000000000000..aee5eb2d0bec
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/include.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^LoginGraceTime.*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/lower_bound.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/lower_bound.pass.sh
index f5236501ca01..809d3c1f4659 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/lower_bound.pass.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/lower_bound.pass.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# profiles = xccdf_org.ssgproject.content_profile_cis
+# profiles = xccdf_org.ssgproject.content_profile_cis,xccdf_org.ssgproject.content_profile_pci-dss-4
# platform = multi_platform_all
SSHD_CONFIG="/etc/ssh/sshd_config"
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/no_limit.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/no_limit.fail.sh
index 63a0aee97f7d..738969589112 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/no_limit.fail.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/no_limit.fail.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# profiles = xccdf_org.ssgproject.content_profile_cis
+# profiles = xccdf_org.ssgproject.content_profile_cis,xccdf_org.ssgproject.content_profile_pci-dss-4
# platform = multi_platform_all
SSHD_CONFIG="/etc/ssh/sshd_config"
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high.fail.sh
index 6d109091b8b9..959f7d699345 100644
--- a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high.fail.sh
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high.fail.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-# profiles = xccdf_org.ssgproject.content_profile_cis
+# profiles = xccdf_org.ssgproject.content_profile_cis,xccdf_org.ssgproject.content_profile_pci-dss-4
# platform = multi_platform_all
SSHD_CONFIG="/etc/ssh/sshd_config"
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..35ea7b48f5f4
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 61" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config.fail.sh
new file mode 100644
index 000000000000..7010af0181bd
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config.fail.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 61" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..1cdd63bb777a
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_login_grace_time/tests/too_high_usr_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+source include.sh
+
+echo "LoginGraceTime 61" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
From 676a554cbe9d8f3ab575f28105946540a89e5d15 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:05:48 +0200
Subject: [PATCH 7/9] For sle16 enhance the check to cover cases with
sshd_config in /usr and subfolders for sshd_set_max_auth_tries rule
---
.../sshd_set_max_auth_tries/oval/sle16.xml | 153 ++++++++++++++++++
...rect_value_etc_sshd_config_drop_in.pass.sh | 6 +
...lue_in_usr_etc_sshd_config_present.fail.sh | 7 +
.../correct_value_usr_etc_sshd_config.pass.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.pass.sh | 6 +
.../sshd_set_max_auth_tries/tests/include.sh | 15 ++
...rong_value_etc_sshd_config_drop_in.fail.sh | 6 +
.../wrong_value_usr_etc_sshd_config.fail.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.fail.sh | 6 +
9 files changed, 211 insertions(+)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/include.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/oval/sle16.xml
new file mode 100644
index 000000000000..a9452bfb71aa
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/oval/sle16.xml
@@ -0,0 +1,153 @@
+
+
+ {{{ oval_metadata("The SSH MaxAuthTries should be set to an appropriate value.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config
+ ^[\s]*(?i)MaxAuthTries[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config
+ ^[\s]*(?i)MaxAuthTries[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)MaxAuthTries[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)MaxAuthTries[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ object_sshd_max_auth_tries_etc
+
+
+ object_sshd_max_auth_tries_config_dir
+ object_sshd_max_auth_tries_usr_config_dir
+
+
+
+
+
+
+
+
+
+
+
+ object_sshd_max_auth_tries_usr
+
+
+ object_sshd_max_auth_tries_config_dir
+ object_sshd_max_auth_tries_usr_config_dir
+
+
+
+
+
+
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..4262a6713622
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 4" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
new file mode 100644
index 000000000000..7b327ed220ce
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+touch /etc/ssh/sshd_config
+echo "MaxAuthTries 4" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config.pass.sh
new file mode 100644
index 000000000000..d902aa806c16
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 4" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..0c0ad79ef4fe
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 4" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/include.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/include.sh
new file mode 100644
index 000000000000..9790bbcd68d0
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/include.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^MaxAuthTries.*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..41136d9eb40b
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 20" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config.fail.sh
new file mode 100644
index 000000000000..218e4deb2407
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 5" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..753e15c14404
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_auth_tries/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = sshd_max_auth_tries_value=4
+source include.sh
+
+echo "MaxAuthTries 0" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
From 5de048fc42cf8406ecc5b97c891db4b846ed4519 Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:06:35 +0200
Subject: [PATCH 8/9] For sle16 enhance the check to cover cases with
sshd_config in /usr and subfolders for sshd_set_max_sessions rule
---
.../sshd_set_max_sessions/oval/sle16.xml | 153 ++++++++++++++++++
...rect_value_etc_sshd_config_drop_in.pass.sh | 6 +
...lue_in_usr_etc_sshd_config_present.fail.sh | 7 +
.../correct_value_usr_etc_sshd_config.pass.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.pass.sh | 6 +
.../sshd_set_max_sessions/tests/include.sh | 15 ++
...rong_value_etc_sshd_config_drop_in.fail.sh | 6 +
.../wrong_value_usr_etc_sshd_config.fail.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.fail.sh | 6 +
9 files changed, 211 insertions(+)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/include.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/oval/sle16.xml
new file mode 100644
index 000000000000..3acd7b75327d
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/oval/sle16.xml
@@ -0,0 +1,153 @@
+
+
+ {{{ oval_metadata("The SSH MaxSessions should be set to an appropriate value.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config
+ ^[\s]*(?i)MaxSessions[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config
+ ^[\s]*(?i)MaxSessions[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)MaxSessions[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+
+
+ /usr/etc/ssh/sshd_config.d
+ .*\.conf$
+ ^[\s]*(?i)MaxSessions[\s]+(\d+)[\s]*(?:#.*)?$
+ 1
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+ object_sshd_max_session_etc
+
+
+ object_sshd_max_session_config_dir
+ object_sshd_max_session_usr_config_dir
+
+
+
+
+
+
+
+
+
+
+
+ object_sshd_max_session_usr
+
+
+ object_sshd_max_session_config_dir
+ object_sshd_max_session_usr_config_dir
+
+
+
+
+
+
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..7fdb6123803b
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 4" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
new file mode 100644
index 000000000000..7f19908dcaea
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+touch /etc/ssh/sshd_config
+echo "MaxSessions 4" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config.pass.sh
new file mode 100644
index 000000000000..180bd49bed98
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 4" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..622d36446727
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 4" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/include.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/include.sh
new file mode 100644
index 000000000000..4c8d058295d8
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/include.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^MaxSessions.*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..606d55099420
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 20" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config.fail.sh
new file mode 100644
index 000000000000..fe6f5a820988
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 5" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..0c07b9608d42
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_max_sessions/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_max_sessions=4
+source include.sh
+
+echo "MaxSessions 10" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
From 8f0e0ed0693492e6d249ebf6f00c607f7a33d87b Mon Sep 17 00:00:00 2001
From: teacup-on-rockingchair
<315160+teacup-on-rockingchair@users.noreply.github.com>
Date: Thu, 26 Feb 2026 08:07:03 +0200
Subject: [PATCH 9/9] For sle16 enhance the check to cover cases with
sshd_config in /usr and subfolders for sshd_set_maxstartups rule
---
.../sshd_set_maxstartups/oval/sle16.xml | 151 ++++++++++++++++++
...rect_value_etc_sshd_config_drop_in.pass.sh | 6 +
...lue_in_usr_etc_sshd_config_present.fail.sh | 7 +
.../correct_value_usr_etc_sshd_config.pass.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.pass.sh | 6 +
.../sshd_set_maxstartups/tests/include.sh | 15 ++
...rong_value_etc_sshd_config_drop_in.fail.sh | 6 +
.../wrong_value_usr_etc_sshd_config.fail.sh | 6 +
..._value_usr_etc_sshd_config_drop_in.fail.sh | 6 +
9 files changed, 209 insertions(+)
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/oval/sle16.xml
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/include.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config.fail.sh
create mode 100644 linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/oval/sle16.xml b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/oval/sle16.xml
new file mode 100644
index 000000000000..5ca10680c2a8
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/oval/sle16.xml
@@ -0,0 +1,151 @@
+
+
+ {{{ oval_metadata("Ensure 'MaxStartups' is properly configured in SSH configuration files.", rule_title=rule_title) }}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^/etc/ssh/sshd_config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^(/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+(\d+):\d+:\d+\s*$
+ 1
+
+
+ ^(/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+\d+:(\d+):\d+\s*$
+ 1
+
+
+ ^(/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+\d+:\d+:(\d+)\s*$
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ^(/usr/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+(\d+):\d+:\d+\s*$
+ 1
+
+
+ ^(/usr/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+\d+:(\d+):\d+\s*$
+ 1
+
+
+ ^(/usr/etc/ssh|/etc/ssh/sshd_config.d|/usr/etc/ssh/sshd_config.d)
+ (sshd_config|.*\.conf)$
+ (?i)^\s*MaxStartups\s+\d+:\d+:(\d+)\s*$
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..fc6371be73be
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 10:30:60" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
new file mode 100644
index 000000000000..6905e07c838e
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_in_usr_etc_sshd_config_present.fail.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+touch /etc/ssh/sshd_config
+echo "MaxStartups 10:30:60" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config.pass.sh
new file mode 100644
index 000000000000..0a93fe6e32ec
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 10:30:60" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
new file mode 100644
index 000000000000..d2835b507b40
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/correct_value_usr_etc_sshd_config_drop_in.pass.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 10:30:60" >> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/include.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/include.sh
new file mode 100644
index 000000000000..1f5b69d60b54
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/include.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+declare -a SSHD_PATHS=("/etc/ssh/sshd_config")
+{{% if product == 'sle16' %}}
+SSHD_PATHS+=("/usr/etc/ssh/sshd_config" /usr/etc/ssh/sshd_config.d/* /etc/ssh/sshd_config.d/*)
+{{% endif %}}
+# clean up configurations
+sed -i '/^MaxStartups.*/d' "${SSHD_PATHS[@]}"
+
+# restore to defaults for sle16
+{{% if product == 'sle16' %}}
+if [ -e "/etc/ssh/sshd_config" ] ; then
+ rm /etc/ssh/sshd_config
+fi
+{{% endif %}}
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..39d6dae3afc2
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 10:30:61" >> /etc/ssh/sshd_config.d/01-complianceascode.conf
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config.fail.sh
new file mode 100644
index 000000000000..9bfce7c33062
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 10:29:60" >> /usr/etc/ssh/sshd_config
diff --git a/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
new file mode 100644
index 000000000000..a0781811a3a3
--- /dev/null
+++ b/linux_os/guide/services/ssh/ssh_server/sshd_set_maxstartups/tests/wrong_value_usr_etc_sshd_config_drop_in.fail.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# platform = SUSE Linux Enterprise 16
+# variables = var_sshd_set_maxstartups=10:30:60
+source include.sh
+
+echo "MaxStartups 11:30:60">> /usr/etc/ssh/sshd_config.d/01-complianceascode.conf