diff options
| -rw-r--r-- | data/templates/ssh/sshd_config.j2 | 14 | ||||
| -rw-r--r-- | interface-definitions/service_ssh.xml.in | 19 | ||||
| -rwxr-xr-x | python/vyos/template.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_service_ssh.py | 17 |
4 files changed, 51 insertions, 1 deletions
diff --git a/data/templates/ssh/sshd_config.j2 b/data/templates/ssh/sshd_config.j2 index d5d155340..32f7e23e7 100644 --- a/data/templates/ssh/sshd_config.j2 +++ b/data/templates/ssh/sshd_config.j2 @@ -72,6 +72,20 @@ HostKeyAlgorithms {{ hostkey_algorithm | join(',') }} PubkeyAcceptedAlgorithms {{ pubkey_accepted_algorithm | join(',') }} {% endif %} +{% if fido is vyos_defined %} +{% set configured_pubkey_options = [] %} +{% if fido.pin_required is vyos_defined %} +{% do configured_pubkey_options.append('verify-required') %} +{% endif %} +{% if fido.touch_required is vyos_defined %} +{% do configured_pubkey_options.append('touch-required') %} +{% endif %} +{% if configured_pubkey_options | length > 0 %} +# Sets one or more public key authentication options. +PubkeyAuthOptions {{ configured_pubkey_options | join(' ') }} +{% endif %} +{% endif %} + {% if mac is vyos_defined %} # Specifies the available MAC (message authentication code) algorithms MACs {{ mac | join(',') }} diff --git a/interface-definitions/service_ssh.xml.in b/interface-definitions/service_ssh.xml.in index 9fd9e32c3..7a1348404 100644 --- a/interface-definitions/service_ssh.xml.in +++ b/interface-definitions/service_ssh.xml.in @@ -61,6 +61,25 @@ <valueless/> </properties> </leafNode> + <node name="fido"> + <properties> + <help>FIDO2 SSH options</help> + </properties> + <children> + <leafNode name="pin-required"> + <properties> + <help>Require FIDO2 keys to attest that a user has been verified (e.g. via a PIN)</help> + <valueless/> + </properties> + </leafNode> + <leafNode name="touch-required"> + <properties> + <help>Require FIDO2 keys to attest that a user is physically present</help> + <valueless/> + </properties> + </leafNode> + </children> + </node> <node name="dynamic-protection"> <properties> <help>Allow dynamic protection</help> diff --git a/python/vyos/template.py b/python/vyos/template.py index 6b3e329a3..596f9e8c5 100755 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -55,7 +55,7 @@ def _get_environment(location=None): loader=loc_loader, trim_blocks=True, undefined=ChainableUndefined, - extensions=['jinja2.ext.loopcontrols'] + extensions=['jinja2.ext.loopcontrols', 'jinja2.ext.do'] ) env.filters.update(_FILTERS) env.tests.update(_TESTS) diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py index 8cd4a2178..72f828093 100755 --- a/smoketest/scripts/cli/test_service_ssh.py +++ b/smoketest/scripts/cli/test_service_ssh.py @@ -494,5 +494,22 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase): self.assertNotIn('none', authorize_principals_file_config) self.assertFalse(os.path.exists(f'/home/{test_user}/.ssh/authorized_principals')) + def test_ssh_fido(self): + # Order does matter for this test because of how the template + # collects and maps the options. + opt_map = { + 'pin-required': 'verify-required', + 'touch-required': 'touch-required', + } + expected = 'PubkeyAuthOptions ' + for k, v in opt_map.items(): + self.cli_set(base_path + ['fido', k]) + expected = f'{expected}{v} ' + expected = expected[:-1] + self.cli_commit() + tmp_sshd_conf = read_file(SSHD_CONF) + self.assertIn(expected, tmp_sshd_conf) + + if __name__ == '__main__': unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on()) |
