diff --git a/Packs/PenfieldAI/.pack-ignore b/Packs/PenfieldAI/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/PenfieldAI/.secrets-ignore b/Packs/PenfieldAI/.secrets-ignore new file mode 100644 index 000000000000..7b5f7948bb9b --- /dev/null +++ b/Packs/PenfieldAI/.secrets-ignore @@ -0,0 +1,88 @@ +FE80:0000:0000:0000:0202:B3FF:FE1E:8329 +2001:0db8:85a3:0000:0000:8a2e:0370:7334 +2001:0db8:85a3:1337:0000:8a2e:0370:7334 +2001:db8:a0b:12f0::1 +1.1.1.1 +user@example.com +8.8.8.8 +192.168.1.1 +192.168.1.12 +6.6.6.6 +2001:db8:a0b:12f0::1aaa +http://example.com +2001:db8:a0b:12f0::98aa +FE80::0202:B3FF:FE1E:8329 +10.10.10.10 +https://exchange.xforce.ibmcloud.com +user@example.com +8.8.8.8 +https://google.com +https://example.com +https://docs.microsoft.com +192.168.0.0 +10.0.0.0 +172.16.0.0 +127.0.0.0 +169.254.0.0 +https://192.12.12.3 +192.12.12.3 +192.168.2.1 +https://some_url.com +xsoar.pan.dev +@test.com +registrar@test.com +11.111.11.11 +::deb +http://www.letsseeifyoucanfindthisone4444.co.il +111.11.11.111 +https://www.a.com +http://www.c.com +mt.kb.user@gmail.com +@pytest.mark.parametrize +1::6:7:8 +1:2:3:4:5:6::8 +1:2::8 +1:2:3:4::8 +['::2:3:4:5:6:7:8', '1::3:4:5:6:7:8'] +::2:3:4:5:6:7:8 +1::3:4:5:6:7:8 +a@gmail.com +1a:2b::4c:5:6:7:8 +1a:2b::4c:5abc +['1a:2b::4c:5:6:7:8', '1a:2b::4c:5abc'] +DBotScoreType.FILE, +2.5.29.17 +2.5.29.14 +2.5.29.15 +2.5.29.37 +2.5.29.35 +2.5.29.31 +2.5.29.32 +['1.3.6.1', '5.5.7.1'] +2.5.29.19 +1.3.6.1 +:attr:`Retry.BACKOFF_MAX`. +dict_safe_get(dict,['something', +http://crl3.digicert.com +http://crl4.digicert.com +https://www.digicert.com +http://ocsp.digicert.com +http://cacerts.digicert.com +KEY-----\\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFw' +KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFw' +key_identifier="0f80611c823161d52f28e78d4638b42ce1c6d9e2" +digest="b34972bb12121b8851cd5564ff9656dcbca3f288", +log_id="f65c942fd1773022145418083094568ee34d131933bfdf0c2f200bcc4ef164e3", +log_id="5cdc4392fee6ab4544b15e9ad456e61037fbd5fa47dca17394b25ee6f6c70eca", +sha256='bc33cf76519f1ec5ae7f287f321df33a7afd4fd553f364cf3c753f91ba689f8d', +sha1='2392ea5cd4c2a61e51547570634ef887ab1942e9', +spki_sha256='94b716aeda21cd661949cfbf3f55457a277da712cdce0ab31989a4f288fad9b9', +"2392ea5cd4c2a61e51547570634ef887ab1942e9", +"94b716aeda21cd661949cfbf3f55457a277da712cdce0ab31989a4f288fad9b9", +2.23.140.1 +'53e6baa124f54462786f1122e98e38ff1be3de82fe2a96b1849a8637043fd847eec7e0f53307bddf7a066565292d500c36c941f1f3bb9dcac807b2f4a0bfce1b', +http://proxy +http://testproxy +https://testproxy +http://165.225.225.99 +165.225.225.99 diff --git a/Packs/PenfieldAI/Author_image.png b/Packs/PenfieldAI/Author_image.png new file mode 100644 index 000000000000..c3c118e6f971 Binary files /dev/null and b/Packs/PenfieldAI/Author_image.png differ diff --git a/Packs/PenfieldAI/Integrations/Penfield/Penfield.py b/Packs/PenfieldAI/Integrations/Penfield/Penfield.py new file mode 100644 index 000000000000..6c3a9c2140a2 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Penfield.py @@ -0,0 +1,112 @@ +import urllib3 +import traceback +import demistomock as demisto +from CommonServerPython import * # pylint: disable=unused-wildcard-import +from CommonServerUserPython import * # noqa + + +# Disable insecure warnings +urllib3.disable_warnings() + +''' CLIENT CLASS ''' + + +class Client(BaseClient): + def live_assign_get(self, analyst_ids, category, created, arg_id, name, severity) -> str: + params = assign_params( + analyst_ids=analyst_ids, + category=category, + created=created, + id=arg_id, + name=name, + severity=severity + ) + response = self._http_request( + method='POST', + url_suffix='/api/v1/xsoar_live_assign/', + params=params + ) + return response['analyst'] + + def test(self) -> str: + response = self._http_request( + method='GET', + url_suffix='/api/v1/xsoar_live_assign/' + ) + return response + + +''' HELPER FUNCTIONS ''' + + +def get_assignee(client: Client, args) -> CommandResults: + analyst_ids = argToList(args.get('analyst_ids')) + category = args.get('category') + created = args.get('created') + arg_id = args.get('id') + name = args.get('name') + severity = args.get('severity') + analyst = client.live_assign_get(analyst_ids, category, created, arg_id, name, severity) + human_readable = tableToMarkdown( + 'Analyst Penfield Recommends', + analyst, + headers=['Recommendation'], + headerTransform=pascalToSpace, + removeNull=True + ) + return CommandResults( + readable_output=human_readable, + outputs_prefix='Penfield.Recommended', + outputs_key_field='Analyst', + outputs=analyst + ) + + +def test_api(client: Client): + return client.test() + + +''' MAIN FUNCTION ''' + + +def main() -> None: + api_key = demisto.params().get('apikey') + base_url = urljoin(demisto.params()['url'], '') + verify_certificate = not demisto.params().get('insecure', False) + proxy = demisto.params().get('proxy', False) + + demisto.debug(f'Command being called is {demisto.command()}') + try: + headers = { + 'Authorization': f'Bearer {api_key}' + } + client = Client( + base_url=base_url, + verify=verify_certificate, + headers=headers, + proxy=proxy + ) + + if demisto.command() == 'test-module': + result = test_api(client) + if int(result) == 0: + return_results('ok') + else: + raise RuntimeError('Penfield API cannot be reached') + + elif demisto.command() == 'penfield-get-assignee': + result = get_assignee(client, demisto.args()) + return_results(result) + + # Log exceptions and return errors + except Exception as e: + demisto.error(traceback.format_exc()) # print the traceback + return_error( + f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}' + ) + + +''' ENTRY POINT ''' + +if __name__ in ('__main__', '__builtin__', 'builtins'): + main() diff --git a/Packs/PenfieldAI/Integrations/Penfield/Penfield.yml b/Packs/PenfieldAI/Integrations/Penfield/Penfield.yml new file mode 100644 index 000000000000..c6c5d355a49d --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Penfield.yml @@ -0,0 +1,74 @@ +category: Case Management +commonfields: + id: Penfield + version: -1 +configuration: +- defaultvalue: https://example.com/ + display: Your server URL + name: url + required: true + type: 0 +- display: API Key + additionalinfo: The API Key to use for connection + name: apikey + required: true + type: 4 +- display: Trust any certificate (not secure) + name: insecure + required: false + type: 8 +- display: Use system proxy settings + name: proxy + required: false + type: 8 +description: "The penfield-get-assignee command takes in necessary context data, and returns\ + \ the analyst that Penfield believes the incident should be assigned to based on\ + \ Penfield's models of skill and process. The test command verfies that the endpoint\ + \ is reachable." +display: 'Penfield' +name: Penfield +script: + commands: + - name: penfield-get-assignee + description: 'Calls the Penfield API and returns the analyst Penfield recommends + assigning the incident to. This information is saved in the output, but the + incident will not be automatically assigned.' + outputs: + - contextPath: Penfield.Recommended.Analyst + description: The XSOAR analyst Penfield recommends assigning the incident to. + type: String + arguments: + - name: analyst_ids + description: 'An array of XSOAR analyst IDs for Penfield to choose from when + determining who to assign to.' + required: true + isArray: true + - name: category + required: true + description: 'The category of the incident to assign. Can be taken from incident + Context Data.' + - name: created + required: true + description: 'The creation_date of the incident to assign. Can be taken from + incident Context Data.' + - name: id + required: true + description: 'The id of the incident to assign. Can be taken from incident Context + Data.' + - name: name + required: true + description: 'The name of the incident to assign. Can be taken from incident + Context Data.' + - name: severity + required: true + description: 'The severity of the incident to assign. Can be taken from incident + Context Data.' + isfetch: false + runonce: false + script: '-' + type: python + subtype: python3 + dockerimage: demisto/python3:3.9.8.24399 +fromversion: 6.0.0 +tests: +- No tests (auto formatted) diff --git a/Packs/PenfieldAI/Integrations/Penfield/Penfield_description.md b/Packs/PenfieldAI/Integrations/Penfield/Penfield_description.md new file mode 100644 index 000000000000..ee5046bd64ef --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Penfield_description.md @@ -0,0 +1,3 @@ +## Integration Help + +For this integration, you will need to have a deployed instance of PenfieldCore. Please contact Penfield to get this done. During the setup process, Penfield will provide an API key and the URL of the endpoint, which will vary depending upon how the setup was performed. \ No newline at end of file diff --git a/Packs/PenfieldAI/Integrations/Penfield/Penfield_image.png b/Packs/PenfieldAI/Integrations/Penfield/Penfield_image.png new file mode 100644 index 000000000000..c3c118e6f971 Binary files /dev/null and b/Packs/PenfieldAI/Integrations/Penfield/Penfield_image.png differ diff --git a/Packs/PenfieldAI/Integrations/Penfield/Penfield_test.py b/Packs/PenfieldAI/Integrations/Penfield/Penfield_test.py new file mode 100644 index 000000000000..9af08f7363d6 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Penfield_test.py @@ -0,0 +1,56 @@ +import demistomock as demisto +from Penfield import main, get_assignee, Client +import json +import io + + +def util_load_json(path): + with io.open(path, mode='r', encoding='utf-8') as f: + return json.loads(f.read()) + + +def test_main(mocker): + mock_users = "username1,username2" + mock_incident = util_load_json('test_data/test_incident.json') + + mocker.patch.object(demisto, 'command', return_value="penfield-get-assignee") + mocker.patch.object(demisto, 'args', return_value={'analysts': mock_users, 'incident': mock_incident}) + mocker.patch('Penfield.get_assignee', return_value="test") + mocker.patch.object(demisto, 'results') + mocker.patch.object(demisto, 'params', return_value={'url': 'https://fakeurl.ai/api/v1/xsoar_live_assign/'}) + + main() + + assert demisto.results.call_args.args[0] == 'test' + + +def test_get_assignee(mocker): + + mock_users = "username1,username2" + + mocker.patch.object(demisto, 'args', return_value={ + 'analyst_ids': mock_users, + 'category': 'test_category', + 'created': '2021-03-02', + 'arg_id': 123, + 'name': 'test name', + 'severity': 'high' + }) + mocker.patch('Penfield.Client.live_assign_get', return_value="test_cr_response") + + api_key = demisto.params().get('apikey') + base_url = 'https://test.com' + verify_certificate = not demisto.params().get('insecure', False) + proxy = demisto.params().get('proxy', False) + + headers = { + 'Authorization': f'Bearer {api_key}' + } + client = Client( + base_url=base_url, + verify=verify_certificate, + headers=headers, + proxy=proxy + ) + + assert type(get_assignee(client, demisto.args())).__name__ == "CommandResults" diff --git a/Packs/PenfieldAI/Integrations/Penfield/Pipfile b/Packs/PenfieldAI/Integrations/Penfield/Pipfile new file mode 100644 index 000000000000..3523d3b6b93b --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Pipfile @@ -0,0 +1,18 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +pylint = "*" +pytest = "==5.0.1" +pytest-mock = "*" +requests-mock = "*" +pytest-asyncio = "*" + +[packages] +pytest = "*" +requests = "*" + +[requires] +python_version = "3.7" diff --git a/Packs/PenfieldAI/Integrations/Penfield/Pipfile.lock b/Packs/PenfieldAI/Integrations/Penfield/Pipfile.lock new file mode 100644 index 000000000000..6bdb9313414e --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/Pipfile.lock @@ -0,0 +1,369 @@ +{ + "_meta": { + "hash": { + "sha256": "278db815bec49c11262633d34305f9b33f09432a223bedd5329a04f758f78b55" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, + "certifi": { + "hashes": [ + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + ], + "version": "==2019.9.11" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "importlib-metadata": { + "hashes": [ + "sha256:652234b6ab8f2506ae58e528b6fbcc668831d3cc758e1bc01ef438d328b68cdb", + "sha256:6f264986fb88042bc1f0535fa9a557e6a376cfe5679dc77caac7fe8b5d43d05f" + ], + "markers": "python_version < '3.8'", + "version": "==0.22" + }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "version": "==7.2.0" + }, + "packaging": { + "hashes": [ + "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", + "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" + ], + "version": "==19.1" + }, + "pluggy": { + "hashes": [ + "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", + "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" + ], + "version": "==0.13.0" + }, + "py": { + "hashes": [ + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + ], + "version": "==1.8.0" + }, + "pyparsing": { + "hashes": [ + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" + ], + "version": "==2.4.2" + }, + "pytest": { + "hashes": [ + "sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210", + "sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865" + ], + "index": "pypi", + "version": "==5.1.2" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "urllib3": { + "hashes": [ + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + ], + "version": "==1.25.3" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "version": "==0.6.0" + } + }, + "develop": { + "astroid": { + "hashes": [ + "sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4", + "sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4" + ], + "version": "==2.2.5" + }, + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, + "certifi": { + "hashes": [ + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + ], + "version": "==2019.9.11" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "importlib-metadata": { + "hashes": [ + "sha256:652234b6ab8f2506ae58e528b6fbcc668831d3cc758e1bc01ef438d328b68cdb", + "sha256:6f264986fb88042bc1f0535fa9a557e6a376cfe5679dc77caac7fe8b5d43d05f" + ], + "markers": "python_version < '3.8'", + "version": "==0.22" + }, + "isort": { + "hashes": [ + "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", + "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" + ], + "version": "==4.3.21" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:02b260c8deb80db09325b99edf62ae344ce9bc64d68b7a634410b8e9a568edbf", + "sha256:18f9c401083a4ba6e162355873f906315332ea7035803d0fd8166051e3d402e3", + "sha256:1f2c6209a8917c525c1e2b55a716135ca4658a3042b5122d4e3413a4030c26ce", + "sha256:2f06d97f0ca0f414f6b707c974aaf8829c2292c1c497642f63824119d770226f", + "sha256:616c94f8176808f4018b39f9638080ed86f96b55370b5a9463b2ee5c926f6c5f", + "sha256:63b91e30ef47ef68a30f0c3c278fbfe9822319c15f34b7538a829515b84ca2a0", + "sha256:77b454f03860b844f758c5d5c6e5f18d27de899a3db367f4af06bec2e6013a8e", + "sha256:83fe27ba321e4cfac466178606147d3c0aa18e8087507caec78ed5a966a64905", + "sha256:84742532d39f72df959d237912344d8a1764c2d03fe58beba96a87bfa11a76d8", + "sha256:874ebf3caaf55a020aeb08acead813baf5a305927a71ce88c9377970fe7ad3c2", + "sha256:9f5caf2c7436d44f3cec97c2fa7791f8a675170badbfa86e1992ca1b84c37009", + "sha256:a0c8758d01fcdfe7ae8e4b4017b13552efa7f1197dd7358dc9da0576f9d0328a", + "sha256:a4def978d9d28cda2d960c279318d46b327632686d82b4917516c36d4c274512", + "sha256:ad4f4be843dace866af5fc142509e9b9817ca0c59342fdb176ab6ad552c927f5", + "sha256:ae33dd198f772f714420c5ab698ff05ff900150486c648d29951e9c70694338e", + "sha256:b4a2b782b8a8c5522ad35c93e04d60e2ba7f7dcb9271ec8e8c3e08239be6c7b4", + "sha256:c462eb33f6abca3b34cdedbe84d761f31a60b814e173b98ede3c81bb48967c4f", + "sha256:fd135b8d35dfdcdb984828c84d695937e58cc5f49e1c854eb311c4d6aa03f4f1" + ], + "version": "==1.4.2" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "version": "==7.2.0" + }, + "packaging": { + "hashes": [ + "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", + "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" + ], + "version": "==19.1" + }, + "pluggy": { + "hashes": [ + "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", + "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" + ], + "version": "==0.13.0" + }, + "py": { + "hashes": [ + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + ], + "version": "==1.8.0" + }, + "pylint": { + "hashes": [ + "sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09", + "sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1" + ], + "index": "pypi", + "version": "==2.3.1" + }, + "pyparsing": { + "hashes": [ + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" + ], + "version": "==2.4.2" + }, + "pytest": { + "hashes": [ + "sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210", + "sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865" + ], + "index": "pypi", + "version": "==5.1.2" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", + "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "pytest-mock": { + "hashes": [ + "sha256:43ce4e9dd5074993e7c021bb1c22cbb5363e612a2b5a76bc6d956775b10758b7", + "sha256:5bf5771b1db93beac965a7347dc81c675ec4090cb841e49d9d34637a25c30568" + ], + "index": "pypi", + "version": "==1.10.4" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "requests-mock": { + "hashes": [ + "sha256:510df890afe08d36eca5bb16b4aa6308a6f85e3159ad3013bac8b9de7bd5a010", + "sha256:88d3402dd8b3c69a9e4f9d3a73ad11b15920c6efd36bc27bf1f701cf4a8e4646" + ], + "index": "pypi", + "version": "==1.7.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "typed-ast": { + "hashes": [ + "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", + "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", + "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", + "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", + "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", + "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", + "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", + "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", + "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", + "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", + "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", + "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + ], + "markers": "implementation_name == 'cpython'", + "version": "==1.4.0" + }, + "urllib3": { + "hashes": [ + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + ], + "version": "==1.25.3" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" + }, + "wrapt": { + "hashes": [ + "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" + ], + "version": "==1.11.2" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "version": "==0.6.0" + } + } +} diff --git a/Packs/PenfieldAI/Integrations/Penfield/README.md b/Packs/PenfieldAI/Integrations/Penfield/README.md new file mode 100644 index 000000000000..4607bdb29b83 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/README.md @@ -0,0 +1,51 @@ +The penfield-get-assignee command takes in necessary context data, and returns the analyst that Penfield believes the incident should be assigned to based on Penfield's models of skill and process. The test command verfies that the endpoint is reachable. +This integration was integrated and tested with version 0.1.4 of Penfield + +## Configure Penfield on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for Penfield. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | Your server URL | | True | + | API Key | The API Key to use for connection | True | + | Trust any certificate (not secure) | Trust any certificate \(not secure\). | False | + | Use system proxy settings | Use system proxy settings. | False | + +4. Click **Test** to validate the URLs, token, and connection. +## Commands +You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. +After you successfully execute a command, a DBot message appears in the War Room with the command details. +### penfield-get-assignee +*** +Calls the Penfield API and returns the analyst Penfield recommends assigning the incident to. This information is saved in the output, but the incident will not be automatically assigned. + + +#### Base Command + +`penfield-get-assignee` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| analyst_ids | An array of XSOAR analyst IDs for Penfield to choose from when determining who to assign to. | Required | +| category | The category of the incident to assign. Can be taken from incident Context Data. | Required | +| created | The creation_date of the incident to assign. Can be taken from incident Context Data. | Required | +| id | The id of the incident to assign. Can be taken from incident Context Data. | Required | +| name | The name of the incident to assign. Can be taken from incident Context Data. | Required | +| severity | The severity of the incident to assign. Can be taken from incident Context Data. | Required | + + +#### Context Output + +| **Parameter** | **Description** | +| --- | --- | +| Penfield.Recommended | The analyst Penfield recommends assigning this incident too. | + +#### Command Example +```!penfield-get-assignee analyst_ids=['analystid1', 'analystid2'] category='my cat' created='2021-09-13T01:58:22.621033322Z' id=34 name='big rootkit attack' severity='High'``` + +#### Human Readable Output +peter \ No newline at end of file diff --git a/Packs/PenfieldAI/Integrations/Penfield/command_examples b/Packs/PenfieldAI/Integrations/Penfield/command_examples new file mode 100644 index 000000000000..5955286a55f9 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/command_examples @@ -0,0 +1 @@ +!penfield-api-call analyst_ids='analystid1,analystid2' category='my cat' created='2021-09-13T01:58:22.621033322Z' id=34 name='big rootkit attack' severity='High' diff --git a/Packs/PenfieldAI/Integrations/Penfield/test_data/test_2_users.json b/Packs/PenfieldAI/Integrations/Penfield/test_data/test_2_users.json new file mode 100644 index 000000000000..59bd8ee593a5 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/test_data/test_2_users.json @@ -0,0 +1 @@ +[{"Brand":"Builtin","Category":"Builtin","Contents":[{"accUser":false,"addedSharedDashboards":["health-status-dashboard","my-home-dashboard","sla-dashboard","097e5436-d8f0-49b7-a19d-a05c60ed1039"],"allRoles":["Administrator"],"dashboards":null,"dateFormat":"","defaultAdmin":true,"disableHyperSearch":false,"disabled":false,"editorStyle":"","email":"","helpSnippetDisabled":false,"homepage":"","hours24":"","id":"admin","image":"609623687###user_image_admin.png","investigationPage":"","lastLogin":"2021-09-08T19:18:08.671819762Z","lastLoginMaster":"0001-01-01T00:00:00Z","name":"Admin","notificationsSettings":{"email":{"all":true},"pushNotifications":{"all":true}},"phone":"","playgroundCleared":false,"playgroundId":"e66b1696-cc6d-49e1-8ffa-4e0eff62b514","preferences":{"automationSearchValuePreference":"","automationShowFilterPreference":"All","automationTypeFilterPreference":"F","installedPacksSearchQuery":"ews","installedPacksSimpleSearch":"updates","integrationsCategoryFilter":null,"integrationsDeprecatedFilter":null,"integrationsSearchValue":"","integrationsShowFilter":null,"integrationsTypeFilter":"custom","userPreferencesDashboardsOrder":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"userPreferencesDefaultDashboard":"097e5436-d8f0-49b7-a19d-a05c60ed1039","userPreferencesIncidentTable":[{"isDefault":true,"key":"id","position":0,"width":110},{"isDefault":true,"key":"name","position":2,"width":300},{"isDefault":true,"key":"type","position":3,"width":200},{"isDefault":true,"key":"severity","position":4,"width":80},{"isDefault":true,"key":"status","position":5,"width":80},{"isDefault":true,"key":"owner","position":6,"width":160},{"isDefault":true,"key":"roles","position":7,"width":160},{"isDefault":true,"key":"playbookId","position":8,"width":150},{"isDefault":true,"key":"occurred","position":9,"width":200},{"isDefault":true,"key":"dueDate","position":10,"width":200}],"userPreferencesIncidentTableQueries":{"Open Jobs in the last 7 days":{"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed category:job"},"Open incidents in the last 7 days":{"isDefault":true,"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed -category:job"}},"userPreferencesSawPluginToast":true,"userPreferencesWarRoomFilter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"userPreferencesWarRoomFilterExpanded":false,"userPreferencesWarRoomFilterMap":{"Chats only":{"categories":["chats"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Default Filter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Playbook results":{"categories":["playbookTaskResult","playbookErrors","justFound"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false}},"userPreferencesWarRoomFilterOpen":true},"readOnly":false,"roles":{"demisto":["Administrator"]},"shortcutsDisabled":false,"theme":"","timeZone":"","type":0,"userTimeZone":"","username":"admin","wasAssigned":false},{"accUser":false,"addedSharedDashboards":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"allRoles":["Analyst"],"dashboards":null,"dateFormat":"","defaultAdmin":false,"disableHyperSearch":false,"disabled":false,"editorStyle":"","email":"chandler@penfield.ai","helpSnippetDisabled":false,"homepage":"","hours24":"","id":"chandler","image":"573003552###user_image_chandler.png","investigationPage":"","lastLogin":"2021-09-02T20:12:00.592869086Z","lastLoginMaster":"0001-01-01T00:00:00Z","name":"chandler","notificationsSettings":{"email":{"all":true},"pushNotifications":{"all":true}},"phone":"","playgroundCleared":false,"playgroundId":"299277d0-9ee6-461c-8f0e-b3a340878266","preferences":{"integrationsCategoryFilter":null,"integrationsDeprecatedFilter":null,"integrationsShowFilter":null,"integrationsTypeFilter":null,"userPreferencesDashboardsOrder":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"userPreferencesDefaultDashboard":"097e5436-d8f0-49b7-a19d-a05c60ed1039","userPreferencesIncidentTable":[{"isDefault":true,"key":"id","position":0,"width":110},{"isDefault":true,"key":"name","position":2,"width":300},{"isDefault":true,"key":"type","position":3,"width":200},{"isDefault":true,"key":"severity","position":4,"width":80},{"isDefault":true,"key":"status","position":5,"width":80},{"isDefault":true,"key":"owner","position":6,"width":160},{"isDefault":true,"key":"roles","position":7,"width":160},{"isDefault":true,"key":"playbookId","position":8,"width":150},{"isDefault":true,"key":"occurred","position":9,"width":200},{"isDefault":true,"key":"dueDate","position":10,"width":200}],"userPreferencesIncidentTableQueries":{"Open Jobs in the last 7 days":{"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed category:job"},"Open incidents in the last 7 days":{"isDefault":true,"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed -category:job"}},"userPreferencesWarRoomFilter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"userPreferencesWarRoomFilterExpanded":false,"userPreferencesWarRoomFilterMap":{"Chats only":{"categories":["chats"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Default Filter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Playbook results":{"categories":["playbookTaskResult","playbookErrors","justFound"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false}},"userPreferencesWarRoomFilterOpen":true},"readOnly":false,"roles":{"demisto":["Analyst"]},"shortcutsDisabled":false,"theme":"","timeZone":"","type":0,"userTimeZone":"","username":"chandler","wasAssigned":false}],"ContentsFormat":"json","EntryContext":{"DemistoUsers":[{"email":"","name":"Admin","phone":"","roles":["demisto: [Administrator]"],"username":"admin"},{"email":"chandler@penfield.ai","name":"chandler","phone":"","roles":["demisto: [Analyst]"],"username":"chandler"}]},"Evidence":false,"EvidenceID":"","File":"","FileID":"","FileMetadata":null,"HumanReadable":"## Users\nUsername | Email | Name | Phone | Roles\n-|-|-|-|-\nadmin | | Admin | | demisto: \\[Administrator\\]\nchandler | chandler@penfield.ai | chandler | | demisto: \\[Analyst\\]\n","ID":"","IgnoreAutoExtract":false,"ImportantEntryContext":null,"IndicatorTimeline":null,"Metadata":{"IndicatorTimeline":null,"ShardID":0,"allRead":false,"allReadWrite":false,"brand":"Builtin","category":"","contents":"","contentsSize":0,"created":"2021-09-08T19:31:04.604271005Z","cronView":false,"dbotCreatedBy":"","endingDate":"0001-01-01T00:00:00Z","entryTask":null,"errorSource":"","file":"","fileID":"","fileMetadata":null,"format":"json","hasRole":false,"id":"","incidentCreationTime":"0001-01-01T00:00:00Z","instance":"Builtin","investigationId":"43","isTodo":false,"mirrored":false,"modified":"0001-01-01T00:00:00Z","note":false,"parentContent":"!PenfieldAssign","parentEntryTruncated":false,"parentId":"80@43","pinned":false,"playbookId":"","previousAllRead":false,"previousAllReadWrite":false,"previousRoles":null,"recurrent":false,"reputationSize":0,"reputations":null,"retryTime":"0001-01-01T00:00:00Z","roles":null,"scheduled":false,"sortValues":null,"startDate":"0001-01-01T00:00:00Z","system":"","tags":null,"tagsRaw":null,"taskId":"","times":0,"timezoneOffset":0,"type":1,"user":"","version":0},"ModuleName":"InnerServicesModule","Note":false,"ReadableContentsFormat":"","System":"","Tags":null,"Type":1,"Version":0}] \ No newline at end of file diff --git a/Packs/PenfieldAI/Integrations/Penfield/test_data/test_incident.json b/Packs/PenfieldAI/Integrations/Penfield/test_data/test_incident.json new file mode 100644 index 000000000000..ff037be0adc7 --- /dev/null +++ b/Packs/PenfieldAI/Integrations/Penfield/test_data/test_incident.json @@ -0,0 +1 @@ +[{"CustomFields":{"detectionsla":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":20,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"remediationsla":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":7200,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"timetoassignment":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":0,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"urlsslverification":[]},"ShardID":0,"account":"","activated":"0001-01-01T00:00:00Z","allRead":false,"allReadWrite":false,"attachment":null,"autime":1630634941158046200,"canvases":null,"category":"","closeNotes":"","closeReason":"","closed":"0001-01-01T00:00:00Z","closingUserId":"","created":"2021-09-03T02:09:01.158046135Z","dbotCreatedBy":"admin","dbotCurrentDirtyFields":null,"dbotDirtyFields":null,"dbotMirrorDirection":"","dbotMirrorId":"","dbotMirrorInstance":"","dbotMirrorLastSync":"0001-01-01T00:00:00Z","dbotMirrorTags":null,"details":"","droppedCount":0,"dueDate":"2021-09-13T02:09:01.158046135Z","feedBased":false,"hasRole":false,"id":"43","investigationId":"43","isPlayground":false,"labels":[{"type":"Instance","value":"admin"},{"type":"Brand","value":"Manual"}],"lastJobRunTime":"0001-01-01T00:00:00Z","lastOpen":"0001-01-01T00:00:00Z","linkedCount":0,"linkedIncidents":null,"modified":"2021-09-03T02:09:03.37485388Z","name":"","notifyTime":"2021-09-03T02:09:03.37228697Z","occurred":"2021-09-03T02:09:01.158046018Z","openDuration":0,"owner":"admin","parent":"","phase":"","playbookId":"playbook0","previousAllRead":false,"previousAllReadWrite":false,"previousRoles":null,"rawCategory":"","rawCloseReason":"","rawJSON":"","rawName":"","rawPhase":"","rawType":"Unclassified","reason":"","reminder":"0001-01-01T00:00:00Z","roles":null,"runStatus":"waiting","severity":1,"sla":0,"sortValues":null,"sourceBrand":"Manual","sourceInstance":"admin","status":1,"type":"Unclassified","version":7}] \ No newline at end of file diff --git a/Packs/PenfieldAI/Playbooks/Penfield_Assign.yml b/Packs/PenfieldAI/Playbooks/Penfield_Assign.yml new file mode 100644 index 000000000000..a8c8423ab359 --- /dev/null +++ b/Packs/PenfieldAI/Playbooks/Penfield_Assign.yml @@ -0,0 +1,167 @@ +id: Penfield Assign +version: -1 +name: Penfield Assign +description: This playbook invokes PenfieldAI backend to assign incident to an online analyst. +starttaskid: "0" +tasks: + "0": + id: "0" + taskid: 806edda5-edcf-4bd3-8ce7-1d5ed0a17b29 + type: start + task: + id: 806edda5-edcf-4bd3-8ce7-1d5ed0a17b29 + version: -1 + name: "" + iscommand: false + brand: "" + description: "" + nexttasks: + '#none#': + - "1" + separatecontext: false + view: |- + { + "position": { + "x": 450, + "y": 50 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + "1": + id: "1" + taskid: e699e084-2f28-4d3a-84c6-287b5f66f11d + type: regular + task: + id: e699e084-2f28-4d3a-84c6-287b5f66f11d + version: -1 + name: getUsers + description: Find all users associated with a role. In addition, you can get + all connected users or the user that ran the command. + script: Builtin|||getUsers + type: regular + iscommand: true + brand: Builtin + nexttasks: + '#none#': + - "2" + scriptarguments: + current: {} + incidentId: {} + onCall: {} + online: + simple: "true" + roles: + simple: Analyst + separatecontext: false + view: |- + { + "position": { + "x": 450, + "y": 230 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + "2": + id: "2" + taskid: c3fbd7f8-c9d3-4962-8ab2-708a51c43208 + type: regular + task: + id: c3fbd7f8-c9d3-4962-8ab2-708a51c43208 + version: -1 + name: penfield-get-assignee + description: Calls the Penfield API and returns the analyst Penfield recommends + assigning the incident to. This information is saved in the output, but the + incident will not be automatically assigned. + script: Penfield|||penfield-get-assignee + type: regular + iscommand: true + brand: Penfield_copy + nexttasks: + '#none#': + - "3" + scriptarguments: + analyst_ids: + complex: + root: DemistoUsers + accessor: name + transformers: + - operator: join + args: + separator: + value: + simple: ',' + category: + simple: ${incident.category} + created: + simple: ${incident.created} + id: + simple: ${incident.id} + name: + simple: ${incident.name} + severity: + simple: ${incident.severity} + separatecontext: false + view: |- + { + "position": { + "x": 450, + "y": 410 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + "3": + id: "3" + taskid: b9e84cf7-e6b7-4863-8c60-458070919a85 + type: regular + task: + id: b9e84cf7-e6b7-4863-8c60-458070919a85 + version: -1 + name: setOwner + description: Set an incident owner + script: Builtin|||setOwner + type: regular + iscommand: true + brand: Builtin + scriptarguments: + owner: + simple: ${Penfield.Recommended} + separatecontext: false + view: |- + { + "position": { + "x": 450, + "y": 590 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 +view: |- + { + "linkLabelsPosition": {}, + "paper": { + "dimensions": { + "height": 635, + "width": 380, + "x": 450, + "y": 50 + } + } + } +inputs: [] +outputs: [] +fromversion: 6.0.0 diff --git a/Packs/PenfieldAI/Playbooks/Penfield_Assign_README.md b/Packs/PenfieldAI/Playbooks/Penfield_Assign_README.md new file mode 100644 index 000000000000..5103a43f158a --- /dev/null +++ b/Packs/PenfieldAI/Playbooks/Penfield_Assign_README.md @@ -0,0 +1,29 @@ +Invokes PenfieldAI backend to assign the incident to an online analyst. + +## Dependencies +This playbook uses the following sub-playbooks, integrations, and scripts. + +## Sub-playbooks +This playbook does not use any sub-playbooks. + +## Integrations +* Penfield + +## Scripts +This playbook does not use any scripts. + +## Commands +* getUsers +* setOwner + +## Playbook Inputs +--- +There are no inputs for this playbook. + +## Playbook Outputs +--- +There are no outputs for this playbook. + +## Playbook Image +--- +![Penfield Assign Playbook](https://raw.githubusercontent.com/demisto/content/21bd874b23f776e5e9706a8e2125b9d8b78e3224/docs/images/playbooks/Penfield_Assign.png) diff --git a/Packs/PenfieldAI/README.md b/Packs/PenfieldAI/README.md new file mode 100644 index 000000000000..0a1f3c4f987d --- /dev/null +++ b/Packs/PenfieldAI/README.md @@ -0,0 +1 @@ +Penfield automatically assigns incidents within the SOC to the appropriate Analyst, to improve the overall speed and accuracy of the incident resolution process. In order to interpret the decision making process, Penfield ingests incident data from XSOAR and combines it with Analyst Interaction data, such as; processes and skills, paired with real-time factors such as active memory, experience, and queue. Based on a command and script, XSOAR is then able to provide the name of the Analyst best suited to respond to the incident. \ No newline at end of file diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.py b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.py new file mode 100644 index 000000000000..2e2881628988 --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.py @@ -0,0 +1,68 @@ +import demistomock as demisto +from CommonServerPython import * +# from CommonServerPython import return_results, return_error +from CommonServerUserPython import * +import traceback + +''' COMMAND FUNCTION ''' + + +def penfield_assign(analyst_ids, category, created, id, name, severity): + return demisto.executeCommand("penfield-get-assignee", { + 'analyst_ids': analyst_ids, + 'category': category, + 'created': created, + 'id': id, + 'name': name, + 'severity': severity + }) + + +''' MAIN FUNCTION ''' + + +def main(): + try: + assign = demisto.args()['assign'] + + # get online analyst ids + analysts = demisto.executeCommand('getUsers', {'online': True})[0]['Contents'] + usernames = [a['username'] for a in analysts] + analyst_ids = '' + analyst_ids += ','.join(usernames) + + # get relevant incident information + incident = demisto.incidents()[0] + category = incident['category'] + created = incident['created'] + id = incident['id'] + name = incident['name'] + severity = incident['severity'] + + # get assignee + chosen_one = penfield_assign( + analyst_ids, + category, + created, + id, + name, + severity + )[0]['Contents'] + + # perform action & return response + if assign == "Yes": + demisto.executeCommand("setOwner", {'owner': chosen_one}) + return_results('incident assigned to: ' + chosen_one) + else: + return_results('penfield suggests: ' + chosen_one) + + except Exception as ex: + demisto.error(traceback.format_exc()) # print the traceback + return_error(ex) + + +''' ENTRY POINT ''' + + +if __name__ in ('__main__', '__builtin__', 'builtins'): + main() diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.yml b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.yml new file mode 100644 index 000000000000..eadfddef2196 --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign.yml @@ -0,0 +1,30 @@ +comment: "PenfieldAssign will use the Penfield integration's penfield-get-assignee command to determine who an incident should be assigned to, then print the selected analyst to the War Room and overwrite the owner property." +commonfields: + id: PenfieldAssign + version: -1 +enabled: true +args: +- name: assign + default: true + auto: PREDEFINED + predefined: + - "Yes" + - "No" + description: Whether this script should actually assign the incident by overwriting + owner. Defaults to yes. + defaultValue: "Yes" +name: PenfieldAssign +script: '-' +system: false +tags: +- management +- user +- Utility +timeout: '0' +type: python +subtype: python3 +dockerimage: demisto/python3:3.9.8.24399 +fromversion: 6.0.0 +dependson: + must: + - Penfield|||penfield-get-assignee diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign_test.py b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign_test.py new file mode 100644 index 000000000000..e413b3fc667b --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/PenfieldAssign_test.py @@ -0,0 +1,63 @@ +"""Base Script for Cortex XSOAR - Unit Tests file + +Pytest Unit Tests: all funcion names must start with "test_" + +More details: https://xsoar.pan.dev/docs/integrations/unit-testing + +MAKE SURE YOU REVIEW/REPLACE ALL THE COMMENTS MARKED AS "TODO" + +""" +import demistomock as demisto +import json +import io +from PenfieldAssign import penfield_assign, main +# from pytest import * + + +def util_load_json(path): + with io.open(path, mode='r', encoding='utf-8') as f: + return json.loads(f.read()) + + +# DUMMY DATA +fake_analyst_ids = 'admin,person' +fake_category = 'fake_cat' +fake_created = 'fake_date' +fake_id = 'fake_id' +fake_name = 'fake_name' +fake_severity = 'Low' + + +# TODO: REMOVE the following dummy unit test function + +fake_response = [{ + 'Contents': 'test_user' +}] + + +def test_penfield_assign(mocker): + # this overwrite the command call + mocker.patch.object(demisto, 'executeCommand', return_value=fake_response) + assert penfield_assign( + analyst_ids=fake_analyst_ids, + category=fake_category, + created=fake_created, + id=fake_id, + name=fake_name, + severity=fake_severity + ) == fake_response + + +def test_main(mocker): + mock_users = util_load_json('test_data/test_2_users.json') + mock_incident = util_load_json('test_data/test_incident.json') + # overwrite get users, incidents, and args + mocker.patch.object(demisto, 'executeCommand', return_value=mock_users) + mocker.patch.object(demisto, 'incidents', return_value=mock_incident) + mocker.patch.object(demisto, 'args', return_value={'assign': "No"}) + mocker.patch('PenfieldAssign.penfield_assign', return_value=fake_response) + mocker.patch.object(demisto, 'results') + + main() + + assert demisto.results.call_args.args[0] == 'penfield suggests: test_user' diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/README.md b/Packs/PenfieldAI/Scripts/PenfieldAssign/README.md new file mode 100644 index 000000000000..73acf5fe638f --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/README.md @@ -0,0 +1,35 @@ +PenfieldAssign will use the PenfieldGetAssignee integration to determine who an incident should be assigned to, then print the selected analyst to the War Room and overwrite the owner property. + +## Script Data +--- + +| **Name** | **Description** | +| --- | --- | +| Script Type | python3 | +| Tags | management, user, Utility | +| Cortex XSOAR Version | 5.5.0 | + +## Dependencies +--- +This script uses the following commands and scripts. +* penfield-api-call + +## Inputs +--- + +| **Argument Name** | **Description** | +| --- | --- | +| assign | Whether this script should actually assign the incident by overwriting owner. Defaults to yes. | + +## Outputs +--- +There are no outputs for this script. + +## Examples +--- +!PenfieldAssign +!PenfieldAssign assign='Yes' +!PenfieldAssign assign='No' + +#### Human Readable Output +incident assigned to: charles \ No newline at end of file diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_2_users.json b/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_2_users.json new file mode 100644 index 000000000000..59bd8ee593a5 --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_2_users.json @@ -0,0 +1 @@ +[{"Brand":"Builtin","Category":"Builtin","Contents":[{"accUser":false,"addedSharedDashboards":["health-status-dashboard","my-home-dashboard","sla-dashboard","097e5436-d8f0-49b7-a19d-a05c60ed1039"],"allRoles":["Administrator"],"dashboards":null,"dateFormat":"","defaultAdmin":true,"disableHyperSearch":false,"disabled":false,"editorStyle":"","email":"","helpSnippetDisabled":false,"homepage":"","hours24":"","id":"admin","image":"609623687###user_image_admin.png","investigationPage":"","lastLogin":"2021-09-08T19:18:08.671819762Z","lastLoginMaster":"0001-01-01T00:00:00Z","name":"Admin","notificationsSettings":{"email":{"all":true},"pushNotifications":{"all":true}},"phone":"","playgroundCleared":false,"playgroundId":"e66b1696-cc6d-49e1-8ffa-4e0eff62b514","preferences":{"automationSearchValuePreference":"","automationShowFilterPreference":"All","automationTypeFilterPreference":"F","installedPacksSearchQuery":"ews","installedPacksSimpleSearch":"updates","integrationsCategoryFilter":null,"integrationsDeprecatedFilter":null,"integrationsSearchValue":"","integrationsShowFilter":null,"integrationsTypeFilter":"custom","userPreferencesDashboardsOrder":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"userPreferencesDefaultDashboard":"097e5436-d8f0-49b7-a19d-a05c60ed1039","userPreferencesIncidentTable":[{"isDefault":true,"key":"id","position":0,"width":110},{"isDefault":true,"key":"name","position":2,"width":300},{"isDefault":true,"key":"type","position":3,"width":200},{"isDefault":true,"key":"severity","position":4,"width":80},{"isDefault":true,"key":"status","position":5,"width":80},{"isDefault":true,"key":"owner","position":6,"width":160},{"isDefault":true,"key":"roles","position":7,"width":160},{"isDefault":true,"key":"playbookId","position":8,"width":150},{"isDefault":true,"key":"occurred","position":9,"width":200},{"isDefault":true,"key":"dueDate","position":10,"width":200}],"userPreferencesIncidentTableQueries":{"Open Jobs in the last 7 days":{"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed category:job"},"Open incidents in the last 7 days":{"isDefault":true,"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed -category:job"}},"userPreferencesSawPluginToast":true,"userPreferencesWarRoomFilter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"userPreferencesWarRoomFilterExpanded":false,"userPreferencesWarRoomFilterMap":{"Chats only":{"categories":["chats"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Default Filter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Playbook results":{"categories":["playbookTaskResult","playbookErrors","justFound"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false}},"userPreferencesWarRoomFilterOpen":true},"readOnly":false,"roles":{"demisto":["Administrator"]},"shortcutsDisabled":false,"theme":"","timeZone":"","type":0,"userTimeZone":"","username":"admin","wasAssigned":false},{"accUser":false,"addedSharedDashboards":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"allRoles":["Analyst"],"dashboards":null,"dateFormat":"","defaultAdmin":false,"disableHyperSearch":false,"disabled":false,"editorStyle":"","email":"chandler@penfield.ai","helpSnippetDisabled":false,"homepage":"","hours24":"","id":"chandler","image":"573003552###user_image_chandler.png","investigationPage":"","lastLogin":"2021-09-02T20:12:00.592869086Z","lastLoginMaster":"0001-01-01T00:00:00Z","name":"chandler","notificationsSettings":{"email":{"all":true},"pushNotifications":{"all":true}},"phone":"","playgroundCleared":false,"playgroundId":"299277d0-9ee6-461c-8f0e-b3a340878266","preferences":{"integrationsCategoryFilter":null,"integrationsDeprecatedFilter":null,"integrationsShowFilter":null,"integrationsTypeFilter":null,"userPreferencesDashboardsOrder":["097e5436-d8f0-49b7-a19d-a05c60ed1039","health-status-dashboard","my-home-dashboard","sla-dashboard"],"userPreferencesDefaultDashboard":"097e5436-d8f0-49b7-a19d-a05c60ed1039","userPreferencesIncidentTable":[{"isDefault":true,"key":"id","position":0,"width":110},{"isDefault":true,"key":"name","position":2,"width":300},{"isDefault":true,"key":"type","position":3,"width":200},{"isDefault":true,"key":"severity","position":4,"width":80},{"isDefault":true,"key":"status","position":5,"width":80},{"isDefault":true,"key":"owner","position":6,"width":160},{"isDefault":true,"key":"roles","position":7,"width":160},{"isDefault":true,"key":"playbookId","position":8,"width":150},{"isDefault":true,"key":"occurred","position":9,"width":200},{"isDefault":true,"key":"dueDate","position":10,"width":200}],"userPreferencesIncidentTableQueries":{"Open Jobs in the last 7 days":{"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed category:job"},"Open incidents in the last 7 days":{"isDefault":true,"picker":{"predefinedRange":{"id":"7","name":"Last 7 days"}},"query":"-status:closed -category:job"}},"userPreferencesWarRoomFilter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"userPreferencesWarRoomFilterExpanded":false,"userPreferencesWarRoomFilterMap":{"Chats only":{"categories":["chats"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Default Filter":{"categories":["chats","incidentInfo","commandAndResults","notes"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false},"Playbook results":{"categories":["playbookTaskResult","playbookErrors","justFound"],"fromTime":"0001-01-01T00:00:00Z","pageSize":0,"tagsAndOperator":false,"usersAndOperator":false}},"userPreferencesWarRoomFilterOpen":true},"readOnly":false,"roles":{"demisto":["Analyst"]},"shortcutsDisabled":false,"theme":"","timeZone":"","type":0,"userTimeZone":"","username":"chandler","wasAssigned":false}],"ContentsFormat":"json","EntryContext":{"DemistoUsers":[{"email":"","name":"Admin","phone":"","roles":["demisto: [Administrator]"],"username":"admin"},{"email":"chandler@penfield.ai","name":"chandler","phone":"","roles":["demisto: [Analyst]"],"username":"chandler"}]},"Evidence":false,"EvidenceID":"","File":"","FileID":"","FileMetadata":null,"HumanReadable":"## Users\nUsername | Email | Name | Phone | Roles\n-|-|-|-|-\nadmin | | Admin | | demisto: \\[Administrator\\]\nchandler | chandler@penfield.ai | chandler | | demisto: \\[Analyst\\]\n","ID":"","IgnoreAutoExtract":false,"ImportantEntryContext":null,"IndicatorTimeline":null,"Metadata":{"IndicatorTimeline":null,"ShardID":0,"allRead":false,"allReadWrite":false,"brand":"Builtin","category":"","contents":"","contentsSize":0,"created":"2021-09-08T19:31:04.604271005Z","cronView":false,"dbotCreatedBy":"","endingDate":"0001-01-01T00:00:00Z","entryTask":null,"errorSource":"","file":"","fileID":"","fileMetadata":null,"format":"json","hasRole":false,"id":"","incidentCreationTime":"0001-01-01T00:00:00Z","instance":"Builtin","investigationId":"43","isTodo":false,"mirrored":false,"modified":"0001-01-01T00:00:00Z","note":false,"parentContent":"!PenfieldAssign","parentEntryTruncated":false,"parentId":"80@43","pinned":false,"playbookId":"","previousAllRead":false,"previousAllReadWrite":false,"previousRoles":null,"recurrent":false,"reputationSize":0,"reputations":null,"retryTime":"0001-01-01T00:00:00Z","roles":null,"scheduled":false,"sortValues":null,"startDate":"0001-01-01T00:00:00Z","system":"","tags":null,"tagsRaw":null,"taskId":"","times":0,"timezoneOffset":0,"type":1,"user":"","version":0},"ModuleName":"InnerServicesModule","Note":false,"ReadableContentsFormat":"","System":"","Tags":null,"Type":1,"Version":0}] \ No newline at end of file diff --git a/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_incident.json b/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_incident.json new file mode 100644 index 000000000000..ff037be0adc7 --- /dev/null +++ b/Packs/PenfieldAI/Scripts/PenfieldAssign/test_data/test_incident.json @@ -0,0 +1 @@ +[{"CustomFields":{"detectionsla":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":20,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"remediationsla":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":7200,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"timetoassignment":{"accumulatedPause":0,"breachTriggered":false,"dueDate":"0001-01-01T00:00:00Z","endDate":"0001-01-01T00:00:00Z","lastPauseDate":"0001-01-01T00:00:00Z","runStatus":"idle","sla":0,"slaStatus":-1,"startDate":"0001-01-01T00:00:00Z","totalDuration":0},"urlsslverification":[]},"ShardID":0,"account":"","activated":"0001-01-01T00:00:00Z","allRead":false,"allReadWrite":false,"attachment":null,"autime":1630634941158046200,"canvases":null,"category":"","closeNotes":"","closeReason":"","closed":"0001-01-01T00:00:00Z","closingUserId":"","created":"2021-09-03T02:09:01.158046135Z","dbotCreatedBy":"admin","dbotCurrentDirtyFields":null,"dbotDirtyFields":null,"dbotMirrorDirection":"","dbotMirrorId":"","dbotMirrorInstance":"","dbotMirrorLastSync":"0001-01-01T00:00:00Z","dbotMirrorTags":null,"details":"","droppedCount":0,"dueDate":"2021-09-13T02:09:01.158046135Z","feedBased":false,"hasRole":false,"id":"43","investigationId":"43","isPlayground":false,"labels":[{"type":"Instance","value":"admin"},{"type":"Brand","value":"Manual"}],"lastJobRunTime":"0001-01-01T00:00:00Z","lastOpen":"0001-01-01T00:00:00Z","linkedCount":0,"linkedIncidents":null,"modified":"2021-09-03T02:09:03.37485388Z","name":"","notifyTime":"2021-09-03T02:09:03.37228697Z","occurred":"2021-09-03T02:09:01.158046018Z","openDuration":0,"owner":"admin","parent":"","phase":"","playbookId":"playbook0","previousAllRead":false,"previousAllReadWrite":false,"previousRoles":null,"rawCategory":"","rawCloseReason":"","rawJSON":"","rawName":"","rawPhase":"","rawType":"Unclassified","reason":"","reminder":"0001-01-01T00:00:00Z","roles":null,"runStatus":"waiting","severity":1,"sla":0,"sortValues":null,"sourceBrand":"Manual","sourceInstance":"admin","status":1,"type":"Unclassified","version":7}] \ No newline at end of file diff --git a/Packs/PenfieldAI/pack_metadata.json b/Packs/PenfieldAI/pack_metadata.json new file mode 100644 index 000000000000..1b676bb2c5e3 --- /dev/null +++ b/Packs/PenfieldAI/pack_metadata.json @@ -0,0 +1,19 @@ +{ + "name": "PenfieldAI", + "description": "Penfield is the industry’s first human-machine intelligence platform to model Cybersecurity Analysts actions and processes in real-time.", + "support": "partner", + "currentVersion": "1.0.0", + "author": "Penfield.AI", + "url": "https://penfield.ai/", + "email": "dev@penfield.ai", + "categories": [ + "Case Management" + ], + "tags": [], + "created": "2021-09-28T21:56:05Z", + "useCases": [], + "keywords": ["assign", "ai"], + "devEmail": [ + "dev@penfield.ai" + ] +} diff --git a/docs/images/playbooks/Penfield_Assign.png b/docs/images/playbooks/Penfield_Assign.png new file mode 100644 index 000000000000..259c288a9329 Binary files /dev/null and b/docs/images/playbooks/Penfield_Assign.png differ