insightconnect-plugin-runtime 6.2.1__tar.gz → 6.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. {insightconnect_plugin_runtime-6.2.1/insightconnect_plugin_runtime.egg-info → insightconnect_plugin_runtime-6.2.2}/PKG-INFO +2 -1
  2. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/README.md +1 -0
  3. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/helper.py +69 -32
  4. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2/insightconnect_plugin_runtime.egg-info}/PKG-INFO +2 -1
  5. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/setup.py +1 -1
  6. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_helpers.py +43 -17
  7. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/MANIFEST.in +0 -0
  8. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect-plugin-swagger.json +0 -0
  9. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/__init__.py +0 -0
  10. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/action.py +0 -0
  11. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/api/__init__.py +0 -0
  12. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/api/endpoints.py +0 -0
  13. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/api/schemas.py +0 -0
  14. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/cli.py +0 -0
  15. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/clients/__init__.py +0 -0
  16. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/clients/aws_client.py +0 -0
  17. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/clients/oauth.py +0 -0
  18. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/connection.py +0 -0
  19. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/data/input_message_schema.json +0 -0
  20. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/data/output_message_schema.json +0 -0
  21. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/dispatcher.py +0 -0
  22. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/exceptions.py +0 -0
  23. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/metrics.py +0 -0
  24. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/plugin.py +0 -0
  25. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/schema.py +0 -0
  26. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/server.py +0 -0
  27. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/step.py +0 -0
  28. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/task.py +0 -0
  29. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/trigger.py +0 -0
  30. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/util.py +0 -0
  31. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime/variables.py +0 -0
  32. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime.egg-info/SOURCES.txt +0 -0
  33. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime.egg-info/dependency_links.txt +0 -0
  34. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime.egg-info/requires.txt +0 -0
  35. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/insightconnect_plugin_runtime.egg-info/top_level.txt +0 -0
  36. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/setup.cfg +0 -0
  37. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/__init__.py +0 -0
  38. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/__init__.py +0 -0
  39. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/__init__.py +0 -0
  40. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/__init__.py +0 -0
  41. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/__init__.py +0 -0
  42. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/__init__.py +0 -0
  43. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/__init__.py +0 -0
  44. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/action.py +0 -0
  45. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/schema.py +0 -0
  46. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/__init__.py +0 -0
  47. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/action.py +0 -0
  48. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/schema.py +0 -0
  49. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/__init__.py +0 -0
  50. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/action.py +0 -0
  51. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/schema.py +0 -0
  52. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/__init__.py +0 -0
  53. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/connection.py +0 -0
  54. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/schema.py +0 -0
  55. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/__init__.py +0 -0
  56. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/__init__.py +0 -0
  57. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/schema.py +0 -0
  58. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/task.py +0 -0
  59. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/__init__.py +0 -0
  60. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/__init__.py +0 -0
  61. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/schema.py +0 -0
  62. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/trigger.py +0 -0
  63. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/__init__.py +0 -0
  64. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/schema.py +0 -0
  65. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/trigger.py +0 -0
  66. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/__init__.py +0 -0
  67. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/schema.py +0 -0
  68. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/trigger.py +0 -0
  69. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/komand_hello_world/util/__init__.py +0 -0
  70. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/hello_world/setup.py +0 -0
  71. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/tests/__init__.py +0 -0
  72. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/tests/conftest.py +0 -0
  73. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/tests/test_cli.py +0 -0
  74. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/tests/test_hello_world.py +0 -0
  75. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/plugin/hello_world/tests/test_server.py +0 -0
  76. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/__init__.py +0 -0
  77. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_action.py +0 -0
  78. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_api.py +0 -0
  79. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_aws_action.py +0 -0
  80. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_custom_encoder.py +0 -0
  81. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_endpoints.py +0 -0
  82. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_exceptions.py +0 -0
  83. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_metrics.py +0 -0
  84. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_oauth.py +0 -0
  85. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_plugin.py +0 -0
  86. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_schema.py +0 -0
  87. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_server_cloud_plugins.py +0 -0
  88. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_server_spec.py +0 -0
  89. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_trigger.py +0 -0
  90. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/test_variables.py +0 -0
  91. {insightconnect_plugin_runtime-6.2.1 → insightconnect_plugin_runtime-6.2.2}/tests/unit/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: insightconnect-plugin-runtime
