From f6cd392495798a5c311f88453aa8d14278e6765b Mon Sep 17 00:00:00 2001 From: joneill-r7 Date: Wed, 17 Jan 2024 15:30:34 +0000 Subject: [PATCH] SOAR-16267: validate con version and remove snyk vulns. --- README.md | 1 + icon_validator/exceptions.py | 1 + .../version_bump_validator.py | 40 ++++++++++--------- requirements.txt | 2 +- setup.py | 4 +- ...ec.good.new.connection.input.optional.yaml | 1 + .../plugin.spec.good.new.output.bumped.yaml | 1 + .../version_validator/plugin.spec_bad.yaml | 2 +- .../test_validate_plugin.py | 37 ++++++++++++----- 9 files changed, 57 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index a3576bbb..9c81ffbd 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ be on your way to contributing! ## Changelog +* 2.47.12 - `VersionBumpValidator` - update validation for connection versions| Updated `GitPython` to version 3.1.41. * 2.47.11 - Update PyYaml version to fix unrelated tooling installation bug. * 2.47.10 - `HelpInputOutputValidator` - Improved error messaging around invalid action/trigger/task headings * 2.47.9 - `DockerfileParentValidator` | `CloudReadyValidator` - update to support cloud plugins and SDK image with specified `--platform` flag | `VersionBumpValidator` - add validation for connection versions. diff --git a/icon_validator/exceptions.py b/icon_validator/exceptions.py index 7d371e80..da28260a 100644 --- a/icon_validator/exceptions.py +++ b/icon_validator/exceptions.py @@ -2,6 +2,7 @@ NO_CON_VERSION_CHANGE = "Connection details have changed but no version bump has occurred." INVALID_CON_VERSION_CHANGE = "Connection details have not changed but the connection version was bumped." INCORRECT_CON_VERSION_CHANGE = "Connection version has been bumped incorrectly." +FIRST_TIME_CONNECTION_ISSUE = "First time connection version is supplied does not match expected value." class ValidationException(Exception): """ diff --git a/icon_validator/rules/plugin_validators/version_bump_validator.py b/icon_validator/rules/plugin_validators/version_bump_validator.py index 3813a32a..11ec51c4 100644 --- a/icon_validator/rules/plugin_validators/version_bump_validator.py +++ b/icon_validator/rules/plugin_validators/version_bump_validator.py @@ -2,7 +2,7 @@ from icon_validator.rules.validator import KomandPluginValidator from icon_validator.exceptions import ValidationException, NO_LOCAL_CON_VERSION, \ - NO_CON_VERSION_CHANGE, INVALID_CON_VERSION_CHANGE, INCORRECT_CON_VERSION_CHANGE + NO_CON_VERSION_CHANGE, INVALID_CON_VERSION_CHANGE, INCORRECT_CON_VERSION_CHANGE, FIRST_TIME_CONNECTION_ISSUE from git import Repo from git.exc import InvalidGitRepositoryError import yaml @@ -265,20 +265,23 @@ def validate_connection_version(self, local_spec, remote_spec=None): if not local_connection_version: # releasing and missing connection version raise ValidationException(f"{NO_LOCAL_CON_VERSION} {err_info}") elif remote_spec: - try: - self.validate_connections(local_spec, remote_spec) # Check if connection details have changed - except ValidationException: - # Validation noticed a difference between remote and local; now check we bumped the version - old_connection_version = remote_spec.get(SpecConstants.CONNECTION_VERSION) - if old_connection_version == local_connection_version: - raise ValidationException(f"{NO_CON_VERSION_CHANGE} {err_info}") - elif local_connection_version != (old_connection_version+1): - raise ValidationException(f"{INCORRECT_CON_VERSION_CHANGE} {err_info}") - return # validation happy that connection schema and version bumped - - # no changes the connection version should not have changed - if int(local_connection_version) != int(remote_spec.get(SpecConstants.CONNECTION_VERSION)): - raise ValidationException(f"{INVALID_CON_VERSION_CHANGE}") + old_connection_version = remote_spec.get(SpecConstants.CONNECTION_VERSION) + if old_connection_version: + try: + self.validate_connections(remote_spec, local_spec) # Check if connection details have changed + except ValidationException: + # Validation noticed a difference between remote and local; now check we bumped the version + if old_connection_version == local_connection_version: + raise ValidationException(f"{NO_CON_VERSION_CHANGE} {err_info}") + elif local_connection_version != (old_connection_version + 1): + raise ValidationException(f"{INCORRECT_CON_VERSION_CHANGE} {err_info}") + return # validation happy that connection schema and version bumped + # no changes the connection version should not have changed + if int(local_connection_version) != int(remote_spec.get(SpecConstants.CONNECTION_VERSION)): + raise ValidationException(f"{INVALID_CON_VERSION_CHANGE}") + elif int(local_connection_version) != int(self.local_version[0]): + # No version to compare against we should make sure one that is supplied matches our plugin version + raise ValidationException(f"{FIRST_TIME_CONNECTION_ISSUE} {err_info}") def validate_inner_fields(self, remote, local): self.validate_no_sections_removed(remote, local) @@ -381,16 +384,15 @@ def validate(self, spec): self.local_version, self.remote_version = self.get_versions(local_spec, remote_spec) + # we should validate connection versions regardless of the version changes to ensure these remain stable + self.validate_connection_version(local_spec, remote_spec) + # case: new plugin with no remote spec if remote_spec is None: - # Check if a connection version should be added - self.validate_connection_version(local_spec) return # perform the different sections of validation # Check if we already did a major version bump- if so, no need to do all this checking if not self.check_major_version_increment_needed(): - # We already bumped the major version - check if connection version bump is needed - self.validate_connection_version(local_spec, remote_spec) return else: self.validate_actions(remote_spec, local_spec) diff --git a/requirements.txt b/requirements.txt index 941d5adf..e41f0c2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,4 @@ urlextract==0.14.0 typing==3.7.4.1 PyYAML==6.0.1 dacite==1.6.0 -GitPython==3.1.37 +GitPython==3.1.41 diff --git a/setup.py b/setup.py index c582d42b..2491bbb0 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name="insightconnect_integrations_validators", - version="2.47.11", + version="2.47.12", description="Validator tooling for InsightConnect integrations", long_description=long_description, long_description_content_type="text/markdown", @@ -25,7 +25,7 @@ "typing==3.7.4.1", "PyYAML==6.0.1", "dacite==1.6.0", - "GitPython==3.1.37", + "GitPython==3.1.41", ], entry_points={"console_scripts": ["icon-validate=icon_validator.__main__:main"]}, classifiers=[ diff --git a/unit_test/plugin_examples/plugin_major_version_bump_all/plugin.spec.good.new.connection.input.optional.yaml b/unit_test/plugin_examples/plugin_major_version_bump_all/plugin.spec.good.new.connection.input.optional.yaml index 74ae1f52..e06030d6 100644 --- a/unit_test/plugin_examples/plugin_major_version_bump_all/plugin.spec.good.new.connection.input.optional.yaml +++ b/unit_test/plugin_examples/plugin_major_version_bump_all/plugin.spec.good.new.connection.input.optional.yaml @@ -5,6 +5,7 @@ name: microsoft_office365_email title: Microsoft Office 365 Email description: The Microsoft Office 365 email plugin enables phishing analysis and email management. The plugin includes the ability to manage and remediate suspicious email version: 5.0.5 +connection_version: 5 vendor: rapid7 support: rapid7 status: [] diff --git a/unit_test/plugin_examples/plugin_minor_version_bump_all/plugin.spec.good.new.output.bumped.yaml b/unit_test/plugin_examples/plugin_minor_version_bump_all/plugin.spec.good.new.output.bumped.yaml index 83a2d3fd..63a1f20d 100644 --- a/unit_test/plugin_examples/plugin_minor_version_bump_all/plugin.spec.good.new.output.bumped.yaml +++ b/unit_test/plugin_examples/plugin_minor_version_bump_all/plugin.spec.good.new.output.bumped.yaml @@ -5,6 +5,7 @@ name: microsoft_office365_email title: Microsoft Office 365 Email description: The Microsoft Office 365 email plugin enables phishing analysis and email management. The plugin includes the ability to manage and remediate suspicious email version: 5.1.0 +connection_version: 5 vendor: rapid7 support: rapid7 status: [] diff --git a/unit_test/plugin_examples/version_validator/plugin.spec_bad.yaml b/unit_test/plugin_examples/version_validator/plugin.spec_bad.yaml index b67891a6..222c5b9c 100755 --- a/unit_test/plugin_examples/version_validator/plugin.spec_bad.yaml +++ b/unit_test/plugin_examples/version_validator/plugin.spec_bad.yaml @@ -1,3 +1,3 @@ plugin_spec_version: v2 name: active_directory_ldap -version: 5.3.3 +version: 5.3.3 \ No newline at end of file diff --git a/unit_test/test_validate_plugin/test_validate_plugin.py b/unit_test/test_validate_plugin/test_validate_plugin.py index f7409d9c..70669a32 100644 --- a/unit_test/test_validate_plugin/test_validate_plugin.py +++ b/unit_test/test_validate_plugin/test_validate_plugin.py @@ -1,6 +1,6 @@ import unittest from icon_validator.exceptions import NO_LOCAL_CON_VERSION, NO_CON_VERSION_CHANGE, \ - INVALID_CON_VERSION_CHANGE, INCORRECT_CON_VERSION_CHANGE + INVALID_CON_VERSION_CHANGE, INCORRECT_CON_VERSION_CHANGE, FIRST_TIME_CONNECTION_ISSUE from icon_validator.validate import validate from icon_validator.exceptions import ValidationException from icon_plugin_spec.plugin_spec import KomandPluginSpec @@ -682,17 +682,36 @@ def test_version_new_output_bumped_succeed(self): @parameterized.expand([ # ('test_name', new_yaml, exception, mock_local_spec) - ('initial_no_connection', "plugin.spec.good.new.connection.input.optional.yaml", NO_LOCAL_CON_VERSION, True), - ('changed_con_schema_no_ver_bump', "plugin.spec.bad.new.connection.yaml", NO_CON_VERSION_CHANGE, False), - ('changed_con_schema_with_ver_bump', "plugin.spec.good.new.connection.yaml", None, False), - ('invalid_con_ver_bump', "plugin.spec.bad.connection.change.yaml", INVALID_CON_VERSION_CHANGE, False), - ('incorrect_con_ver_bump', "plugin.spec.bad.new.connection.version.yaml", INCORRECT_CON_VERSION_CHANGE, False) + ('initial_no_connection', "plugin.spec.good.new.nonrequired.input.yaml", NO_LOCAL_CON_VERSION, False), + ('changed_con_schema_no_ver_bump', "plugin.spec.bad.new.connection.yaml", NO_CON_VERSION_CHANGE, True), + ('changed_con_schema_with_ver_bump', "plugin.spec.good.new.connection.yaml", None, True), + ('invalid_con_ver_bump', "plugin.spec.bad.connection.change.yaml", INVALID_CON_VERSION_CHANGE, True), + ('incorrect_con_ver_bump', "plugin.spec.bad.new.connection.version.yaml", INCORRECT_CON_VERSION_CHANGE, True), + ('initial_version_connection', "plugin.spec.good.new.connection.yaml", None, True), + ('bad_initial_version_con', "plugin.spec.bad.new.connection.version.yaml", FIRST_TIME_CONNECTION_ISSUE, True) ]) @patch('builtins.print') - def test_plugin_connection_version(self, _test_name, local_yaml, exp_exception, mock_spec, mock_print): + def test_plugin_connection_version(self, test_name, local_yaml, exp_exception, mock_spec, mock_print): + """ + Tests and explanation of passing vs error reasoning. If mocking the remote_spec our util file looks in the + specified directory for the spec file named: `plugin.spec.remote.yaml` + - #1: connection params are present but no version has been specified, we should error. + - #2: connection details have changed from previous plugin spec, the version should have been bumped. + - #3: happy path that we have updated connection details and bumped the connection version correctly. + - #4: connection version has changed when it was not required, we want to error on this. + - #5: connection version should match the plugin version major version, error that these do not match. + - #6: first time plugin is released with a connection version specified, previously no con version was included. + - #7: first time plugin is specifying the connection version and this does not match the plugin major version. + """ directory_to_test = "plugin_examples/plugin_major_version_bump_all" - remote_spec = MockRepoSpecResponse.mock_patch_remote_spec_major_version(directory_to_test) - VersionBumpValidator.get_remote_spec = MagicMock(return_value=remote_spec if not mock_spec else None) + + if test_name in ["initial_version_connection", "bad_initial_version_con"]: + remote_dir = "plugin_examples/plugin_minor_version_bump_all" # no remote connection version in this spec + else: + remote_dir = directory_to_test + + remote_spec = MockRepoSpecResponse.mock_patch_remote_spec_major_version(remote_dir) + VersionBumpValidator.get_remote_spec = MagicMock(return_value=remote_spec if mock_spec else None) result = validate(directory_to_test, local_yaml, False, True, [VersionBumpValidator()]) exit_code = 0