insightconnect-plugin-runtime 6.4.0__tar.gz → 6.4.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 (94) hide show
  1. {insightconnect_plugin_runtime-6.4.0/insightconnect_plugin_runtime.egg-info → insightconnect_plugin_runtime-6.4.2}/PKG-INFO +16 -14
  2. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/README.md +4 -2
  3. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/clients/aws_client.py +18 -3
  4. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/helper.py +1 -1
  5. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/server.py +3 -2
  6. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2/insightconnect_plugin_runtime.egg-info}/PKG-INFO +16 -14
  7. insightconnect_plugin_runtime-6.4.2/insightconnect_plugin_runtime.egg-info/requires.txt +21 -0
  8. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/setup.py +12 -12
  9. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_aws_action.py +66 -11
  10. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_connection.py +6 -6
  11. insightconnect_plugin_runtime-6.4.0/insightconnect_plugin_runtime.egg-info/requires.txt +0 -21
  12. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/MANIFEST.in +0 -0
  13. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect-plugin-swagger.json +0 -0
  14. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/__init__.py +0 -0
  15. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/action.py +0 -0
  16. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/api/__init__.py +0 -0
  17. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/api/endpoints.py +0 -0
  18. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/api/schemas.py +0 -0
  19. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/cli.py +0 -0
  20. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/clients/__init__.py +0 -0
  21. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/clients/oauth.py +0 -0
  22. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/connection.py +0 -0
  23. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/data/input_message_schema.json +0 -0
  24. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/data/output_message_schema.json +0 -0
  25. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/dispatcher.py +0 -0
  26. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/exceptions.py +0 -0
  27. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/metrics.py +0 -0
  28. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/plugin.py +0 -0
  29. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/schema.py +0 -0
  30. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/step.py +0 -0
  31. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/task.py +0 -0
  32. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/telemetry.py +0 -0
  33. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/trigger.py +0 -0
  34. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/util.py +0 -0
  35. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime/variables.py +0 -0
  36. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime.egg-info/SOURCES.txt +0 -0
  37. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime.egg-info/dependency_links.txt +0 -0
  38. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/insightconnect_plugin_runtime.egg-info/top_level.txt +0 -0
  39. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/setup.cfg +0 -0
  40. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/__init__.py +0 -0
  41. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/__init__.py +0 -0
  42. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/__init__.py +0 -0
  43. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/__init__.py +0 -0
  44. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/__init__.py +0 -0
  45. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/__init__.py +0 -0
  46. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/__init__.py +0 -0
  47. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/action.py +0 -0
  48. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/hello/schema.py +0 -0
  49. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/__init__.py +0 -0
  50. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/action.py +0 -0
  51. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/return_bad_json/schema.py +0 -0
  52. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/__init__.py +0 -0
  53. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/action.py +0 -0
  54. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/actions/throw_exception/schema.py +0 -0
  55. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/__init__.py +0 -0
  56. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/connection.py +0 -0
  57. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/connection/schema.py +0 -0
  58. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/__init__.py +0 -0
  59. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/__init__.py +0 -0
  60. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/schema.py +0 -0
  61. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/tasks/monitor_events/task.py +0 -0
  62. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/__init__.py +0 -0
  63. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/__init__.py +0 -0
  64. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/schema.py +0 -0
  65. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/hello_trigger/trigger.py +0 -0
  66. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/__init__.py +0 -0
  67. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/schema.py +0 -0
  68. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/return_bad_json_trigger/trigger.py +0 -0
  69. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/__init__.py +0 -0
  70. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/schema.py +0 -0
  71. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/triggers/throw_exception_trigger/trigger.py +0 -0
  72. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/komand_hello_world/util/__init__.py +0 -0
  73. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/hello_world/setup.py +0 -0
  74. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/tests/__init__.py +0 -0
  75. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/tests/conftest.py +0 -0
  76. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/tests/test_cli.py +0 -0
  77. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/tests/test_hello_world.py +0 -0
  78. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/plugin/hello_world/tests/test_server.py +0 -0
  79. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/__init__.py +0 -0
  80. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_action.py +0 -0
  81. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_api.py +0 -0
  82. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_custom_encoder.py +0 -0
  83. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_endpoints.py +0 -0
  84. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_exceptions.py +0 -0
  85. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_helpers.py +0 -0
  86. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_metrics.py +0 -0
  87. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_oauth.py +0 -0
  88. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_plugin.py +0 -0
  89. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_schema.py +0 -0
  90. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_server_cloud_plugins.py +0 -0
  91. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_server_spec.py +0 -0
  92. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_trigger.py +0 -0
  93. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/test_variables.py +0 -0
  94. {insightconnect_plugin_runtime-6.4.0 → insightconnect_plugin_runtime-6.4.2}/tests/unit/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: insightconnect-plugin-runtime