3
- Version: 6.2.1
3
+ Version: 6.2.2
4
4
  Summary: InsightConnect Plugin Runtime
5
5
  Home-page: https://github.com/rapid7/komand-plugin-sdk-python
6
6
  Author: Rapid7 Integrations Alliance
@@ -211,6 +211,7 @@ contributed. Black is installed as a test dependency and the hook can be initial
211
211
  after cloning this repository.
212
212
 
213
213
  ## Changelog
214
+ * 6.2.2 - Fix instances where logging errors would lead to duplicate entries being output | Add option to hash only on provided keys for `hash_sha1` function
214
215
  * 6.2.1 - Fix instances where logging would lead to duplicate entries being output
215
216
  * 6.2.0 - Update base images to pull Python 3.11.10 | changed the pep-8 check in tox to `pycodestyle`
216
217
  * 6.1.4 - Address vulnerabilities within local development requirements.txt and vulnerabilities in slim image.
@@ -182,6 +182,7 @@ contributed. Black is installed as a test dependency and the hook can be initial
182
182
  after cloning this repository.
183
183
 
184
184
  ## Changelog
185
+ * 6.2.2 - Fix instances where logging errors would lead to duplicate entries being output | Add option to hash only on provided keys for `hash_sha1` function
185
186
  * 6.2.1 - Fix instances where logging would lead to duplicate entries being output
186
187
  * 6.2.0 - Update base images to pull Python 3.11.10 | changed the pep-8 check in tox to `pycodestyle`
187
188
  * 6.1.4 - Address vulnerabilities within local development requirements.txt and vulnerabilities in slim image.
@@ -10,7 +10,7 @@ import subprocess
10
10
  import time
11
11
  from datetime import datetime, timedelta
12
12
  from io import IOBase
13
- from typing import Any, Callable, Dict, List, Union, Tuple
13
+ from typing import Any, Callable, Dict, List, Union, Tuple, Optional
14
14
  from urllib import request
15
15
  from hashlib import sha1
16
16
  from json import JSONDecodeError
@@ -33,17 +33,45 @@ DEFAULTS_HOURS_AGO = 24
33
33
  logger = logging.getLogger()
34
34
 
35
35
 
36
- def hash_sha1(log: Dict) -> str:
36
+ def hash_sha1(log: Dict[str, Any], keys: Optional[List[str]] = None) -> str:
37
37
  """
38
38
  Iterate through a dictionary and hash each value.
39
+ Optionally only hash certain keys in the dictionary.
40
+
39
41
  :param log: Dictionary to be hashed.
40
- :type Dict:
42
+ :param keys: Optional list of keys to hash on if provided
43
+
41
44
  :return: Hex digest of hash.
42
- :rtype: str
43
45
  """
46
+
44
47
  hash_ = sha1() # nosec B303
45
- for key, value in log.items():
48
+
49
+ # Leaving no room for developer error and ensuring they know exactly where it went wrong
50
+ # if they provide a key not in list format
51
+ if keys is not None and not isinstance(keys, list):
52
+ raise TypeError(
53
+ f"The 'keys' parameter must be a list or None in the 'hash_sha1' function, not {type(keys).__name__}"
54
+ )
55
+
56
+ # Hash all key-value pairs if no keys provided
57
+ if keys is None:
58
+ items_to_hash = log.items()
59
+
60
+ # Otherwise, only include specified keys
61
+ else:
62
+ items_to_hash = []
63
+ for key in keys:
64
+ if key in log:
65
+ items_to_hash.append((key, log[key]))
66
+
67
+ # Alert if the key is not found in the log
68
+ else:
69
+ raise KeyError(f"Key '{key}' not found in the provided log.")
70
+
71
+ # Iterate through items to hash and hash
72
+ for key, value in items_to_hash:
46
73
  hash_.update(f"{key}{value}".encode(ENCODE_TYPE))
