diff --git a/src/ssh_audit/policy.py b/src/ssh_audit/policy.py index 03430341..a93448cf 100644 --- a/src/ssh_audit/policy.py +++ b/src/ssh_audit/policy.py @@ -57,6 +57,7 @@ def __init__(self, policy_file: Optional[str] = None, policy_data: Optional[str] self._allow_algorithm_subset_and_reordering = False self._allow_larger_keys = False self._errors: List[Any] = [] + self._updated_builtin_policy_available = False # If True, an outdated built-in policy was loaded. self._name_and_version: str = '' @@ -496,6 +497,11 @@ def get_name_and_version(self) -> str: return self._name_and_version + def is_outdated_builtin_policy(self) -> bool: + '''Returns True if this is a built-in policy that has a more recent version available than currently selected.''' + return self._updated_builtin_policy_available + + def is_server_policy(self) -> bool: '''Returns True if this is a server policy, or False if this is a client policy.''' return self._server_policy @@ -549,6 +555,14 @@ def load_builtin_policy(policy_name: str, json_output: bool = False) -> Optional # Ensure this struct has all the necessary fields. p._normalize_hostkey_sizes() # pylint: disable=protected-access + # Now check if an updated version of the requested policy exists. If so, set a warning for the user. + if p is not None and p._version is not None: # pylint: disable=protected-access + next_version = str(int(p._version) + 1) # pylint: disable=protected-access + name_version_pos = policy_name.find("(version ") + next_version_name = policy_name[0:name_version_pos] + "(version %s)" % next_version + if next_version_name in BUILTIN_POLICIES: + p._updated_builtin_policy_available = True # pylint: disable=protected-access + return p diff --git a/src/ssh_audit/ssh_audit.py b/src/ssh_audit/ssh_audit.py index 8bf7d3a0..012a4d8d 100755 --- a/src/ssh_audit/ssh_audit.py +++ b/src/ssh_audit/ssh_audit.py @@ -670,7 +670,12 @@ def evaluate_policy(out: OutputBuffer, aconf: AuditConf, banner: Optional['Banne passed, error_struct, error_str = aconf.policy.evaluate(banner, kex) if aconf.json: - json_struct = {'host': aconf.host, 'port': aconf.port, 'policy': aconf.policy.get_name_and_version(), 'passed': passed, 'errors': error_struct} + warnings: List[str] = [] + if aconf.policy.is_outdated_builtin_policy(): + warnings.append("A newer version of this built-in policy is available.") + + json_struct = {'host': aconf.host, 'port': aconf.port, 'policy': aconf.policy.get_name_and_version(), 'passed': passed, 'errors': error_struct, 'warnings': warnings} + out.info(json.dumps(json_struct, indent=4 if aconf.json_print_indent else None, sort_keys=True)) else: spacing = '' @@ -703,6 +708,10 @@ def evaluate_policy(out: OutputBuffer, aconf: AuditConf, banner: Optional['Banne out.fail("%sFailed!" % icon_fail) out.warn("\nErrors:\n%s" % error_str) + # If the user selected an out-dated built-in policy then issue a warning. + if aconf.policy.is_outdated_builtin_policy(): + out.warn("Note: A newer version of this built-in policy is available. Use the -L option to view all available versions.") + return passed diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json index 194aa8fe..e82d4d7d 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test1 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json index 8fc4ce5d..1cf208a9 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json @@ -28,5 +28,6 @@ "host": "localhost", "passed": false, "policy": "Docker poliicy: test10 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json index cf48e87d..81a35169 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json @@ -20,5 +20,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test2 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json index b629e7a4..5f2e9e72 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json @@ -19,5 +19,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test3 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json index bcfa0aba..9d94aa0d 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json @@ -29,5 +29,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test4 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json index 188592b6..b2f3e746 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json @@ -28,5 +28,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test5 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json index f6dc578b..2def674f 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker poliicy: test7 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json index b9c726d0..312630d0 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json @@ -16,5 +16,6 @@ "host": "localhost", "passed": false, "policy": "Docker poliicy: test8 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json index d431d52d..5ff0f457 100644 --- a/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json @@ -16,5 +16,6 @@ "host": "localhost", "passed": false, "policy": "Docker poliicy: test9 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json index 0fc0cfc5..cc359984 100644 --- a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json @@ -40,5 +40,6 @@ "host": "localhost", "passed": false, "policy": "Hardened OpenSSH Server v8.0 (version 4)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json index 2936fcca..5b479a62 100644 --- a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json @@ -63,5 +63,6 @@ "host": "localhost", "passed": false, "policy": "Hardened OpenSSH Server v8.0 (version 4)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json index 60f4f870..cca96c62 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test11 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json index 8a099193..e86ad564 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json @@ -40,5 +40,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test12 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json index 6ddca443..e6d015b3 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test13 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json index 8b89ef33..a9031034 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json @@ -16,5 +16,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test14 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test15.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test15.json index 91fee110..139ef024 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test15.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test15.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test15 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test16.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test16.json index 7d19ee41..41946592 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test16.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test16.json @@ -83,5 +83,6 @@ "host": "localhost", "passed": false, "policy": "Docker policy: test16 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test17.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test17.json index dd1d4f4d..8c13444e 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test17.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test17.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test17 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] } diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json index 78f7f87b..4fea5369 100644 --- a/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json @@ -3,5 +3,6 @@ "host": "localhost", "passed": true, "policy": "Docker policy: test6 (version 1)", - "port": 2222 + "port": 2222, + "warnings": [] }