From f599b80cd9a56fc443328a90d7d0356309ef6600 Mon Sep 17 00:00:00 2001 From: "Brad House (nexthop)" Date: Thu, 10 Apr 2025 13:04:13 -0400 Subject: [PATCH 1/2] SSH hardening configuration options The SSH configuration does not contain many of the hardening requirements by the various standards bodies. This adds support for: * password_authentication - ability to disable password auth * permit_root_login - ability to prevent root logins * ciphers - ability to specify available ciphers * kex_algorithms - ability to specify key exchange algorithms * macs - ability to specify macs Signed-off-by: Brad House --- src/sonic-yang-models/doc/Configuration.md | 12 +++- .../tests/files/sample_config_db.json | 7 +- .../yang_model_tests/tests/ssh-server.json | 20 ++++++ .../tests_config/ssh-server.json | 54 +++++++++++++++- .../yang-models/sonic-ssh-server.yang | 64 +++++++++++++++++++ 5 files changed, 154 insertions(+), 3 deletions(-) diff --git a/src/sonic-yang-models/doc/Configuration.md b/src/sonic-yang-models/doc/Configuration.md index 1d2479221e97..0a1ee9bb9ca7 100644 --- a/src/sonic-yang-models/doc/Configuration.md +++ b/src/sonic-yang-models/doc/Configuration.md @@ -3055,6 +3055,11 @@ In this table, we allow configuring ssh server global settings. This will featur - ports - Ssh port numbers - string of port numbers seperated by ',' - inactivity_timeout - Inactivity timeout for SSH session, allowed values: 0-35000 (min), default value: 15 (min) - max_sessions - Max number of concurrent logins, allowed values: 0-100 (where 0 means no limit), default value: 0 +- permit_root_login - Whether or not to allow root login. Boolean. +- password_authentication - Whether or not to allow password authentication. Boolean. +- ciphers - Ciphers to allow. See `ssh -Q ciphers` +- kex_algorithms - Key Exchange algorithms to allow. See `ssh -Q kex_algorithms` +- macs - MAC algorithms to allow. See `ssh -Q macs` ``` { "SSH_SERVER": { @@ -3063,7 +3068,12 @@ In this table, we allow configuring ssh server global settings. This will featur "login_timeout": "120", "ports": "22", "inactivity_timeout": "15", - "max_sessions": "0" + "max_sessions": "0", + "permit_root_login": "false", + "password_authentication": "true", + "ciphers": [ "chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com" ], + "kex_algorithms": [ "sntrup761x25519-sha512", "curve25519-sha256", "ecdh-sha2-nistp521" ], + "macs": [ "hmac-sha2-512-etm@openssh.com", "hmac-sha2-512" ] } } } diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 4157ad0dd01b..632580cb8126 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -2702,7 +2702,12 @@ "login_timeout": "120", "ports": "22", "inactivity_timeout": "15", - "max_sessions": "0" + "max_sessions": "0", + "permit_root_login": "false", + "password_authentication": "true", + "ciphers": [ "chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com" ], + "kex_algorithms": [ "sntrup761x25519-sha512", "curve25519-sha256", "ecdh-sha2-nistp521" ], + "macs": [ "hmac-sha2-512-etm@openssh.com", "hmac-sha2-512" ] } }, diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json b/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json index b67c7b66edb2..76c756f1ffb3 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json @@ -28,5 +28,25 @@ "SSH_SERVER_INVALID_MAX_SESSIONS": { "desc": "Configure invalid max_sessions value in SSH_SERVER.", "eStrKey": "Range" + }, + "SSH_SERVER_INVALID_PERMIT_ROOT_LOGIN": { + "desc": "Configure invalid permit_root_login value in SSH_SERVER.", + "eStrKey": "InvalidValue" + }, + "SSH_SERVER_INVALID_PASSWORD_AUTHENTICATION": { + "desc": "Configure invalid password_authentication value in SSH_SERVER.", + "eStrKey": "InvalidValue" + }, + "SSH_SERVER_INVALID_CIPHERS": { + "desc": "Configure invalid ciphers value in SSH_SERVER.", + "eStrKey": "InvalidValue" + }, + "SSH_SERVER_INVALID_KEX_ALGORITHMS": { + "desc": "Configure invalid kex_algorithms value in SSH_SERVER.", + "eStrKey": "InvalidValue" + }, + "SSH_SERVER_INVALID_MACS": { + "desc": "Configure invalid macs value in SSH_SERVER.", + "eStrKey": "InvalidValue" } } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json index 1780bab89582..76f9060965b3 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json @@ -5,7 +5,14 @@ "POLICIES":{ "authentication_retries": "6", "login_timeout": "120", - "ports": "22" + "ports": "22", + "inactivity_timeout": "15", + "max_sessions": "0", + "permit_root_login": "false", + "password_authentication": "true", + "ciphers": [ "chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com" ], + "kex_algorithms": [ "sntrup761x25519-sha512", "curve25519-sha256", "ecdh-sha2-nistp521" ], + "macs": [ "hmac-sha2-512-etm@openssh.com", "hmac-sha2-512" ] } } } @@ -74,5 +81,50 @@ } } } + }, + "SSH_SERVER_INVALID_PERMIT_ROOT_LOGIN": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "permit_root_login": "invalid" + } + } + } + }, + "SSH_SERVER_INVALID_PASSWORD_AUTHENTICATION": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "password_authentication": "invalid" + } + } + } + }, + "SSH_SERVER_INVALID_CIPHERS": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "ciphers": [ "chacha20-poly1305@openssh.com", "invalid" ] + } + } + } + }, + "SSH_SERVER_INVALID_KEX_ALGORITHMS": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "kex_algorithms": [ "sntrup761x25519-sha512", "invalid" ] + } + } + } + }, + "SSH_SERVER_INVALID_MACS": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "macs": [ "hmac-sha2-512-etm@openssh.com", "invalid" ] + } + } + } } } diff --git a/src/sonic-yang-models/yang-models/sonic-ssh-server.yang b/src/sonic-yang-models/yang-models/sonic-ssh-server.yang index fb17159eea94..c83a4757b724 100644 --- a/src/sonic-yang-models/yang-models/sonic-ssh-server.yang +++ b/src/sonic-yang-models/yang-models/sonic-ssh-server.yang @@ -59,6 +59,70 @@ module sonic-ssh-server { range 0..100; } } + leaf permit_root_login { + description "Specifies whether root can log in using ssh."; + type boolean; + } + leaf password_authentication { + description "Specifies whether password authentication is enabled."; + type boolean; + default true; + } + leaf-list ciphers { + description "Specifies the ciphers allowed."; + type enumeration { + enum "3des-cbc"; + enum "aes128-cbc"; + enum "aes192-cbc"; + enum "aes256-cbc"; + enum "aes128-ctr"; + enum "aes192-ctr"; + enum "aes256-ctr"; + enum "aes128-gcm@openssh.com"; + enum "aes256-gcm@openssh.com"; + enum "chacha20-poly1305@openssh.com"; + } + } + leaf-list kex_algorithms { + description "Specifies the available Key Exchange algorithms."; + type enumeration { + enum "diffie-hellman-group1-sha1"; + enum "diffie-hellman-group14-sha1"; + enum "diffie-hellman-group14-sha256"; + enum "diffie-hellman-group16-sha512"; + enum "diffie-hellman-group18-sha512"; + enum "diffie-hellman-group-exchange-sha1"; + enum "diffie-hellman-group-exchange-sha256"; + enum "ecdh-sha2-nistp256"; + enum "ecdh-sha2-nistp384"; + enum "ecdh-sha2-nistp521"; + enum "curve25519-sha256"; + enum "curve25519-sha256@libssh.org"; + enum "sntrup761x25519-sha512"; + enum "sntrup761x25519-sha512@openssh.com"; + } + } + leaf-list macs { + description "Specifies the available MAC (message authentication code) algorithms."; + type enumeration { + enum "hmac-sha1"; + enum "hmac-sha1-96"; + enum "hmac-sha2-256"; + enum "hmac-sha2-512"; + enum "hmac-md5"; + enum "hmac-md5-96"; + enum "umac-64@openssh.com"; + enum "umac-128@openssh.com"; + enum "hmac-sha1-etm@openssh.com"; + enum "hmac-sha1-96-etm@openssh.com"; + enum "hmac-sha2-256-etm@openssh.com"; + enum "hmac-sha2-512-etm@openssh.com"; + enum "hmac-md5-etm@openssh.com"; + enum "hmac-md5-96-etm@openssh.com"; + enum "umac-64-etm@openssh.com"; + enum "umac-128-etm@openssh.com"; + } + } }/*container policies */ } /* container SSH_SERVER */ }/* container sonic-ssh-server */ From 835f191dd554b0985faf3746e0dba88e33d5f9bf Mon Sep 17 00:00:00 2001 From: "Brad House (nexthop)" Date: Tue, 20 May 2025 08:34:05 -0400 Subject: [PATCH 2/2] make permit_root_login an enumeration --- src/sonic-yang-models/doc/Configuration.md | 6 ++- .../tests/files/sample_config_db.json | 2 +- .../yang_model_tests/tests/ssh-server.json | 12 ++++++ .../tests_config/ssh-server.json | 38 ++++++++++++++++++- .../yang-models/sonic-ssh-server.yang | 7 +++- 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/sonic-yang-models/doc/Configuration.md b/src/sonic-yang-models/doc/Configuration.md index 0a1ee9bb9ca7..2f5244cbcdcb 100644 --- a/src/sonic-yang-models/doc/Configuration.md +++ b/src/sonic-yang-models/doc/Configuration.md @@ -3055,7 +3055,11 @@ In this table, we allow configuring ssh server global settings. This will featur - ports - Ssh port numbers - string of port numbers seperated by ',' - inactivity_timeout - Inactivity timeout for SSH session, allowed values: 0-35000 (min), default value: 15 (min) - max_sessions - Max number of concurrent logins, allowed values: 0-100 (where 0 means no limit), default value: 0 -- permit_root_login - Whether or not to allow root login. Boolean. +- permit_root_login - Whether or not to allow root login. Default value: "prohibit-password" + - "yes" + - "prohibit-password" + - "forced-commands-only" + - "no" - password_authentication - Whether or not to allow password authentication. Boolean. - ciphers - Ciphers to allow. See `ssh -Q ciphers` - kex_algorithms - Key Exchange algorithms to allow. See `ssh -Q kex_algorithms` diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 632580cb8126..f31b0baf41ed 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -2703,7 +2703,7 @@ "ports": "22", "inactivity_timeout": "15", "max_sessions": "0", - "permit_root_login": "false", + "permit_root_login": "no", "password_authentication": "true", "ciphers": [ "chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com" ], "kex_algorithms": [ "sntrup761x25519-sha512", "curve25519-sha256", "ecdh-sha2-nistp521" ], diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json b/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json index 76c756f1ffb3..b87b5916a989 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/ssh-server.json @@ -5,6 +5,18 @@ "SSH_SERVER_VALID_MODIFIED": { "desc": "Configure modified SSH_SERVER." }, + "SSH_SERVER_PERMIT_ROOT_YES": { + "desc": "permit_root_login: yes" + }, + "SSH_SERVER_PERMIT_ROOT_NO": { + "desc": "permit_root_login: no" + }, + "SSH_SERVER_PERMIT_ROOT_PROHIBIT_PASSWORD": { + "desc": "permit_root_login: prohibit-password" + }, + "SSH_SERVER_PERMIT_ROOT_FORCED_COMMANDS_ONLY": { + "desc": "permit_root_login: forced-commands-only" + }, "SSH_SERVER_INVALID_AUTH_RETRIES": { "desc": "Configure invalid number of authentication retries in SSH_SERVER.", "eStrKey" : "Range" diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json index 76f9060965b3..8f42e6831011 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/ssh-server.json @@ -8,7 +8,7 @@ "ports": "22", "inactivity_timeout": "15", "max_sessions": "0", - "permit_root_login": "false", + "permit_root_login": "no", "password_authentication": "true", "ciphers": [ "chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com" ], "kex_algorithms": [ "sntrup761x25519-sha512", "curve25519-sha256", "ecdh-sha2-nistp521" ], @@ -28,6 +28,42 @@ } } }, + "SSH_SERVER_PERMIT_ROOT_YES": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "permit_root_login": "yes" + } + } + } + }, + "SSH_SERVER_PERMIT_ROOT_NO": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "permit_root_login": "no" + } + } + } + }, + "SSH_SERVER_PERMIT_ROOT_PROHIBIT_PASSWORD": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "permit_root_login": "prohibit-password" + } + } + } + }, + "SSH_SERVER_PERMIT_ROOT_FORCED_COMMANDS_ONLY": { + "sonic-ssh-server:sonic-ssh-server": { + "sonic-ssh-server:SSH_SERVER": { + "POLICIES":{ + "permit_root_login": "forced-commands-only" + } + } + } + }, "SSH_SERVER_INVALID_AUTH_RETRIES": { "sonic-ssh-server:sonic-ssh-server": { "sonic-ssh-server:SSH_SERVER": { diff --git a/src/sonic-yang-models/yang-models/sonic-ssh-server.yang b/src/sonic-yang-models/yang-models/sonic-ssh-server.yang index c83a4757b724..6686728f68f1 100644 --- a/src/sonic-yang-models/yang-models/sonic-ssh-server.yang +++ b/src/sonic-yang-models/yang-models/sonic-ssh-server.yang @@ -61,7 +61,12 @@ module sonic-ssh-server { } leaf permit_root_login { description "Specifies whether root can log in using ssh."; - type boolean; + type enumeration { + enum "yes"; + enum "prohibit-password"; + enum "forced-commands-only"; + enum "no"; + } } leaf password_authentication { description "Specifies whether password authentication is enabled.";