3
- Version: 6.4.0
3
+ Version: 6.4.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
@@ -12,27 +12,27 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Natural Language :: English
13
13
  Classifier: Topic :: Software Development :: Build Tools
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: requests==2.32.4
15
+ Requires-Dist: requests==2.32.5
16
16
  Requires-Dist: python_jsonschema_objects==0.5.2
17
17
  Requires-Dist: jsonschema==4.22.0
18
- Requires-Dist: certifi==2025.8.3
19
- Requires-Dist: Flask==3.1.1
18
+ Requires-Dist: certifi==2026.1.4
19
+ Requires-Dist: Flask==3.1.2
20
20
  Requires-Dist: gunicorn==23.0.0
21
- Requires-Dist: greenlet==3.2.3
21
+ Requires-Dist: greenlet==3.3.0
22
22
  Requires-Dist: gevent==25.5.1
23
- Requires-Dist: marshmallow==3.21.0
23
+ Requires-Dist: marshmallow==3.26.2
24
24
  Requires-Dist: apispec==6.5.0
25
25
  Requires-Dist: apispec-webframeworks==1.0.0
26
26
  Requires-Dist: blinker==1.9.0
27
- Requires-Dist: structlog==25.4.0
27
+ Requires-Dist: structlog==25.5.0
28
28
  Requires-Dist: python-json-logger==2.0.7
29
29
  Requires-Dist: Jinja2==3.1.6
30
30
  Requires-Dist: python-dateutil==2.9.0.post0
31
- Requires-Dist: opentelemetry-sdk==1.36.0
32
- Requires-Dist: opentelemetry-instrumentation-flask==0.57b0
33
- Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.36.0
34
- Requires-Dist: opentelemetry-instrumentation-requests==0.57b0
35
- Requires-Dist: urllib3==2.5.0
31
+ Requires-Dist: opentelemetry-sdk==1.39.1
32
+ Requires-Dist: opentelemetry-instrumentation-flask==0.60b1
33
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.39.1
34
+ Requires-Dist: opentelemetry-instrumentation-requests==0.60b1
35
+ Requires-Dist: urllib3==2.6.3
36
36
  Dynamic: author
37
37
  Dynamic: author-email
38
38
  Dynamic: classifier
@@ -63,10 +63,10 @@ to get started.
63
63
 
64
64
  ## Development of the InsightConnect Plugin Runtime
65
65
 
66
- The Python Runtime codebase is built to support Python 3.11.13 as of version 6.2.3. The following dependencies will need
66
+ The Python Runtime codebase is built to support Python 3.13 as of version 6.4.0. The following dependencies will need
67
67
  to be installed when developing or testing the Plugin Runtime:
68
68
 
69
- - Python 3.11.13
69
+ - Python 3.13.11
70
70
  - Docker
71
71
  - make
72
72
  - tox
@@ -226,6 +226,8 @@ contributed. Black is installed as a test dependency and the hook can be initial
226
226
  after cloning this repository.
227
227
 
228
228
  ## Changelog
