insightconnect-plugin-runtime 5.5.2__py3-none-any.whl → 5.5.4__py3-none-any.whl

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.
@@ -634,14 +634,19 @@ class Endpoints:
634
634
  schema = conn.schema
635
635
  return jsonify(ConnectionDetailsSchema().dump(schema))
636
636
 
637
- @v1.route("/connection/test", methods=["POST"])
638
- def connection_test():
637
+ @v1.route("/connection/<string:connection_test_type>", methods=["POST"])
638
+ def connection_test(connection_test_type: str):
639
639
  """
640
640
  Run connection test endpoint
641
641
  ---
642
642
  post:
643
643
  summary: Run connection test
644
644
  description: Run InsightConnect plugin connection test
645
+ parameters:
646
+ - in: path
647
+ name: connection_test_type
648
+ description: Type of connection test to be run
649
+ type: string
645
650
  responses:
646
651
  200:
647
652
  description: Connection test output to be returned
@@ -658,12 +663,26 @@ class Endpoints:
658
663
  status_code = 200
659
664
  output = None
660
665
 
666
+ supported_tests = ["test", "test_task"]
667
+ if connection_test_type not in supported_tests:
668
+ return make_response(
669
+ jsonify(
670
+ {
671
+ "error": f"The requested endpoint is not available, only {supported_tests} are supported.",
672
+ "code": 404,
673
+ "method": "POST",
674
+ "name": "Not Found"
675
+ }
676
+ ),
677
+ 404,
678
+ )
679
+
661
680
  input_message = request.get_json(force=True)
662
681
  Endpoints.validate_action_trigger_task_empty_input(input_message)
663
682
 
664
683
  try:
665
684
  output = self.plugin.handle_step(
666
- input_message, is_debug=self.debug, is_test=True
685
+ input_message, is_debug=self.debug, is_test=True, connection_test_type=connection_test_type
667
686
  )
668
687
  if output.get("body", {}).get("output") is None:
669
688
  status_code = 204
@@ -36,6 +36,7 @@ class PaginationHelper:
36
36
  limit_key: str = None,
37
37
  more_results: str = None,
38
38
  non_aggregate_keys: List[str] = None,
39
+ max_pages : int = None, # if we want to limit how many pages of data we pull from AWS
39
40
  ):
40
41
  self.input_token = input_token
41
42
  self.output_token = output_token
@@ -46,6 +47,7 @@ class PaginationHelper:
46
47
  self.keys_to_remove = []
47
48
  self.keys_to_remove.extend(input_token)
48
49
  self.keys_to_remove.extend(output_token)
50
+ self.max_pages = max_pages
49
51
  if more_results:
50
52
  self.keys_to_remove.append(self.more_results)
51
53
 
@@ -83,6 +85,20 @@ class PaginationHelper:
83
85
 
84
86
  return is_paginated
85
87
 
88
+ def check_total_results(self, params, response: dict[str, Any]) -> bool:
89
+ """
90
+ Check if we have ran the AWS call too many times, eg params[max_keys] * max_pages = len response
91
+ :param params: parameters used within the ListObjectsv2 command
92
+ :param response: response contents from ListObjectsv2
93
+ :return: boolean to indicate if we have reached the max amount of objects to be returned in one execution.
94
+ """
95
+ if self.max_pages:
96
+ max_allowed = params[self.limit_key] * self.max_pages
97
+ if max_allowed >= len(response[self.result_key[0]]):
98
+ return True
99
+
100
+ return False
101
+
86
102
  def merge_responses(
87
103
  self,
88
104
  input_: Dict[str, Any],
@@ -429,7 +445,7 @@ class AWSAction(Action):
429
445
  helper = self.connection.helper
430
446
 
431
447
  # Format the input parameters for the botocall call
432
- self.logger.info(params)
448
+ self.logger.debug(params)
433
449
  try:
434
450
  params = helper.format_input(params)
435
451
  except Exception:
@@ -437,7 +453,7 @@ class AWSAction(Action):
437
453
  raise PluginException(cause="Unable to format input parameters")
438
454
 
439
455
  # Execute the botocore function
440
- self.logger.info(params)
456
+ self.logger.debug(params)
441
457
  response = self._handle_botocore_function(client_function, params)
442
458
 
443
459
  # Format the output parameters for the komand action output schema
@@ -495,13 +511,21 @@ class AWSAction(Action):
495
511
  # Handle possible pagination if this action supports pagination.
496
512
  if self.pagination_helper:
497
513
  while self.pagination_helper.check_pagination(params, response):
514
+ if self.pagination_helper.check_total_results(params, response):
515
+ self.logger.info("Reached max amount of pages per execution breaking...")
516
+ break
517
+
498
518
  self.logger.info("Response was paginated. Performing another call.")
499
519
  response, max_hit = self.pagination_helper.merge_responses(
500
520
  params, self.handle_rest_call(client_function, params), response
501
521
  )
502
- if max_hit:
522
+
523
+ if max_hit: # all data possible in this particular AWS call
503
524
  break
504
- self.pagination_helper.remove_keys(response)
525
+
526
+ # if we have pagination enabled for AWS we want to take note of the tokens
527
+ if not self.pagination_helper.max_pages:
528
+ self.pagination_helper.remove_keys(response)
505
529
 
506
530
  return response
507
531
 
@@ -362,7 +362,7 @@ class Plugin(object):
362
362
  if "input" not in body:
363
363
  body["input"] = {}
364
364
 
365
- def handle_step(self, input_message, is_test=False, is_debug=False):
365
+ def handle_step(self, input_message, is_test=False, is_debug=False, connection_test_type="test"):
366
366
  """
