diff --git a/plugins/math/.CHECKSUM b/plugins/math/.CHECKSUM index 68b3bde372..123e4b5421 100644 --- a/plugins/math/.CHECKSUM +++ b/plugins/math/.CHECKSUM @@ -1,19 +1,19 @@ { - "spec": "990d9d987b565629ff1bacd185717f6b", - "manifest": "30d28225ce02d2d9698e638a4fc2e656", - "setup": "fc006dbe786e2f5e7636bcc680f077d9", + "spec": "057aaea15b4dac436df277eaf21b1172", + "manifest": "d764412b6d589e5330ece619415a0361", + "setup": "a1e6979da8016ee0b27b09a3440a5305", "schemas": [ { "identifier": "calculate/schema.py", - "hash": "32605e5abb79fe7497f124f7e066417d" + "hash": "488209c1d55a6e8ce927398e58582f1c" }, { "identifier": "max/schema.py", - "hash": "cb99bd0f0f0fcd232900ba3ecfd7f379" + "hash": "b8bbe6c2e6fe58f103861c67785db4c2" }, { "identifier": "connection/schema.py", - "hash": "da5382221ca2a33a2f854e17b068d502" + "hash": "bd524b567f9638ba1c6f7e0c9e45ff2e" } ] } \ No newline at end of file diff --git a/plugins/math/Dockerfile b/plugins/math/Dockerfile index 070f45e0ce..27dd354062 100755 --- a/plugins/math/Dockerfile +++ b/plugins/math/Dockerfile @@ -1,18 +1,17 @@ -FROM rapid7/insightconnect-python-3-38-slim-plugin:4 -# Add any custom package dependencies here -# NOTE: Add pip packages to requirements.txt +FROM --platform=linux/amd64 rapid7/insightconnect-python-3-slim-plugin:6.1.3 -# End package dependencies +LABEL organization=rapid7 +LABEL sdk=python -# Add source code WORKDIR /python/src + ADD ./plugin.spec.yaml /plugin.spec.yaml -ADD . /python/src +ADD ./requirements.txt /python/src/requirements.txt -# Install pip dependencies RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi -# Install plugin +ADD . /python/src + RUN python setup.py build && python setup.py install # User to run plugin code. The two supported users are: root, nobody diff --git a/plugins/math/bin/komand_math b/plugins/math/bin/komand_math index e7106a35bc..64abe8f695 100755 --- a/plugins/math/bin/komand_math +++ b/plugins/math/bin/komand_math @@ -1,12 +1,12 @@ #!/usr/bin/env python -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT import os import json from sys import argv Name = "Math" Vendor = "rapid7" -Version = "1.2.1" +Version = "1.2.2" Description = "Basic mathematical operations" @@ -35,9 +35,9 @@ def main(): connection=connection.Connection() ) self.add_action(actions.Calculate()) - + self.add_action(actions.Max()) - + """Run plugin""" cli = insightconnect_plugin_runtime.CLI(ICONMath()) diff --git a/plugins/math/help.md b/plugins/math/help.md index 12333d5f85..cc3aa19403 100644 --- a/plugins/math/help.md +++ b/plugins/math/help.md @@ -8,109 +8,111 @@ This plugin allows basic arithmetic functions to be performed. * Math Division and multiplication, addition and subtraction # Requirements + +*This plugin does not contain any requirements.* -_This plugin does not contain any requirements._ +# Supported Product Versions + +* 2024-10-09 # Documentation ## Setup - -_This plugin does not contain a connection._ + +*This plugin does not contain a connection.* ## Technical Details ### Actions -#### Max -This action is used to find the largest number from a list of numbers. +#### Calculate -##### Input +This action is used to run a calculation -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|numbers|[]number|None|True|Array of numbers to find the highest value from|None|[1, 5.5, 10, 100.5, 100]| +##### Input +|Name|Type|Default|Required|Description|Enum|Example|Placeholder|Tooltip| +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | +|equation|string|None|True|Equation to calculate. Uses Python arithmetic operators (+, -, /, *, **, %)|None|((3**2) * 3) + 3 - 5|None|None| + Example input: ``` { - "numbers": [ - 1, - 5.5, - 10, - 100.5, - 100 - ] + "equation": "((3**2) * 3) + 3 - 5" } ``` ##### Output -|Name|Type|Required|Description| -|----|----|--------|-----------| -|max|number|True|Highest value number| - +|Name|Type|Required|Description|Example| +| :--- | :--- | :--- | :--- | :--- | +|result|number|True|Result of the arithmetic operation|25| + Example output: ``` { - "max": 100.5 + "result": 25 } ``` -#### Calculate +#### Max -This action is used to run a calculation. +This action is used to find the largest number from a list of numbers ##### Input -|Name|Type|Default|Required|Description|Enum|Example| -|----|----|-------|--------|-----------|----|-------| -|equation|string|None|True|Equation to calculate. Uses Python arithmetic operators (+, -, /, *, **, %)|None|((3**2) * 3) + 3 - 5| - +|Name|Type|Default|Required|Description|Enum|Example|Placeholder|Tooltip| +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | +|numbers|[]number|None|True|Array of numbers to find the highest value from|None|[1, 5.5, 10, 100.5, 100]|None|None| + Example input: ``` { - "equation": "((3**2) * 3) + 3 - 5" + "numbers": [ + 1, + 5.5, + 10, + 100.5, + 100 + ] } ``` ##### Output -|Name|Type|Required|Description| -|----|----|--------|-----------| -|result|number|True|Result of the arithmetic operation| - +|Name|Type|Required|Description|Example| +| :--- | :--- | :--- | :--- | :--- | +|max|number|True|Highest value number|100.5| + Example output: ``` - { - "result": 25.0 + "max": 100.5 } - ``` - ### Triggers - -_This plugin does not contain any triggers._ - + +*This plugin does not contain any triggers.* ### Tasks + +*This plugin does not contain any tasks.* -_This plugin does not contain any tasks._ - -### Custom Output Types - -_This plugin does not contain any custom output types._ +### Custom Types + +*This plugin does not contain any custom output types.* ## Troubleshooting - -_This plugin does not contain any troubleshooting information._ + +*This plugin does not contain a troubleshooting.* # Version History +* 1.2.2 - Initial updates for fedramp compliance | Updated SDK to the latest version * 1.2.1 - Update to v4 Python plugin runtime * 1.2.0 - New action Max * 1.1.3 - Change docker image from `komand/python-pypy3-plugin:2` to `komand/python-3-37-slim-plugin:3` to reduce plugin image size | Changed `Exception` to `PluginException` | Use input and output constants | Remove not secure eval for simple_eval @@ -122,7 +124,8 @@ _This plugin does not contain any troubleshooting information._ # Links -## References - * [Arithmetic](https://en.wikipedia.org/wiki/Arithmetic) +## References + +* [Arithmetic](https://en.wikipedia.org/wiki/Arithmetic) \ No newline at end of file diff --git a/plugins/math/komand_math/actions/__init__.py b/plugins/math/komand_math/actions/__init__.py index d6267c1744..4dca13f5f9 100755 --- a/plugins/math/komand_math/actions/__init__.py +++ b/plugins/math/komand_math/actions/__init__.py @@ -1,3 +1,6 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + from .calculate.action import Calculate + from .max.action import Max + diff --git a/plugins/math/komand_math/actions/calculate/__init__.py b/plugins/math/komand_math/actions/calculate/__init__.py index 76aa74a830..327a172e34 100755 --- a/plugins/math/komand_math/actions/calculate/__init__.py +++ b/plugins/math/komand_math/actions/calculate/__init__.py @@ -1,2 +1,2 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT from .action import Calculate diff --git a/plugins/math/komand_math/actions/calculate/action.py b/plugins/math/komand_math/actions/calculate/action.py index f72ee556b4..2d305ee9e1 100755 --- a/plugins/math/komand_math/actions/calculate/action.py +++ b/plugins/math/komand_math/actions/calculate/action.py @@ -1,8 +1,11 @@ +from typing import Union + import insightconnect_plugin_runtime -from .schema import CalculateInput, CalculateOutput, Input, Output, Component from insightconnect_plugin_runtime.exceptions import PluginException from simpleeval import simple_eval +from .schema import CalculateInput, CalculateOutput, Component, Input, Output + class Calculate(insightconnect_plugin_runtime.Action): _result = None @@ -16,19 +19,29 @@ def __init__(self): ) def run(self, params={}): - equation = params.get(Input.EQUATION) - result = Calculate.execute_equation(equation) + # START INPUT BINDING - DO NOT REMOVE - ANY INPUTS BELOW WILL UPDATE WITH YOUR PLUGIN SPEC AFTER REGENERATION + equation = params.get(Input.EQUATION, "") + # END INPUT BINDING - DO NOT REMOVE + try: + result = Calculate.execute_equation(equation) + except Exception as error: + raise PluginException(preset=PluginException.Preset.UNKNOWN, data=error) if result is None: raise PluginException( cause="Calculation error", assistance="Error occurred while calculating the equation. Check to make sure it is valid and try " - "again. ", + "again.", ) - return {Output.RESULT: result} @staticmethod - def execute_equation(eq): - eq = str().join([c for c in eq if (c.isdecimal() or c in ["+", "-", "*", "/", "**", "%", "(", ")", "."])]) - return simple_eval(eq) + def execute_equation(equation) -> Union[int, float]: + equation = str().join( + [ + character + for character in equation + if (character.isdecimal() or character in ["+", "-", "*", "/", "**", "%", "(", ")", "."]) + ] + ) + return simple_eval(equation) diff --git a/plugins/math/komand_math/actions/calculate/schema.py b/plugins/math/komand_math/actions/calculate/schema.py index 98bfcf454c..0fa9f44ef0 100755 --- a/plugins/math/komand_math/actions/calculate/schema.py +++ b/plugins/math/komand_math/actions/calculate/schema.py @@ -1,4 +1,4 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT import insightconnect_plugin_runtime import json @@ -9,14 +9,14 @@ class Component: class Input: EQUATION = "equation" - + class Output: RESULT = "result" - + class CalculateInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" + schema = json.loads(r""" { "type": "object", "title": "Variables", @@ -30,7 +30,8 @@ class CalculateInput(insightconnect_plugin_runtime.Input): }, "required": [ "equation" - ] + ], + "definitions": {} } """) @@ -39,7 +40,7 @@ def __init__(self): class CalculateOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" + schema = json.loads(r""" { "type": "object", "title": "Variables", @@ -53,7 +54,8 @@ class CalculateOutput(insightconnect_plugin_runtime.Output): }, "required": [ "result" - ] + ], + "definitions": {} } """) diff --git a/plugins/math/komand_math/actions/max/__init__.py b/plugins/math/komand_math/actions/max/__init__.py index e4efaa67c5..be78105847 100755 --- a/plugins/math/komand_math/actions/max/__init__.py +++ b/plugins/math/komand_math/actions/max/__init__.py @@ -1,2 +1,2 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT from .action import Max diff --git a/plugins/math/komand_math/actions/max/action.py b/plugins/math/komand_math/actions/max/action.py index 1196fdd35d..a897d31863 100755 --- a/plugins/math/komand_math/actions/max/action.py +++ b/plugins/math/komand_math/actions/max/action.py @@ -1,5 +1,7 @@ import insightconnect_plugin_runtime -from .schema import MaxInput, MaxOutput, Input, Output, Component +from insightconnect_plugin_runtime.exceptions import PluginException + +from .schema import Component, Input, MaxInput, MaxOutput, Output # Custom imports below @@ -11,5 +13,11 @@ def __init__(self): ) def run(self, params={}): - numbers = params.get(Input.NUMBERS) - return {"max": max(numbers)} + # START INPUT BINDING - DO NOT REMOVE - ANY INPUTS BELOW WILL UPDATE WITH YOUR PLUGIN SPEC AFTER REGENERATION + numbers = params.get(Input.NUMBERS, []) + # END INPUT BINDING - DO NOT REMOVE + + try: + return {Output.MAX: max(numbers)} + except Exception as error: + raise PluginException(preset=PluginException.Preset.UNKNOWN, data=error) diff --git a/plugins/math/komand_math/actions/max/schema.py b/plugins/math/komand_math/actions/max/schema.py index ca2209370c..937e283c95 100755 --- a/plugins/math/komand_math/actions/max/schema.py +++ b/plugins/math/komand_math/actions/max/schema.py @@ -1,4 +1,4 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT import insightconnect_plugin_runtime import json @@ -9,14 +9,14 @@ class Component: class Input: NUMBERS = "numbers" - + class Output: MAX = "max" - + class MaxInput(insightconnect_plugin_runtime.Input): - schema = json.loads(""" + schema = json.loads(r""" { "type": "object", "title": "Variables", @@ -33,7 +33,8 @@ class MaxInput(insightconnect_plugin_runtime.Input): }, "required": [ "numbers" - ] + ], + "definitions": {} } """) @@ -42,7 +43,7 @@ def __init__(self): class MaxOutput(insightconnect_plugin_runtime.Output): - schema = json.loads(""" + schema = json.loads(r""" { "type": "object", "title": "Variables", @@ -56,7 +57,8 @@ class MaxOutput(insightconnect_plugin_runtime.Output): }, "required": [ "max" - ] + ], + "definitions": {} } """) diff --git a/plugins/math/komand_math/connection/__init__.py b/plugins/math/komand_math/connection/__init__.py index a515dcf6b0..c78d3356be 100755 --- a/plugins/math/komand_math/connection/__init__.py +++ b/plugins/math/komand_math/connection/__init__.py @@ -1,2 +1,2 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT from .connection import Connection diff --git a/plugins/math/komand_math/connection/connection.py b/plugins/math/komand_math/connection/connection.py index 21e34a7004..9008440092 100755 --- a/plugins/math/komand_math/connection/connection.py +++ b/plugins/math/komand_math/connection/connection.py @@ -2,14 +2,15 @@ from .schema import ConnectionSchema # Custom imports below +from typing import Dict class Connection(insightconnect_plugin_runtime.Connection): def __init__(self): super(self.__class__, self).__init__(input=ConnectionSchema()) - def connect(self, params): + def connect(self, params={}): pass - def test(self): - return {"result": 0} + def test(self) -> Dict[str, bool]: + return {"success": True} diff --git a/plugins/math/komand_math/connection/schema.py b/plugins/math/komand_math/connection/schema.py index b93c5a7c44..10cc2e684f 100755 --- a/plugins/math/komand_math/connection/schema.py +++ b/plugins/math/komand_math/connection/schema.py @@ -1,4 +1,4 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT import insightconnect_plugin_runtime import json @@ -6,8 +6,9 @@ class Input: pass + class ConnectionSchema(insightconnect_plugin_runtime.Input): - schema = json.loads(""" + schema = json.loads(r""" {} """) diff --git a/plugins/math/komand_math/tasks/__init__.py b/plugins/math/komand_math/tasks/__init__.py index bace8db897..7020c9a4ad 100755 --- a/plugins/math/komand_math/tasks/__init__.py +++ b/plugins/math/komand_math/tasks/__init__.py @@ -1 +1,2 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + diff --git a/plugins/math/komand_math/triggers/__init__.py b/plugins/math/komand_math/triggers/__init__.py index bace8db897..7020c9a4ad 100755 --- a/plugins/math/komand_math/triggers/__init__.py +++ b/plugins/math/komand_math/triggers/__init__.py @@ -1 +1,2 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT + diff --git a/plugins/math/plugin.spec.yaml b/plugins/math/plugin.spec.yaml index 0976488fde..0aeaea4470 100644 --- a/plugins/math/plugin.spec.yaml +++ b/plugins/math/plugin.spec.yaml @@ -4,23 +4,47 @@ products: [insightconnect] name: math title: Math description: Basic mathematical operations -version: 1.2.1 +version: 1.2.2 +connection_version: 1 vendor: rapid7 support: community +supported_versions: ["2024-10-09"] status: [] cloud_ready: true +fedramp_ready: true resources: source_url: https://github.com/rapid7/insightconnect-plugins/tree/master/plugins/math license_url: https://github.com/rapid7/insightconnect-plugins/blob/master/LICENSE tags: -- math -- computation -- utilities -- calculator + - math + - computation + - utilities + - calculator hub_tags: use_cases: [data_utility] keywords: [math, computation, utilities, calculator, cloud_enabled] features: [] +sdk: + type: slim + version: 6.1.3 + user: nobody +key_features: + - "Math operations module and exponents" + - "Math Division and multiplication, addition and subtraction" +version_history: + - "1.2.2 - Initial updates for fedramp compliance | Updated SDK to the latest version" + - "1.2.1 - Update to v4 Python plugin runtime" + - "1.2.0 - New action Max" + - "1.1.3 - Change docker image from `komand/python-pypy3-plugin:2` to `komand/python-3-37-slim-plugin:3` to reduce plugin image size | Changed `Exception` to `PluginException` | Use input and output constants | Remove not secure eval for simple_eval" + - "1.1.2 - New spec and help.md format for the Extension Library" + - "1.1.1 - Update plugin tag from `utility` to `utilities` for Marketplace searchability" + - "1.1.0 - Update to v2 Python plugin architecture | Support web server mode" + - "1.0.0 - Update Calculate action: Allow freeform input" + - "0.1.0 - Initial plugin" +links: + - "[Arithmetic](https://en.wikipedia.org/wiki/Arithmetic)" +references: + - "[Arithmetic](https://en.wikipedia.org/wiki/Arithmetic)" actions: calculate: title: Calculate @@ -39,6 +63,7 @@ actions: description: Result of the arithmetic operation type: number required: true + example: 25 max: title: Max description: Find the largest number from a list of numbers @@ -55,3 +80,4 @@ actions: description: Highest value number type: number required: true + example: 100.5 diff --git a/plugins/math/requirements.txt b/plugins/math/requirements.txt index b399e3f05d..6b48a6890a 100755 --- a/plugins/math/requirements.txt +++ b/plugins/math/requirements.txt @@ -1,4 +1,5 @@ # List third-party dependencies here, separated by newlines. # All dependencies must be version-pinned, eg. requests==1.2.0 # See: https://pip.pypa.io/en/stable/user_guide/#requirements-files -simpleeval==0.9.10 \ No newline at end of file +simpleeval==0.9.13 +parameterized==0.8.1 diff --git a/plugins/math/setup.py b/plugins/math/setup.py index 51a3bdf6b5..0f38b7e869 100755 --- a/plugins/math/setup.py +++ b/plugins/math/setup.py @@ -1,9 +1,9 @@ -# GENERATED BY KOMAND SDK - DO NOT EDIT +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT from setuptools import setup, find_packages setup(name="math-rapid7-plugin", - version="1.2.1", + version="1.2.2", description="Basic mathematical operations", author="rapid7", author_email="", diff --git a/plugins/math/unit_test/__init__.py b/plugins/math/unit_test/__init__.py new file mode 100644 index 0000000000..d9ae09fc16 --- /dev/null +++ b/plugins/math/unit_test/__init__.py @@ -0,0 +1,4 @@ +# GENERATED BY INSIGHT-PLUGIN - DO NOT EDIT +import sys + +sys.path.append("../") \ No newline at end of file diff --git a/plugins/math/unit_test/test_calculate.py b/plugins/math/unit_test/test_calculate.py new file mode 100644 index 0000000000..d76ff8c108 --- /dev/null +++ b/plugins/math/unit_test/test_calculate.py @@ -0,0 +1,46 @@ +import os +import sys + +from insightconnect_plugin_runtime.exceptions import PluginException + +sys.path.append(os.path.abspath("../")) + +from typing import Any, Dict +from unittest import TestCase + +from jsonschema import validate +from komand_math.actions.calculate import Calculate +from komand_math.actions.calculate.schema import Input, Output +from parameterized import parameterized + + +class TestCalculate(TestCase): + def setUp(self) -> None: + self.action = Calculate() + + @parameterized.expand( + [ + ({Input.EQUATION: "2 + 2"}, {Output.RESULT: 4}), + ({Input.EQUATION: "10 - 2"}, {Output.RESULT: 8}), + ({Input.EQUATION: "2 * 2 * 3"}, {Output.RESULT: 12}), + ] + ) + def test_calculate(self, input_parameters: Dict[str, Any], expected: Dict[str, Any]) -> None: + response = self.action.run(input_parameters) + validate(response, self.action.output.schema) + self.assertEqual(response, expected) + + @parameterized.expand( + [ + ( + {Input.EQUATION: "Wrong"}, + PluginException.causes[PluginException.Preset.UNKNOWN], + PluginException.assistances[PluginException.Preset.UNKNOWN], + ) + ] + ) + def test_calculate_error(self, input_parameters: Dict[str, Any], cause: str, assistance: str) -> None: + with self.assertRaises(PluginException) as context: + self.action.run(input_parameters) + self.assertEqual(context.exception.cause, cause) + self.assertEqual(context.exception.assistance, assistance) diff --git a/plugins/math/unit_test/test_max.py b/plugins/math/unit_test/test_max.py new file mode 100644 index 0000000000..32a2cb9226 --- /dev/null +++ b/plugins/math/unit_test/test_max.py @@ -0,0 +1,45 @@ +import os +import sys + +sys.path.append(os.path.abspath("../")) + +from typing import Any, Dict +from unittest import TestCase + +from insightconnect_plugin_runtime.exceptions import PluginException +from jsonschema import validate +from komand_math.actions.max import Max +from komand_math.actions.max.schema import Input, Output +from parameterized import parameterized + + +class TestMax(TestCase): + def setUp(self) -> None: + self.action = Max() + + @parameterized.expand( + [ + ({Input.NUMBERS: [1, 2, 3, 4]}, {Output.MAX: 4}), + ({Input.NUMBERS: [-2, 10.5, 100.5, 20, 2012]}, {Output.MAX: 2012}), + ({Input.NUMBERS: [0, 0]}, {Output.MAX: 0}), + ] + ) + def test_max(self, input_parameters: Dict[str, Any], expected: Dict[str, Any]) -> None: + response = self.action.run(input_parameters) + validate(response, self.action.output.schema) + self.assertEqual(response, expected) + + @parameterized.expand( + [ + ( + {Input.NUMBERS: 0}, + PluginException.causes[PluginException.Preset.UNKNOWN], + PluginException.assistances[PluginException.Preset.UNKNOWN], + ) + ] + ) + def test_max_error(self, input_parameters: Dict[str, Any], cause: str, assistance: str) -> None: + with self.assertRaises(PluginException) as context: + self.action.run(input_parameters) + self.assertEqual(context.exception.cause, cause) + self.assertEqual(context.exception.assistance, assistance)