229
+ * 6.4.2 - Added error handling for `hash_sha1` in helpers | Updated base images to Python 3.13.11 | Updated dependencies
230
+ * 6.4.1 - Fix logging on cloud mode to remove `taskName` | Close boto client after assuming role
229
231
  * 6.4.0 - When running in cloud mode, always create a new connection object | Bump Python version to 3.13.9 | Docker build tidyup to reduce image size
230
232
  * 6.3.10 - Fixed tracing name to better allign otel standards
231
233
  * 6.3.9 - Fixed `monitor_task_delay` decorator handling of millisecond epoch timestamps | Allow `test_task` connection method to accept task name parameter | Updated base images to Python 3.11.13
@@ -19,10 +19,10 @@ to get started.
19
19
 
20
20
  ## Development of the InsightConnect Plugin Runtime
21
21
 
22
- The Python Runtime codebase is built to support Python 3.11.13 as of version 6.2.3. The following dependencies will need
22
+ The Python Runtime codebase is built to support Python 3.13 as of version 6.4.0. The following dependencies will need
23
23
  to be installed when developing or testing the Plugin Runtime:
24
24
 
25
- - Python 3.11.13
25
+ - Python 3.13.11
26
26
  - Docker
27
27
  - make
28
28
  - tox
@@ -182,6 +182,8 @@ 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.4.2 - Added error handling for `hash_sha1` in helpers | Updated base images to Python 3.13.11 | Updated dependencies
186
+ * 6.4.1 - Fix logging on cloud mode to remove `taskName` | Close boto client after assuming role
185
187
  * 6.4.0 - When running in cloud mode, always create a new connection object | Bump Python version to 3.13.9 | Docker build tidyup to reduce image size
186
188
  * 6.3.10 - Fixed tracing name to better allign otel standards
187
189
  * 6.3.9 - Fixed `monitor_task_delay` decorator handling of millisecond epoch timestamps | Allow `test_task` connection method to accept task name parameter | Updated base images to Python 3.11.13
@@ -19,6 +19,7 @@ from insightconnect_plugin_runtime.exceptions import (
19
19
  ConnectionTestException,
20
20
  )
21
21
  from insightconnect_plugin_runtime.helper import clean
22
+ from insightconnect_plugin_runtime.util import is_running_in_cloud
22
23
 
23
24
  REGION = "region"
24
25
  EXTERNAL_ID = "external_id"
@@ -371,6 +372,7 @@ class AWSAction(Action):
371
372
  aws_service: str,
372
373
  aws_command: str,
373
374
  pagination_helper: PaginationHelper = None,
375
+ close_client: bool = None,
374
376
  ):
375
377
  """
376
378
 
@@ -382,6 +384,8 @@ class AWSAction(Action):
382
384
  :param output: The output schema object
383
385
  :param aws_service: The AWS service. Should be snake case.
384
386
  :param aws_command: The type of request to invoke. Should be snake case.
387
+ :param pagination_helper: Paginating helper indicate attrs like max_pages and token location.
388
+ :param close_client: Determine if the created client should be closed at the end of the action.
385
389
  """
386
390
 
387
391
  super().__init__(
@@ -391,6 +395,11 @@ class AWSAction(Action):
391
395
  self.aws_command = aws_command
392
396
  self.pagination_helper = pagination_helper
393
397
 
398
+ # when running in cloud mode we won't hold this connection, so each call to action.run() will spawn a new
399
+ # client, in this case we should close the client unless otherwise specified. A use case to not close
400
+ # is on a task plugin that re-uses the client for list_objects_v2 and get_bucket_content.
401
+ self.close_client = is_running_in_cloud() if close_client is None else close_client
402
+
394
403
  def _handle_botocore_function(
395
404
  self, client_function: Callable, params: Dict
396
405
  ) -> Dict:
@@ -441,6 +450,9 @@ class AWSAction(Action):
441
450
  raise PluginException(
442
451
  cause="Error occurred when invoking the aws-cli.", data=error
443
452
  )
453
+ finally:
454
+ if self.close_client:
455
+ self.connection.client.close()
444
456
  return response
445
457
 
446
458
  def _handle_format_output(self, response: Dict, helper: ActionHelper) -> Dict:
@@ -542,6 +554,9 @@ class AWSAction(Action):
542
554
  if not self.pagination_helper.max_pages:
543
555
  self.pagination_helper.remove_keys(response)
544
556
 
557
+ if self.close_client:
558
+ self.connection.client.close()
559
+
545
560
  return response
546
561
 
547
562
  def test(self, params={}):
@@ -610,14 +625,14 @@ class AWSAction(Action):
610
625
  }