367
367
  Executes a single step, given the input message dictionary.
368
368
 
@@ -427,6 +427,7 @@ class Plugin(object):
427
427
  log_stream,
428
428
  is_test,
429
429
  is_debug,
430
+ connection_test_type=connection_test_type
430
431
  )
431
432
  elif message_type == "trigger_start":
432
433
  out_type = "trigger_event"
@@ -437,6 +438,7 @@ class Plugin(object):
437
438
  log_stream,
438
439
  is_test,
439
440
  is_debug,
441
+ connection_test_type=connection_test_type
440
442
  )
441
443
  elif message_type == "task_start":
442
444
  out_type = "task_event"
@@ -449,6 +451,7 @@ class Plugin(object):
449
451
  log_stream,
450
452
  is_test,
451
453
  is_debug,
454
+ connection_test_type=connection_test_type
452
455
  )
453
456
  else:
454
457
  (
@@ -464,6 +467,7 @@ class Plugin(object):
464
467
  log_stream,
465
468
  is_test,
466
469
  is_debug,
470
+ connection_test_type=connection_test_type
467
471
  )
468
472
  elif message_type == "connection_test":
469
473
  out_type = "connection_test"
@@ -475,6 +479,7 @@ class Plugin(object):
475
479
  is_test,
476
480
  is_debug,
477
481
  is_connection_test=True,
482
+ connection_test_type=connection_test_type
478
483
  )
479
484
  except (ClientException, ServerException, PluginException, Exception) as e:
480
485
  success = False
@@ -513,6 +518,7 @@ class Plugin(object):
513
518
  is_test=False,
514
519
  is_debug=False,
515
520
  is_connection_test=False,
521
+ connection_test_type="test"
516
522
  ):
517
523
  """
518
524
  Starts an action.
@@ -523,6 +529,7 @@ class Plugin(object):
523
529
  :param is_test: True if the action's test method should execute
524
530
  :param is_debug: True if debug is enabled
525
531
  :param is_connection_test: True if connection test is running
532
+ :param connection_test_type: The type of connection test to be run
526
533
  :return: An action_event message
527
534
  """