74
+
47
75
  return hash_.hexdigest()
48
76
 
49
77
 
@@ -137,7 +165,12 @@ def make_request(
137
165
  raise PluginException(
138
166
  preset=PluginException.Preset.UNKNOWN, data=str(exception)
139
167
  )
140
- response_handler(response, exception_custom_configs, exception_data_location, allowed_status_codes)
168
+ response_handler(
169
+ response,
170
+ exception_custom_configs,
171
+ exception_data_location,
172
+ allowed_status_codes,
173
+ )
141
174
  return response
142
175
 
143
176
 
@@ -192,7 +225,7 @@ def request_error_handling(
192
225
  exception.response,
193
226
  data_location=exception_data_location,
194
227
  custom_configs=custom_configs,
195
- allowed_status_codes=allowed_status_codes
228
+ allowed_status_codes=allowed_status_codes,
196
229
  )
197
230
  else:
198
231
  raise PluginException(
@@ -443,15 +476,19 @@ def convert_dict_to_snake_case(
443
476
 
444
477
  if isinstance(input_dict, list):
445
478
  return [
446
- convert_dict_to_snake_case(element)
447
- if isinstance(element, (dict, list))
448
- else element
479
+ (
480
+ convert_dict_to_snake_case(element)
481
+ if isinstance(element, (dict, list))
482
+ else element
483
+ )
449
484
  for element in input_dict
450
485
  ]
451
486
  return {
452
- convert_to_snake_case(key): convert_dict_to_snake_case(value)
453
- if isinstance(value, (dict, list))
454
- else value
487
+ convert_to_snake_case(key): (
488
+ convert_dict_to_snake_case(value)
489
+ if isinstance(value, (dict, list))
490
+ else value
491
+ )
455
492
  for key, value in input_dict.items()
456
493
  }
457
494
 
@@ -665,7 +702,7 @@ def open_cachefile(cache_file, append=False):
665
702
  logger.info("OpenCacheFile: %s created", cache_file)
666
703
  f = open(cache_file, "a+" if append else "r+")
667
704
  return f
668
- logging.error("OpenCacheFile: %s directory or does not exist", cache_dir)
705
+ logger.error("OpenCacheFile: %s directory or does not exist", cache_dir)
669
706
 
670
707
 
671
708
  def remove_cachefile(cache_file):
@@ -748,11 +785,11 @@ def open_url(url, timeout=None, verify=True, **kwargs):
748
785
  urlobj = request.urlopen(req, timeout=timeout, context=ctx)
749
786
  return urlobj
750
787
  except request.HTTPError as e:
751
- logging.error("HTTPError: %s for %s", str(e.code), url)
788
+ logger.error("HTTPError: %s for %s", str(e.code), url)
752
789
  if e.code == 304:
753
790
  return None
754
791
  except request.URLError as e:
755
- logging.error("URLError: %s for %s", str(e.reason), url)
792
+ logger.error("URLError: %s for %s", str(e.reason), url)
756
793
  raise Exception("GetURL Failed")
757
794
 
758
795
 
@@ -780,17 +817,17 @@ def check_url(url):
780
817
  return True
781
818
 
782
819
  except requests.exceptions.HTTPError:
783
- logging.error(
820
+ logger.error(
784
821
  "Requests: HTTPError: status code %s for %s",
785
822
  str(resp.status_code) if resp else None,
786
823
  url,
787
824
  )
788
825
  except requests.exceptions.Timeout:
789
- logging.error("Requests: Timeout for %s", url)
826
+ logger.error("Requests: Timeout for %s", url)
790
827
  except requests.exceptions.TooManyRedirects:
791
- logging.error("Requests: TooManyRedirects for %s", url)
828
+ logger.error("Requests: TooManyRedirects for %s", url)
792
829
  except requests.ConnectionError:
793
- logging.error("Requests: ConnectionError for %s", url)
830
+ logger.error("Requests: ConnectionError for %s", url)
794
831
  return False
795
832
 
796
833
 
@@ -810,7 +847,7 @@ def exec_command(command):
810
847
  rcode = p.poll()
811
848
  return {"stdout": stdout, "stderr": stderr, "rcode": rcode}
812
849
  except OSError as e:
813
- logging.error(
850
+ logger.error(
814
851
  "SubprocessError: %s %s: %s", str(e.filename), str(e.strerror), str(e.errno)
815
852
  )
816
853
  raise Exception("ExecCommand")
@@ -836,7 +873,7 @@ def encode_file(file_path):
836
873
  return efile
837
874
  return None
838
875
  except (IOError, OSError) as e:
839
- logging.error("EncodeFile: Failed to open file: %s", e.strerror)
876
+ logger.error("EncodeFile: Failed to open file: %s", e.strerror)
840
877
  raise Exception("EncodeFile")
841
878
  finally:
842
879
  if isinstance(f, IOBase):
@@ -859,17 +896,17 @@ def check_url_modified(url):
859
896
  if resp.status_code == 200:
860
897
  return True
861
898
  except requests.exceptions.HTTPError:
862
- logging.error(
899
+ logger.error(
863
900
  "Requests: HTTPError: status code %s for %s",
864
901
  str(resp.status_code) if resp else None,
865
902
  url,
866
903
  )
867
904
  except requests.exceptions.Timeout:
868
- logging.error("Requests: Timeout for %s", url)
905
+ logger.error("Requests: Timeout for %s", url)
869
906
  except requests.exceptions.TooManyRedirects:
870
- logging.error("Requests: TooManyRedirects for %s", url)
907
+ logger.error("Requests: TooManyRedirects for %s", url)
871
908
  except requests.ConnectionError:
872
- logging.error("Requests: ConnectionError for %s", url)
909
+ logger.error("Requests: ConnectionError for %s", url)
873
910
  return False
874
911
 
875
912
 
@@ -895,7 +932,7 @@ def get_url_path_filename(url):
895
932
  if name[n].endswith("."):
896
933
  return name
897
934
  except IndexError:
898
- logging.error("Range: IndexError: URL basename is short: %s of %s", name, url)
935
+ logger.error("Range: IndexError: URL basename is short: %s of %s", name, url)
899
936
  return None
900
937
  return None
901
938
 
@@ -915,16 +952,16 @@ def get_url_filename(url):
915
952
  return name
916
953
  return None
917
954
  except requests.exceptions.MissingSchema:
918
- logging.error("Requests: MissingSchema: Requires ftp|http(s):// for %s", url)
955
+ logger.error("Requests: MissingSchema: Requires ftp|http(s):// for %s", url)
919
956
  except requests.exceptions.HTTPError:
920
- logging.error(
957
+ logger.error(
921
958
  "Requests: HTTPError: status code %s for %s",
922
959
  str(resp.status_code) if resp else None,
923
960
  url,
924
961
  )
925
962
  except requests.exceptions.Timeout:
926
- logging.error("Requests: Timeout for %s", url)
963
+ logger.error("Requests: Timeout for %s", url)
927
964
  except requests.exceptions.TooManyRedirects:
928
- logging.error("Requests: TooManyRedirects for %s", url)
965
+ logger.error("Requests: TooManyRedirects for %s", url)
929
966
  except requests.ConnectionError:
930
- logging.error("Requests: ConnectionError for %s", url)
967
+ logger.error("Requests: ConnectionError for %s", url)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: insightconnect-plugin-runtime
3
- Version: 6.2.1
3
+ Version: 6.2.2
4
4
  Summary: InsightConnect Plugin Runtime
5
5
  Home-page: https://github.com/rapid7/komand-plugin-sdk-python
6
6
  Author: Rapid7 Integrations Alliance
@@ -211,6 +211,7 @@ contributed. Black is installed as a test dependency and the hook can be initial
211
211
  after cloning this repository.
212
212
 
213
213
  ## Changelog
214
+ * 6.2.2 - Fix instances where logging errors would lead to duplicate entries being output | Add option to hash only on provided keys for `hash_sha1` function
214
215
  * 6.2.1 - Fix instances where logging would lead to duplicate entries being output
215
216
  * 6.2.0 - Update base images to pull Python 3.11.10 | changed the pep-8 check in tox to `pycodestyle`
216
217
  * 6.1.4 - Address vulnerabilities within local development requirements.txt and vulnerabilities in slim image.
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name="insightconnect-plugin-runtime",
8
- version="6.2.1",
8
+ version="6.2.2",
9
9
  description="InsightConnect Plugin Runtime",
10
10
  long_description=long_description,
11
11
  long_description_content_type="text/markdown",
@@ -510,20 +510,46 @@ class TestRequestsHelpers(TestCase):
510
510
  )
511
511
 
512
512
 
513
- def test_hash_sha1():
514
- log = {"example": "value", "sample": "value"}
515
- assert "2e1ccc1a95e9b2044f13546c25fe380bbd039293" == helper.hash_sha1(log)
516
-
517
-
518
- def test_compare_and_dedupe_hashes():
519
- hashes = ["2e1ccc1a95e9b2044f13546c25fe380bbd039293"]
520
- logs = [
521
- {
522
- "example": "value",
523
- "sample": "value",
524
- },
525
- {"specimen": "new_value"},
526
- ]
527
- assert [{"specimen": "new_value"}], [
528
- "ad6ae80c0356e02b1561cb58408ee678eb1070bb"
529
- ] == helper.compare_and_dedupe_hashes(hashes, logs)
513
+ class TestHashing(TestCase):
514
+ def setUp(self) -> None:
515
+ self.log = {"example": "value", "sample": "value"}
516
+
517
+ def test_hash_sha1_no_keys(self):
518
+ # Test hash with no keys provided
519
+ expected_hash = "2e1ccc1a95e9b2044f13546c25fe380bbd039293"
520
+ self.assertEqual(helper.hash_sha1(self.log), expected_hash)
521
+
522
+ def test_hash_sha1_keys(self):
523
+ # Test hash with valid key provided
524
+ expected_hash = "61c908e52d66a763ceed0798b8e5f4b7f0328a21"
525
+ self.assertEqual(helper.hash_sha1(self.log, keys=["example"]), expected_hash)
526
+
527
+ def test_hash_sha1_keys_wrong_type(self):
528
+ # Test hash with wrong type for keys
529
+ with self.assertRaises(TypeError) as context:
530
+ helper.hash_sha1(self.log, keys="test")
531
+
532
+ self.assertEqual(
533
+ str(context.exception),
534
+ "The 'keys' parameter must be a list or None in the 'hash_sha1' function, not str"
535
+ )
536
+
537
+ def test_hash_sha1_keys_not_found(self):
538
+ # Test hash with key not found
539
+ with self.assertRaises(KeyError) as context:
540
+ helper.hash_sha1(self.log, keys=["example", "test"])
541
+
542
+ self.assertEqual(str(context.exception), "\"Key 'test' not found in the provided log.\"")
543
+
544
+ def test_compare_and_dedupe_hashes(self):
545
+ hashes = ["2e1ccc1a95e9b2044f13546c25fe380bbd039293"]
546
+ logs = [
547
+ {
548
+ "example": "value",
549
+ "sample": "value",
550
+ },
551
+ {"specimen": "new_value"},
552
+ ]
553
+ assert [{"specimen": "new_value"}], [
554
+ "ad6ae80c0356e02b1561cb58408ee678eb1070bb"
555
+ ] == helper.compare_and_dedupe_hashes(hashes, logs)