611
626
  )
612
627
  )
628
+ sts_client.close()
613
629
  except ClientError as error:
614
630
  raise PluginException(
615
631
  cause=f"Boto3 raised following error during assume role: {error.response['Error']['Code']}",
616
632
  assistance="Please verify your role ARN and external ID are correct",
617
633
  )
618
634
  credentials = assumed_role_object["Credentials"]
619
- session = botocore.session.Session()
620
- boto_session = session.create_client(
635
+ boto_client = boto3.client(
621
636
  service_name,
622
637
  aws_access_key_id=credentials["AccessKeyId"],
623
638
  aws_secret_access_key=credentials["SecretAccessKey"],
@@ -625,4 +640,4 @@ class AWSAction(Action):
625
640
  region_name=assume_role_params[REGION],
626
641
  )
627
642
 
628
- return boto_session
643
+ return boto_client
@@ -71,7 +71,7 @@ def hash_sha1(log: Dict[str, Any], keys: Optional[List[str]] = None) -> str:
71
71
 
72
72
  # Iterate through items to hash and hash
73
73
  for key, value in items_to_hash:
74
- hash_.update(f"{key}{value}".encode(ENCODE_TYPE))
74
+ hash_.update(f"{key}{value}".encode(ENCODE_TYPE, errors="ignore"))
75
75
 
76
76
  return hash_.hexdigest()
77
77
 
@@ -11,7 +11,7 @@ from apispec.ext.marshmallow import MarshmallowPlugin
11
11
  from apispec_webframeworks.flask import FlaskPlugin
12
12
  from flask import Flask, request_started, request
13
13
  from gunicorn.arbiter import Arbiter
14
- from pythonjsonlogger.jsonlogger import JsonFormatter
14
+ from pythonjsonlogger.jsonlogger import JsonFormatter, RESERVED_ATTRS
15
15
  from requests import get as request_get
16
16
  from requests.exceptions import (
17
17
  HTTPError,
@@ -146,7 +146,8 @@ class PluginServer(gunicorn.app.base.BaseApplication):
146
146
  console_handler = logging.StreamHandler()
147
147
  if is_running_in_cloud():
148
148
  console_handler.setFormatter(
149
- JsonFormatter()
149
+ # since python bump to 3.13 the logging lib now includes a bunch of extra keywords we want to discard
150
+ JsonFormatter(reserved_attrs=RESERVED_ATTRS + ("taskName",))
150
151
  ) # Only log in JSON if running in cloud
151
152
 
152
153
  logger.addHandler(console_handler)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: insightconnect-plugin-runtime
3
- Version: 6.4.0
3
+ Version: 6.4.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
@@ -12,27 +12,27 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Natural Language :: English
13
13
  Classifier: Topic :: Software Development :: Build Tools
14
14
  Description-Content-Type: text/markdown
15
- Requires-Dist: requests==2.32.4
15
+ Requires-Dist: requests==2.32.5
16
16
  Requires-Dist: python_jsonschema_objects==0.5.2
17
17
  Requires-Dist: jsonschema==4.22.0
18
- Requires-Dist: certifi==2025.8.3
19
- Requires-Dist: Flask==3.1.1
18
+ Requires-Dist: certifi==2026.1.4
19
+ Requires-Dist: Flask==3.1.2
20
20
  Requires-Dist: gunicorn==23.0.0
21
- Requires-Dist: greenlet==3.2.3
21
+ Requires-Dist: greenlet==3.3.0
22
22
  Requires-Dist: gevent==25.5.1
23
- Requires-Dist: marshmallow==3.21.0
23
+ Requires-Dist: marshmallow==3.26.2
24
24
  Requires-Dist: apispec==6.5.0
25
25
  Requires-Dist: apispec-webframeworks==1.0.0
26
26
  Requires-Dist: blinker==1.9.0
27
- Requires-Dist: structlog==25.4.0
27
+ Requires-Dist: structlog==25.5.0
28
28
  Requires-Dist: python-json-logger==2.0.7
29
29
  Requires-Dist: Jinja2==3.1.6
30
30
  Requires-Dist: python-dateutil==2.9.0.post0
31
- Requires-Dist: opentelemetry-sdk==1.36.0
32
- Requires-Dist: opentelemetry-instrumentation-flask==0.57b0
33
- Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.36.0
34
- Requires-Dist: opentelemetry-instrumentation-requests==0.57b0
35
- Requires-Dist: urllib3==2.5.0
31
+ Requires-Dist: opentelemetry-sdk==1.39.1
32
+ Requires-Dist: opentelemetry-instrumentation-flask==0.60b1
33
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.39.1
34
+ Requires-Dist: opentelemetry-instrumentation-requests==0.60b1
35
+ Requires-Dist: urllib3==2.6.3
36
36
  Dynamic: author
37
37
  Dynamic: author-email
38
38
  Dynamic: classifier
@@ -63,10 +63,10 @@ to get started.
63
63
 
64
64
  ## Development of the InsightConnect Plugin Runtime
65
65
 
66
- The Python Runtime codebase is built to support Python 3.11.13 as of version 6.2.3. The following dependencies will need
66
+ The Python Runtime codebase is built to support Python 3.13 as of version 6.4.0. The following dependencies will need
67
67
  to be installed when developing or testing the Plugin Runtime:
68
68
 
69
- - Python 3.11.13
69
+ - Python 3.13.11
70
70
  - Docker
71
71
  - make
72
72
  - tox
@@ -226,6 +226,8 @@ contributed. Black is installed as a test dependency and the hook can be initial
226
226
  after cloning this repository.
227
227
 
228
228
  ## Changelog
229
+ * 6.4.2 - Added error handling for `hash_sha1` in helpers | Updated base images to Python 3.13.11 | Updated dependencies
230
+ * 6.4.1 - Fix logging on cloud mode to remove `taskName` | Close boto client after assuming role
229
231
  * 6.4.0 - When running in cloud mode, always create a new connection object | Bump Python version to 3.13.9 | Docker build tidyup to reduce image size
230
232
  * 6.3.10 - Fixed tracing name to better allign otel standards
231
233
  * 6.3.9 - Fixed `monitor_task_delay` decorator handling of millisecond epoch timestamps | Allow `test_task` connection method to accept task name parameter | Updated base images to Python 3.11.13
@@ -0,0 +1,21 @@
1
+ requests==2.32.5
2
+ python_jsonschema_objects==0.5.2
3
+ jsonschema==4.22.0
4
+ certifi==2026.1.4
5
+ Flask==3.1.2
6
+ gunicorn==23.0.0
7
+ greenlet==3.3.0
8
+ gevent==25.5.1
9
+ marshmallow==3.26.2
10
+ apispec==6.5.0
11
+ apispec-webframeworks==1.0.0
12
+ blinker==1.9.0
13
+ structlog==25.5.0
14
+ python-json-logger==2.0.7
15
+ Jinja2==3.1.6
16
+ python-dateutil==2.9.0.post0
17
+ opentelemetry-sdk==1.39.1
18
+ opentelemetry-instrumentation-flask==0.60b1
19
+ opentelemetry-exporter-otlp-proto-http==1.39.1
20
+ opentelemetry-instrumentation-requests==0.60b1
21
+ urllib3==2.6.3
@@ -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.4.0",
8
+ version="6.4.2",
9
9
  description="InsightConnect Plugin Runtime",
10
10
  long_description=long_description,
11
11
  long_description_content_type="text/markdown",
@@ -14,27 +14,27 @@ setup(
14
14
  url="https://github.com/rapid7/komand-plugin-sdk-python",
15
15
  packages=find_packages(),
16
16
  install_requires=[
17
- "requests==2.32.4",
17
+ "requests==2.32.5",
18
18
  "python_jsonschema_objects==0.5.2",
19
19
  "jsonschema==4.22.0",
20
- "certifi==2025.8.3",
21
- "Flask==3.1.1",
20
+ "certifi==2026.1.4",
21
+ "Flask==3.1.2",
22
22
  "gunicorn==23.0.0",
23
- "greenlet==3.2.3",
23
+ "greenlet==3.3.0",
24
24
  "gevent==25.5.1",
25
- "marshmallow==3.21.0",
25
+ "marshmallow==3.26.2",
26
26
  "apispec==6.5.0",
27
27
  "apispec-webframeworks==1.0.0",
28
28
  "blinker==1.9.0",
29
- "structlog==25.4.0",
29
+ "structlog==25.5.0",
30
30
  "python-json-logger==2.0.7",
31
31
  "Jinja2==3.1.6",
32
32
  "python-dateutil==2.9.0.post0",
33
- "opentelemetry-sdk==1.36.0",
34
- "opentelemetry-instrumentation-flask==0.57b0",
35
- "opentelemetry-exporter-otlp-proto-http==1.36.0",
36
- "opentelemetry-instrumentation-requests==0.57b0",
37
- "urllib3==2.5.0"
33
+ "opentelemetry-sdk==1.39.1",
34
+ "opentelemetry-instrumentation-flask==0.60b1",
35
+ "opentelemetry-exporter-otlp-proto-http==1.39.1",
36
+ "opentelemetry-instrumentation-requests==0.60b1",
37
+ "urllib3==2.6.3"
38
38
  ],
39
39
  tests_require=[
40
40
  "pytest",
@@ -3,6 +3,7 @@ import io
3
3
  import json
4
4
  import unittest
5
5
  import unittest.mock
6
+ from os import environ
6
7
  from pathlib import Path
7
8
 
8
9
  import botocore.exceptions as be
@@ -28,6 +29,10 @@ class Boto3Stub:
28
29
  }
29
30
  }
30
31
 
32
+ def close(self):
33
+ # stub for closing the sts client after assuming the role
34
+ pass
35
+
31
36
 
32
37
  class TestAwsAction(unittest.TestCase):
33
38
  def setUp(self) -> None:
@@ -37,6 +42,12 @@ class TestAwsAction(unittest.TestCase):
37
42
  }
38
43
  self.region = "us-east"
39
44
 
45
+ self.assume_role_params = {
46
+ "role_arn": "test_role",
47
+ "external_id": "test_id",
48
+ "region": "test-region",
49
+ }
50
+
40
51
  self.aws_action = AWSAction(
41
52
  "NewAction", "Description", None, None, "ec2", "service"
42
53
  )
@@ -45,19 +56,11 @@ class TestAwsAction(unittest.TestCase):
45
56
  self.aws_action.input = Input({})
46
57
  self.aws_action.output = Output({})
47
58
 
48
- @unittest.mock.patch("botocore.session.Session", return_value=unittest.mock.Mock())
49
59
  @unittest.mock.patch("boto3.client", return_value=Boto3Stub())
50
- def test_assume_role(self, mock_session, mock_sts_client):
51
- assume_role_params = {
52
- "role_arn": "test_role",
53
- "external_id": "test_id",
54
- "region": "test-region",
55
- }
56
- aws_session = unittest.mock.Mock()
57
-
58
- AWSAction.try_to_assume_role("ec2", assume_role_params, self.auth_params)
60
+ def test_assume_role(self, mock_sts_client):
61
+ AWSAction.try_to_assume_role("ec2", self.assume_role_params, self.auth_params)
59
62
 
60
- mock_sts_client.assert_called_once()
63
+ self.assertEqual(mock_sts_client.call_count, 2) # twice for assume role and create client afterwards
61
64
 
62
65
  @unittest.mock.patch("botocore.session.Session", return_value=unittest.mock.Mock())
63
66
  @unittest.mock.patch("boto3.client", return_value=Boto3Stub())
@@ -135,6 +138,58 @@ class TestAwsAction(unittest.TestCase):
135
138
  with self.assertRaises(PluginException):
136
139
  self.aws_action.handle_rest_call(mock_call, {})
137
140
 
141
+ @unittest.mock.patch.dict(environ, {"PLUGIN_RUNTIME_ENVIRONMENT": "orchestrator"})
142
+ @unittest.mock.patch.object(AWSAction, "handle_rest_call", return_value={"mock_key": "mock_value"})
143
+ def test_run_client_non_cloud_mode_in_action_default_behaviour(self, _mock_handle_rest_call):
144
+ # Test AWSAction called for customers running on an orchestrator that their client can remain open
145
+ aws_action = AWSAction("NewAction", "Description", None, None, "s3", "service")
146
+ aws_action.connection = unittest.mock.create_autospec(Connection)
147
+ aws_action.connection.assume_role_params = self.assume_role_params
148
+ aws_action.connection.auth_params = self.auth_params
149
+ aws_action.connection.client = unittest.mock.create_autospec(Boto3Stub)
150
+ aws_action.connection.client.service = unittest.mock.MagicMock()
151
+ aws_action.run()
152
+ aws_action.connection.client.close.assert_not_called()
153
+
154
+ @unittest.mock.patch.dict(environ, {"PLUGIN_RUNTIME_ENVIRONMENT": "cloud"})
155
+ @unittest.mock.patch.object(AWSAction, "handle_rest_call", return_value={"mock_key": "mock_value"})
156
+ def test_run_client_cloud_mode_in_normal_action(self, _mock_handle_rest_call):
157
+ # Test the same AWSAction as above but now running in cloud - we should close this client
158
+ aws_action = AWSAction("NewAction", "Description", None, None, "s3", "service")
159
+ aws_action.connection = unittest.mock.create_autospec(Connection)
160
+ aws_action.connection.assume_role_params = self.assume_role_params
161
+ aws_action.connection.auth_params = self.auth_params
162
+ aws_action.connection.client = unittest.mock.create_autospec(Boto3Stub)
163
+ aws_action.connection.client.service = unittest.mock.MagicMock()
164
+ aws_action.run()
165
+ aws_action.connection.client.close.assert_called_once()
166
+
167
+ @unittest.mock.patch.dict(environ, {"PLUGIN_RUNTIME_ENVIRONMENT": "orchestrator"})
168
+ @unittest.mock.patch.object(AWSAction, "handle_rest_call", return_value={"mock_key": "mock_value"})
169
+ def test_run_client_non_cloud_mode_in_action_default_override(self, _mock_handle_rest_call):
170
+ # Test AWSAction when we have specified to close the client
171
+ aws_action = AWSAction("NewAction", "Description", None, None, "s3", "service", close_client=True)
172
+ aws_action.connection = unittest.mock.create_autospec(Connection)
173
+ aws_action.connection.assume_role_params = self.assume_role_params
174
+ aws_action.connection.auth_params = self.auth_params
175
+ aws_action.connection.client = unittest.mock.create_autospec(Boto3Stub)
176
+ aws_action.connection.client.service = unittest.mock.MagicMock()
177
+ aws_action.run()
178
+ aws_action.connection.client.close.assert_called_once()
179
+
180
+ @unittest.mock.patch.dict(environ, {"PLUGIN_RUNTIME_ENVIRONMENT": "cloud"})
181
+ @unittest.mock.patch.object(AWSAction, "handle_rest_call", return_value={"mock_key": "mock_value"})
182
+ def test_run_client_cloud_mode_in_typical_c2c_task(self, _mock_handle_rest_call):
183
+ # Test AWSAction used within a C2C task, we want to keep the client for subsequent calls
184
+ aws_action = AWSAction("NewAction", "Description", None, None, "s3", "service", close_client=False)
185
+ aws_action.connection = unittest.mock.create_autospec(Connection)
186
+ aws_action.connection.assume_role_params = self.assume_role_params
187
+ aws_action.connection.auth_params = self.auth_params
188
+ aws_action.connection.client = unittest.mock.create_autospec(Boto3Stub)
189
+ aws_action.connection.client.service = unittest.mock.MagicMock()
190
+ aws_action.run()
191
+ aws_action.connection.client.close.assert_not_called()
192
+
138
193
  def mocked_requests_get(*args, **kwargs):
139
194
  class MockResponse:
140
195
  def __init__(self, json_data, status_code):
@@ -64,7 +64,7 @@ class TestCloudConnections(TestCase):
64
64
  def test_running_onprem_has_cached_connection(self):
65
65
  conn = self.connection_cache.get(self.connection, self.logger)
66
66
  self.assertEqual(conn.parameters, self.connection)
67
- self.assertNotEquals(self.connection_cache.connections, {})
67
+ self.assertNotEqual(self.connection_cache.connections, {})
68
68
 
69
69
  # the connection cache key should exist
70
70
  hashed_key = key(conn.parameters)
@@ -81,13 +81,13 @@ class TestCloudConnections(TestCase):
81
81
  # first call the connection cache for the first time adding a new entry
82
82
  conn = self.connection_cache.get(self.connection, self.logger)
83
83
  self.assertEqual(len(self.connection_cache.connections), 1)
84
- self.assertEquals(list(self.connection_cache.connections.values())[0], pretend_obj)
85
- self.assertEquals(conn, pretend_obj)
84
+ self.assertEqual(list(self.connection_cache.connections.values())[0], pretend_obj)
85
+ self.assertEqual(conn, pretend_obj)
86
86
  self.assertEqual(stub_key.call_count, 1)
87
87
 
88
88
  # on a second call we get the same value but the create_and_validate shouldn't be called again
89
89
  conn2 = self.connection_cache.get(self.connection, self.logger)
90
- self.assertEquals(conn, conn2)
90
+ self.assertEqual(conn, conn2)
91
91
  stub_create.assert_called_once_with(self.connection, self.logger)
92
92
 
93
93
  # on a third call we add a new entry to the cached connections
@@ -103,11 +103,11 @@ class TestCloudConnections(TestCase):
103
103
  _conn = self.connection_cache.get(self.connection, self.logger)
104
104
 
105
105
  # this means the connection object is not saved in cache
106
- self.assertEquals(self.connection_cache.connections, {})
106
+ self.assertEqual(self.connection_cache.connections, {})
107
107
 
108
108
  def test_connection_validation_raised(self):
109
109
  with self.assertRaises(Exception): # not the expected input to match the connection schema
110
110
  _conn = self.connection_cache.get({"not_expected_key": "value"}, self.logger)
111
111
 
112
112
  # this means the connection object is not saved in cache
113
- self.assertEquals(self.connection_cache.connections, {})
113
+ self.assertEqual(self.connection_cache.connections, {})
@@ -1,21 +0,0 @@
1
- requests==2.32.4
2
- python_jsonschema_objects==0.5.2
3
- jsonschema==4.22.0
4
- certifi==2025.8.3
5
- Flask==3.1.1
6
- gunicorn==23.0.0
7
- greenlet==3.2.3
8
- gevent==25.5.1
9
- marshmallow==3.21.0
10
- apispec==6.5.0
11
- apispec-webframeworks==1.0.0
12
- blinker==1.9.0
13
- structlog==25.4.0
14
- python-json-logger==2.0.7
15
- Jinja2==3.1.6
16
- python-dateutil==2.9.0.post0
17
- opentelemetry-sdk==1.36.0
18
- opentelemetry-instrumentation-flask==0.57b0
19
- opentelemetry-exporter-otlp-proto-http==1.36.0
20
- opentelemetry-instrumentation-requests==0.57b0
21
- urllib3==2.5.0