528
535
  connection = self.connection_cache.get(message_body["connection"], logger)
@@ -534,7 +541,9 @@ class Plugin(object):
534
541
  plugin_version=connection.meta.version,
535
542
  )
536
543
  )
537
- if hasattr(connection, "test"):
544
+ if hasattr(connection, "test_task") and connection_test_type == "test_task":
545
+ func = connection.test_task
546
+ elif hasattr(connection, "test"):
538
547
  func = connection.test
539
548
  else:
540
549
  raise NotImplementedError(
@@ -617,7 +626,10 @@ class Plugin(object):
617
626
  if is_test:
618
627
  # Check if connection test func available. If so - use it (preferred). Else fallback to action/trigger test
619
628
  if hasattr(step.connection, "test"):
620
- func = step.connection.test
629
+ if hasattr(step.connection, "test") and connection_test_type == "test_task":
630
+ func = step.connection.task_test
631
+ else:
632
+ func = step.connection.test
621
633
  else:
622
634
  func = step.test
623
635
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: insightconnect-plugin-runtime
3
- Version: 5.5.2
3
+ Version: 5.5.4
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,8 @@ 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
+ * 5.5.4 - Support pagination parameters within AWS client.
215
+ * 5.5.3 - Adding in a new endpoint that can be called to run a task connection test
214
216
  * 5.5.2 - Address bug with typing for type `List` in Python 3.8
215
217
  * 5.5.1 - Address bug with typing for type `Tuple` in Python 3.8
216
218
  * 5.5.0 - Updated helper class to add `make_request`, `response_handler`, `extract_json`, and `request_error_handling` for HTTP requests, and `hash_sha1` and `compare_and_dedupe_hashes` to provide support for hash comparisons | Add `METHOD_NOT_ALLOWED`, `CONFLICT`, `REDIRECT_ERROR`, and `CONNECTION_ERROR` to PluginException presets
@@ -6,7 +6,7 @@ insightconnect_plugin_runtime/dispatcher.py,sha256=ru7njnyyWE1-oD-VbZJ-Z8tELwvDf
6
6
  insightconnect_plugin_runtime/exceptions.py,sha256=7aYNoGgmV6SugHAQqeQYm1zo2LZm0vgXEGqHmYD7NCo,8260
7
7
  insightconnect_plugin_runtime/helper.py,sha256=XlMGpW2LQYo5KjhJeJtaYRCEDDWjrA9ZW1jP9FDpKpE,31155
8
8
  insightconnect_plugin_runtime/metrics.py,sha256=hf_Aoufip_s4k4o8Gtzz90ymZthkaT2e5sXh5B4LcF0,3186
9
- insightconnect_plugin_runtime/plugin.py,sha256=9k01QqEh78OTs0pMRfnwZcRr-vFe7iyAtLz_QBa23e4,24127
9
+ insightconnect_plugin_runtime/plugin.py,sha256=s2YVyygPcNeXeDi3X_JmaCiLHXZWIqz4mlLJy6p7-UA,24904
10
10
  insightconnect_plugin_runtime/schema.py,sha256=jTNc6KAMqFpaDVWrAYhkVC6e8I63P3X7uVlJkAr1hiY,583
11
11
  insightconnect_plugin_runtime/server.py,sha256=09fxsbKf2ZZvSqRP2Bv9e9-fspDyEFR8_YgIFeMnXqQ,12578
12
12
  insightconnect_plugin_runtime/step.py,sha256=KdERg-789-s99IEKN61DR08naz-YPxyinPT0C_T81C4,855
@@ -15,10 +15,10 @@ insightconnect_plugin_runtime/trigger.py,sha256=Zq3cy68N3QxAGbNZKCID6CZF05Zi7YD2
15
15
  insightconnect_plugin_runtime/util.py,sha256=qPkZ3LA55nYuNYdansEbnCnBccQkpzIpp9NA1B64Kvw,8444
16
16
  insightconnect_plugin_runtime/variables.py,sha256=7FjJGnU7KUR7m9o-_tRq7Q3KiaB1Pp0Apj1NGgOwrJk,3056
17
17
  insightconnect_plugin_runtime/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- insightconnect_plugin_runtime/api/endpoints.py,sha256=57pSoVSyZU6ERPZ6joMUf6eTDXVRCROLJkmtw4DJhUg,31720
18
+ insightconnect_plugin_runtime/api/endpoints.py,sha256=rqieWL71Eu0jIKrspizof4xSyp672xCQxbrQUYdpbbA,32560
19
19
  insightconnect_plugin_runtime/api/schemas.py,sha256=jRmDrwLJTBl-iQOnyZkSwyJlCWg4eNjAnKfD9Eko4z0,2754
20
20
  insightconnect_plugin_runtime/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- insightconnect_plugin_runtime/clients/aws_client.py,sha256=p_s7YLYOeSrBnJl-1gStuNwse6nw4_sl7kz6AKThboY,20465
21
+ insightconnect_plugin_runtime/clients/aws_client.py,sha256=1hAhPD89ELlqtND2Vn46G4yaDG920gBlPg1Tyi02aAU,21658
22
22
  insightconnect_plugin_runtime/clients/oauth.py,sha256=bWtAGRMwdK4dw9vMPcw9usklyIHBDtZh55kMZ7sWROc,2453
23
23
  insightconnect_plugin_runtime/data/input_message_schema.json,sha256=7_BcHi6UOBiVWGrrJHHn5IoddteXjL7GOKETdO9T2DE,1770
24
24
  insightconnect_plugin_runtime/data/output_message_schema.json,sha256=Qya6U-NR5MfOlw4V98VpQzGBVq75eGMUQhI-j3yxOHI,1137
@@ -64,7 +64,7 @@ tests/plugin/hello_world/tests/test_server.py,sha256=7QfMNVsNcRoX5aAL0xM9tXS-ciy
64
64
  tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
65
  tests/unit/test_action.py,sha256=0SVen1qNrFLKKAXMurN9T4NpItpftnSpDZ71AdrGZeo,1683
66
66
  tests/unit/test_api.py,sha256=uZ1dWMmgQ-ZePYjmcZfjc-qOTJsjs20Wic0Uf4U12-8,4441
67
- tests/unit/test_aws_action.py,sha256=uerrNB_cH0J9lnxEaVuVaMxTFZoPXuT9lmtpcwoG34Y,7952
67
+ tests/unit/test_aws_action.py,sha256=eei4uPDx1Y8WcYgAWhiyqBYv5OOHGiZrCvajXC7RHdM,9597
68
68
  tests/unit/test_custom_encoder.py,sha256=KLYyVOTq9MEkZXyhVHqjm5LVSW6uJS4Davgghsw9DGk,2207
69
69
  tests/unit/test_endpoints.py,sha256=LuXOfLBu47rDjGa5YEsOwTZBEdvQdl_C6-r46oxWZA8,6401
70
70
  tests/unit/test_exceptions.py,sha256=t8c67n3ZQPpyzzYPN6TZHpNeE8uKlOSfHJPk71QONuU,4668
@@ -78,7 +78,7 @@ tests/unit/test_server_spec.py,sha256=je97BaktgK0Fiz3AwFPkcmHzYtOJJNqJV_Fw5hrvqX
78
78
  tests/unit/test_trigger.py,sha256=E53mAUoVyponWu_4IQZ0IC1gQ9lakBnTn_9vKN2IZfg,1692
79
79
  tests/unit/test_variables.py,sha256=OUEOqGYZA3Nd5oKk5GVY3hcrWKHpZpxysBJcO_v5gzs,291
80
80
  tests/unit/utils.py,sha256=VooVmfpIgxmglNdtmT32AkEDFxHxyRHLK8RsCWjjYRY,2153
81
- insightconnect_plugin_runtime-5.5.2.dist-info/METADATA,sha256=OHfxHfvU8vRAiFkDevFvTnw39pzjpWuYNkKQWQD9mlE,13636
82
- insightconnect_plugin_runtime-5.5.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
83
- insightconnect_plugin_runtime-5.5.2.dist-info/top_level.txt,sha256=AJtyJOpiFzHxsbHUICTcUKXyrGQ3tZxhrEHsPjJBvEA,36
84
- insightconnect_plugin_runtime-5.5.2.dist-info/RECORD,,
81
+ insightconnect_plugin_runtime-5.5.4.dist-info/METADATA,sha256=4T8uMLK4wr9KtC6eSxa-vn77qsWBbbDfCPA0K6uT3KQ,13779
82
+ insightconnect_plugin_runtime-5.5.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
83
+ insightconnect_plugin_runtime-5.5.4.dist-info/top_level.txt,sha256=AJtyJOpiFzHxsbHUICTcUKXyrGQ3tZxhrEHsPjJBvEA,36
84
+ insightconnect_plugin_runtime-5.5.4.dist-info/RECORD,,
@@ -10,7 +10,7 @@ import botocore.response as br
10
10
  from parameterized import parameterized
11
11
 
12
12
  from insightconnect_plugin_runtime import Input, Output, Connection
13
- from insightconnect_plugin_runtime.clients.aws_client import AWSAction, ActionHelper
13
+ from insightconnect_plugin_runtime.clients.aws_client import AWSAction, ActionHelper, PaginationHelper
14
14
  from insightconnect_plugin_runtime.exceptions import PluginException
15
15
 
16
16
 
@@ -80,6 +80,37 @@ class TestAwsAction(unittest.TestCase):
80
80
  self.aws_action.connection.helper.format_input.assert_called_once()
81
81
  self.aws_action.connection.helper.format_output.assert_called_once()
82
82
 
83
+ @unittest.mock.patch("botocore.session.Session", return_value=unittest.mock.Mock())
84
+ @unittest.mock.patch("boto3.client", return_value=Boto3Stub())
85
+ def test_run_action_pagination(self, mock_session, mock_sts_client):
86
+ """
87
+ Test when max_pages attribute is on the pagination_helper that the response is not cleaned
88
+ allowing the two tokens (next_continuation_token & contination_token) to be returned.
89
+ """
90
+ client_function = getattr(mock_session, "service")
91
+ # Mock connection as we're calling action.run() in this unit test
92
+ self.aws_action.connection.assume_role_params = {}
93
+ self.aws_action.connection.auth_params = {}
94
+ self.aws_action.connection.client = {}
95
+
96
+ self.aws_action.pagination_helper = unittest.mock.create_autospec(PaginationHelper)
97
+ self.aws_action.connection.client = mock_session
98
+
99
+ # First run has no pagination set so we clean the response
100
+ self.aws_action.pagination_helper.max_pages = None
101
+ self.aws_action.run()
102
+
103
+ client_function.assert_called_once()
104
+ self.aws_action.connection.helper.format_input.assert_called_once()
105
+ self.aws_action.connection.helper.format_output.assert_called_once()
106
+ self.aws_action.pagination_helper.remove_keys.assert_called_once()
107
+
108
+ # Call again with max_pages set and this means remove_keys is not called
109
+ self.aws_action.pagination_helper.max_pages = 1
110
+ self.aws_action.pagination_helper.remove_keys.reset_mock()
111
+ self.aws_action.run()
112
+ self.aws_action.pagination_helper.remove_keys.assert_not_called()
113
+
83
114
  def _mock_call_raise_endpoint_connection_error(self):
84
115
  raise be.EndpointConnectionError(**{"endpoint_url": "test_url"})
85
116