ps-banshee 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. ps_banshee-1.1.0/LICENSE +21 -0
  2. ps_banshee-1.1.0/PKG-INFO +146 -0
  3. ps_banshee-1.1.0/README.md +115 -0
  4. ps_banshee-1.1.0/banshee/__init__.py +16 -0
  5. ps_banshee-1.1.0/banshee/_version.py +15 -0
  6. ps_banshee-1.1.0/banshee/app_config.py +40 -0
  7. ps_banshee-1.1.0/banshee/branding.py +36 -0
  8. ps_banshee-1.1.0/banshee/commands/__init__.py +12 -0
  9. ps_banshee-1.1.0/banshee/commands/args.py +44 -0
  10. ps_banshee-1.1.0/banshee/commands/cmd_classic_alerts.py +175 -0
  11. ps_banshee-1.1.0/banshee/commands/cmd_entity.py +54 -0
  12. ps_banshee-1.1.0/banshee/commands/cmd_ioc.py +236 -0
  13. ps_banshee-1.1.0/banshee/commands/cmd_lists.py +293 -0
  14. ps_banshee-1.1.0/banshee/commands/cmd_pcap_enrich.py +74 -0
  15. ps_banshee-1.1.0/banshee/commands/cmd_playbook_alerts.py +297 -0
  16. ps_banshee-1.1.0/banshee/commands/cmd_risklist.py +239 -0
  17. ps_banshee-1.1.0/banshee/commands/cmd_rules.py +185 -0
  18. ps_banshee-1.1.0/banshee/commands/epilogs.py +602 -0
  19. ps_banshee-1.1.0/banshee/commands/errors.py +20 -0
  20. ps_banshee-1.1.0/banshee/detection_rules/__init__.py +14 -0
  21. ps_banshee-1.1.0/banshee/detection_rules/detection_rules_search.py +210 -0
  22. ps_banshee-1.1.0/banshee/entity_match/__init__.py +17 -0
  23. ps_banshee-1.1.0/banshee/entity_match/constants.py +168 -0
  24. ps_banshee-1.1.0/banshee/entity_match/errors.py +20 -0
  25. ps_banshee-1.1.0/banshee/entity_match/lookup.py +42 -0
  26. ps_banshee-1.1.0/banshee/entity_match/search.py +52 -0
  27. ps_banshee-1.1.0/banshee/formatters/__init__.py +12 -0
  28. ps_banshee-1.1.0/banshee/formatters/output_formatters.py +45 -0
  29. ps_banshee-1.1.0/banshee/fusion_files/__init__.py +14 -0
  30. ps_banshee-1.1.0/banshee/fusion_files/feed_stat.py +66 -0
  31. ps_banshee-1.1.0/banshee/indicators/__init__.py +18 -0
  32. ps_banshee-1.1.0/banshee/indicators/constants.py +103 -0
  33. ps_banshee-1.1.0/banshee/indicators/helpers.py +24 -0
  34. ps_banshee-1.1.0/banshee/indicators/lookup.py +92 -0
  35. ps_banshee-1.1.0/banshee/indicators/rules.py +82 -0
  36. ps_banshee-1.1.0/banshee/indicators/search.py +80 -0
  37. ps_banshee-1.1.0/banshee/indicators/soar.py +57 -0
  38. ps_banshee-1.1.0/banshee/legacy_alerts/__init__.py +12 -0
  39. ps_banshee-1.1.0/banshee/legacy_alerts/alert_lookup.py +38 -0
  40. ps_banshee-1.1.0/banshee/legacy_alerts/alert_search.py +82 -0
  41. ps_banshee-1.1.0/banshee/legacy_alerts/alert_update.py +80 -0
  42. ps_banshee-1.1.0/banshee/legacy_alerts/constants.py +35 -0
  43. ps_banshee-1.1.0/banshee/legacy_alerts/rules_search.py +46 -0
  44. ps_banshee-1.1.0/banshee/lists/__init__.py +24 -0
  45. ps_banshee-1.1.0/banshee/lists/fetch_list.py +35 -0
  46. ps_banshee-1.1.0/banshee/lists/list_add.py +53 -0
  47. ps_banshee-1.1.0/banshee/lists/list_bulk_add.py +85 -0
  48. ps_banshee-1.1.0/banshee/lists/list_bulk_remove.py +85 -0
  49. ps_banshee-1.1.0/banshee/lists/list_clear.py +31 -0
  50. ps_banshee-1.1.0/banshee/lists/list_create.py +46 -0
  51. ps_banshee-1.1.0/banshee/lists/list_entities.py +42 -0
  52. ps_banshee-1.1.0/banshee/lists/list_entries.py +37 -0
  53. ps_banshee-1.1.0/banshee/lists/list_helpers.py +100 -0
  54. ps_banshee-1.1.0/banshee/lists/list_info.py +39 -0
  55. ps_banshee-1.1.0/banshee/lists/list_remove.py +46 -0
  56. ps_banshee-1.1.0/banshee/lists/list_search.py +57 -0
  57. ps_banshee-1.1.0/banshee/lists/list_status.py +37 -0
  58. ps_banshee-1.1.0/banshee/main.py +118 -0
  59. ps_banshee-1.1.0/banshee/pcap_enrich/__init__.py +14 -0
  60. ps_banshee-1.1.0/banshee/pcap_enrich/constants.py +18 -0
  61. ps_banshee-1.1.0/banshee/pcap_enrich/helpers.py +64 -0
  62. ps_banshee-1.1.0/banshee/pcap_enrich/pcap_enrich.py +251 -0
  63. ps_banshee-1.1.0/banshee/playbook_alerts/__init__.py +14 -0
  64. ps_banshee-1.1.0/banshee/playbook_alerts/alert_lookup.py +49 -0
  65. ps_banshee-1.1.0/banshee/playbook_alerts/alert_search.py +62 -0
  66. ps_banshee-1.1.0/banshee/playbook_alerts/alert_update.py +107 -0
  67. ps_banshee-1.1.0/banshee/playbook_alerts/constants.py +75 -0
  68. ps_banshee-1.1.0/banshee/risklist/__init__.py +17 -0
  69. ps_banshee-1.1.0/banshee/risklist/risklist_create.py +154 -0
  70. ps_banshee-1.1.0/banshee/risklist/risklist_fetch.py +89 -0
  71. ps_banshee-1.1.0/banshee/risklist/risklist_stat.py +58 -0
  72. ps_banshee-1.1.0/banshee/threat/__init__.py +16 -0
  73. ps_banshee-1.1.0/banshee/threat/constants.py +99 -0
  74. ps_banshee-1.1.0/banshee/threat/endpoints.py +20 -0
  75. ps_banshee-1.1.0/banshee/threat/fetch_threat_map.py +59 -0
  76. ps_banshee-1.1.0/ps_banshee.egg-info/PKG-INFO +146 -0
  77. ps_banshee-1.1.0/ps_banshee.egg-info/SOURCES.txt +110 -0
  78. ps_banshee-1.1.0/ps_banshee.egg-info/dependency_links.txt +1 -0
  79. ps_banshee-1.1.0/ps_banshee.egg-info/entry_points.txt +2 -0
  80. ps_banshee-1.1.0/ps_banshee.egg-info/requires.txt +22 -0
  81. ps_banshee-1.1.0/ps_banshee.egg-info/top_level.txt +1 -0
  82. ps_banshee-1.1.0/pyproject.toml +72 -0
  83. ps_banshee-1.1.0/setup.cfg +4 -0
  84. ps_banshee-1.1.0/tests/test_cmd_ca_lookup.py +60 -0
  85. ps_banshee-1.1.0/tests/test_cmd_ca_rules.py +29 -0
  86. ps_banshee-1.1.0/tests/test_cmd_ca_search.py +104 -0
  87. ps_banshee-1.1.0/tests/test_cmd_ca_update.py +95 -0
  88. ps_banshee-1.1.0/tests/test_cmd_entity_lookup.py +39 -0
  89. ps_banshee-1.1.0/tests/test_cmd_entity_search.py +73 -0
  90. ps_banshee-1.1.0/tests/test_cmd_ioc_bulk_lookup.py +84 -0
  91. ps_banshee-1.1.0/tests/test_cmd_ioc_lookup.py +191 -0
  92. ps_banshee-1.1.0/tests/test_cmd_ioc_rules.py +147 -0
  93. ps_banshee-1.1.0/tests/test_cmd_ioc_search.py +133 -0
  94. ps_banshee-1.1.0/tests/test_cmd_list_add.py +44 -0
  95. ps_banshee-1.1.0/tests/test_cmd_list_bulk_add.py +333 -0
  96. ps_banshee-1.1.0/tests/test_cmd_list_bulk_remove.py +333 -0
  97. ps_banshee-1.1.0/tests/test_cmd_list_clear.py +33 -0
  98. ps_banshee-1.1.0/tests/test_cmd_list_create.py +55 -0
  99. ps_banshee-1.1.0/tests/test_cmd_list_entities.py +49 -0
  100. ps_banshee-1.1.0/tests/test_cmd_list_info.py +45 -0
  101. ps_banshee-1.1.0/tests/test_cmd_list_remove.py +44 -0
  102. ps_banshee-1.1.0/tests/test_cmd_list_search.py +66 -0
  103. ps_banshee-1.1.0/tests/test_cmd_list_status.py +46 -0
  104. ps_banshee-1.1.0/tests/test_cmd_pba_lookup.py +134 -0
  105. ps_banshee-1.1.0/tests/test_cmd_pba_search.py +92 -0
  106. ps_banshee-1.1.0/tests/test_cmd_pba_update.py +124 -0
  107. ps_banshee-1.1.0/tests/test_cmd_pcap.py +216 -0
  108. ps_banshee-1.1.0/tests/test_cmd_risklist_create.py +225 -0
  109. ps_banshee-1.1.0/tests/test_cmd_risklist_fetch.py +163 -0
  110. ps_banshee-1.1.0/tests/test_cmd_risklist_stat.py +105 -0
  111. ps_banshee-1.1.0/tests/test_cmd_rules_search.py +194 -0
  112. ps_banshee-1.1.0/tests/test_main.py +169 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RecordedFuture-ProfessionalServices
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: ps-banshee
3
+ Version: 1.1.0
4
+ Summary: PS Banshee is a command line tool used to access Recorded Future Intelligence. PS Banshee is designed to get you working quickly with Recorded Future.
5
+ Author-email: Moise Medici <moise.medici@recordedfuture.com>, Ernest Bartosevic <ernest.bartosevic@recordedfuture.com>
6
+ Keywords: API,Recorded Future,Cyber Security Engineering,Threat Intelligence,command line tool,CLI,ioc enrichment
7
+ Requires-Python: <3.14,>=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: typer<0.16.0
11
+ Requires-Dist: pyshark==0.6
12
+ Requires-Dist: polars~=1.34.0
13
+ Requires-Dist: psengine~=2.4.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: build==1.0.3; extra == "dev"
16
+ Requires-Dist: ruff~=0.11.0; extra == "dev"
17
+ Requires-Dist: pytest==8.3.4; extra == "dev"
18
+ Requires-Dist: pytest-vcr==1.0.2; extra == "dev"
19
+ Requires-Dist: pytest-cov==6.0.0; extra == "dev"
20
+ Requires-Dist: pytest-mock==3.14.0; extra == "dev"
21
+ Requires-Dist: urllib3<2.3.0; extra == "dev"
22
+ Requires-Dist: mimesis>=12.1.0; extra == "dev"
23
+ Provides-Extra: docs
24
+ Requires-Dist: ruff~=0.11.0; extra == "docs"
25
+ Requires-Dist: mike~=2.1.3; extra == "docs"
26
+ Requires-Dist: mkdocs~=1.6.1; extra == "docs"
27
+ Requires-Dist: mkdocs-material~=9.6.18; extra == "docs"
28
+ Requires-Dist: mkdocstrings[python]>=0.18; extra == "docs"
29
+ Requires-Dist: griffe-typingdoc~=0.2.8; extra == "docs"
30
+ Dynamic: license-file
31
+
32
+ # PS Banshee
33
+
34
+ PS Banshee is a command-line interface (CLI) tool designed to provide quick and efficient access to Recorded Future Intelligence. Built for security professionals, PS Banshee helps streamline investigations and automate common security operations tasks.
35
+
36
+ ![Welcome](docs/img/welcome.gif)
37
+
38
+ ---
39
+
40
+ ## Table of Contents
41
+
42
+ - [Features](#features)
43
+ - [Installation](#installation)
44
+ - [Usage](#usage)
45
+ - [Development Environment Setup](#development-environment-setup)
46
+ - [Documentation](#documentation)
47
+ - [Support](#support)
48
+
49
+ ---
50
+
51
+ ## Key Features
52
+
53
+ - IOC lookup and search
54
+ - Packet capture (pcap) analysis
55
+ - Recorded Future Alert search, lookup, and update
56
+ - Recorded Future Detection Rules (YARA, Snort, Sigma) search and download
57
+ - Recorded Future Entity search and lookup
58
+ - Recorded Future List & Watch List management
59
+ - Recorded Future Playbook Alert search, lookup, and update
60
+ - Recorded Future Risk List download, and creation
61
+
62
+ ## Installation
63
+
64
+ PS Banshee is available on PyPI and can be installed using `pip` or `pipx`.
65
+
66
+ !!! tip "PS Banshee requires Python 3.9 or later (up to 3.13)."
67
+
68
+ ### Recommended: pipx (isolated environment)
69
+ To install globally, run:
70
+
71
+ ```bash
72
+ pipx install ps-banshee
73
+ ```
74
+
75
+
76
+ !!! info "Installing pipx"
77
+ If you don't have pipx installed, see the [installation guide](https://github.com/pypa/pipx?tab=readme-ov-file#install-pipx).
78
+
79
+
80
+ ### Alternative: pip (current environment)
81
+ To install in the current environment, run:
82
+ ```bash
83
+ pip install ps-banshee
84
+ ```
85
+
86
+ ### Dependencies
87
+
88
+ `pipx` will automatically resolve all Python dependencies.
89
+ If you want to use the `pcap` command, you will also need:
90
+
91
+ - tshark 3.0.0 or later
92
+
93
+ ### Command Auto Completion
94
+
95
+ After installing PS Banshee, you can enable command auto completion:
96
+
97
+ ```bash
98
+ banshee --install-completion
99
+ ```
100
+
101
+ Restart your shell to complete the installation. You can now use TAB to auto-complete commands.
102
+
103
+ ## Usage
104
+
105
+ To see the list of available commands, run:
106
+
107
+ ```bash
108
+ banshee -h
109
+ ```
110
+
111
+ ### Authorization
112
+
113
+ PS Banshee requires a Recorded Future API key, which can be provided as the `-k` or `--api-key` argument, or set as the `RF_TOKEN` environment variable.
114
+
115
+ ```bash
116
+ banshee -k <RF_TOKEN> <command> <sub-command> <arguments>
117
+ ```
118
+
119
+ ### Proxies
120
+
121
+ If you are behind a proxy, set the `HTTP_PROXY` and `HTTPS_PROXY` environment variables.
122
+
123
+ To disable SSL verification, use the `-s` flag:
124
+
125
+ ```bash
126
+ banshee -s ca rules
127
+ ```
128
+
129
+ ### Command Help
130
+
131
+ All commands support the `--help` (`-h`) option:
132
+
133
+ ```bash
134
+ banshee -h
135
+ banshee ca --help
136
+ banshee ioc lookup --help
137
+ banshee list bulk-add -h
138
+ ```
139
+
140
+ ## Support
141
+
142
+ Submit a [support request](https://support.recordedfuture.com/hc/en-us/requests/new) for help alternatively reach out to [support@recordedfuture.com](mailto:support@recordedfuture.com).
143
+
144
+ ---
145
+
146
+ **PS Banshee is developed and maintained by the Recorded Future Professional Services Cyber Security Engineers 🚀**
@@ -0,0 +1,115 @@
1
+ # PS Banshee
2
+
3
+ PS Banshee is a command-line interface (CLI) tool designed to provide quick and efficient access to Recorded Future Intelligence. Built for security professionals, PS Banshee helps streamline investigations and automate common security operations tasks.
4
+
5
+ ![Welcome](docs/img/welcome.gif)
6
+
7
+ ---
8
+
9
+ ## Table of Contents
10
+
11
+ - [Features](#features)
12
+ - [Installation](#installation)
13
+ - [Usage](#usage)
14
+ - [Development Environment Setup](#development-environment-setup)
15
+ - [Documentation](#documentation)
16
+ - [Support](#support)
17
+
18
+ ---
19
+
20
+ ## Key Features
21
+
22
+ - IOC lookup and search
23
+ - Packet capture (pcap) analysis
24
+ - Recorded Future Alert search, lookup, and update
25
+ - Recorded Future Detection Rules (YARA, Snort, Sigma) search and download
26
+ - Recorded Future Entity search and lookup
27
+ - Recorded Future List & Watch List management
28
+ - Recorded Future Playbook Alert search, lookup, and update
29
+ - Recorded Future Risk List download, and creation
30
+
31
+ ## Installation
32
+
33
+ PS Banshee is available on PyPI and can be installed using `pip` or `pipx`.
34
+
35
+ !!! tip "PS Banshee requires Python 3.9 or later (up to 3.13)."
36
+
37
+ ### Recommended: pipx (isolated environment)
38
+ To install globally, run:
39
+
40
+ ```bash
41
+ pipx install ps-banshee
42
+ ```
43
+
44
+
45
+ !!! info "Installing pipx"
46
+ If you don't have pipx installed, see the [installation guide](https://github.com/pypa/pipx?tab=readme-ov-file#install-pipx).
47
+
48
+
49
+ ### Alternative: pip (current environment)
50
+ To install in the current environment, run:
51
+ ```bash
52
+ pip install ps-banshee
53
+ ```
54
+
55
+ ### Dependencies
56
+
57
+ `pipx` will automatically resolve all Python dependencies.
58
+ If you want to use the `pcap` command, you will also need:
59
+
60
+ - tshark 3.0.0 or later
61
+
62
+ ### Command Auto Completion
63
+
64
+ After installing PS Banshee, you can enable command auto completion:
65
+
66
+ ```bash
67
+ banshee --install-completion
68
+ ```
69
+
70
+ Restart your shell to complete the installation. You can now use TAB to auto-complete commands.
71
+
72
+ ## Usage
73
+
74
+ To see the list of available commands, run:
75
+
76
+ ```bash
77
+ banshee -h
78
+ ```
79
+
80
+ ### Authorization
81
+
82
+ PS Banshee requires a Recorded Future API key, which can be provided as the `-k` or `--api-key` argument, or set as the `RF_TOKEN` environment variable.
83
+
84
+ ```bash
85
+ banshee -k <RF_TOKEN> <command> <sub-command> <arguments>
86
+ ```
87
+
88
+ ### Proxies
89
+
90
+ If you are behind a proxy, set the `HTTP_PROXY` and `HTTPS_PROXY` environment variables.
91
+
92
+ To disable SSL verification, use the `-s` flag:
93
+
94
+ ```bash
95
+ banshee -s ca rules
96
+ ```
97
+
98
+ ### Command Help
99
+
100
+ All commands support the `--help` (`-h`) option:
101
+
102
+ ```bash
103
+ banshee -h
104
+ banshee ca --help
105
+ banshee ioc lookup --help
106
+ banshee list bulk-add -h
107
+ ```
108
+
109
+ ## Support
110
+
111
+ Submit a [support request](https://support.recordedfuture.com/hc/en-us/requests/new) for help alternatively reach out to [support@recordedfuture.com](mailto:support@recordedfuture.com).
112
+
113
+ ---
114
+
115
+ **PS Banshee is developed and maintained by the Recorded Future Professional Services Cyber Security Engineers 🚀**
@@ -0,0 +1,16 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ """Base package for PS Banshee."""
15
+
16
+ from ._version import __version__ as version
@@ -0,0 +1,15 @@
1
+ #################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+ from importlib.metadata import version
14
+
15
+ __version__ = version('ps-banshee')
@@ -0,0 +1,40 @@
1
+ #################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+
15
+ from psengine.config import Config
16
+ from pydantic import ValidationError
17
+
18
+ from ._version import __version__
19
+ from .commands.errors import InitConfigError
20
+
21
+
22
+ def config_init(cmd: str, rf_token: str = None, no_ssl_verify: bool = False) -> Config:
23
+ """Global configuration for the CLI.
24
+
25
+ Args:
26
+ cmd (str): The command name + sub command, used to generate the app_id,
27
+ typically will be the name one of the banshee commands,
28
+ confor example: 'ca-search', or 'entity-lookup'.
29
+ rf_token (str, optional): The Recorded Future API token.
30
+ no_ssl_verify (bool, optional): Disable SSL verification.
31
+ """
32
+ # invert no_ssl_verify
33
+ ssl_verify = not no_ssl_verify
34
+ app_id = f'banshee_{cmd}/{__version__}'
35
+ try:
36
+ Config.init(rf_token=rf_token, app_id=app_id, client_ssl_verify=ssl_verify)
37
+ except ValidationError as e:
38
+ if 'rf_token' in e.errors()[0]['loc']:
39
+ raise InitConfigError('Invalid Recorded Future API key') # noqa: B904
40
+ raise InitConfigError(e.errors()[0]['msg']) # noqa: B904
@@ -0,0 +1,36 @@
1
+ #################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+
15
+ from typer import Typer
16
+
17
+ BRANDING = ':rocket: \033[93mBrought to you by the Cyber Security Engineers at Recorded Future\033[0m :rocket:' # noqa: E501
18
+
19
+
20
+ def banshee_cmd(app: Typer, help_: str, epilog: str, *args, **kwargs):
21
+ """Main decorator create banshee commands.
22
+ Under the hood, it adds branding to the help text of the command.
23
+
24
+
25
+ Args:
26
+ app (Typer): The Typer app instance
27
+ help_ (str): The help text for the command
28
+ epilog (str): The epilog text for the command
29
+ *args: Additional arguments to pass to the command
30
+ **kwargs: Additional keyword arguments to pass to the command
31
+
32
+ Returns:
33
+ Typer: The updated Typer app instance
34
+ """
35
+ help_ += f'\n\n{BRANDING}'
36
+ return app.command(help=help_, epilog=epilog, *args, **kwargs) # noqa: B026
@@ -0,0 +1,12 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
@@ -0,0 +1,44 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from typing import Annotated, Optional
15
+
16
+ from typer import Option
17
+
18
+ ################################
19
+ # Global options / arguments
20
+ ################################
21
+
22
+ # How to use: api_key: RF_API_KEY = None
23
+ OPT_RF_API_KEY = Annotated[
24
+ Optional[str],
25
+ Option(
26
+ '--api-key', '-k', help='Recorded Future API Key', envvar='RF_TOKEN', show_default=False
27
+ ),
28
+ ]
29
+
30
+ # How to use: pretty: PRETTY_PRINT = False
31
+ OPT_PRETTY_PRINT = Annotated[
32
+ bool, Option('--pretty', '-p', help='Pretty print the results in a human readable format')
33
+ ]
34
+
35
+
36
+ OPT_NO_SSL_VERIFY = Annotated[
37
+ Optional[bool],
38
+ Option(
39
+ '--no-ssl-verify',
40
+ '-s',
41
+ help="""Disable SSL Verification. Useful when using proxies. To
42
+ utilize a proxy set the environment variable HTTP_PROXY or HTTPS_PROXY.""",
43
+ ),
44
+ ]
@@ -0,0 +1,175 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ import re
15
+ import sys
16
+ from typing import Annotated
17
+
18
+ from typer import Argument, BadParameter, Option, Typer
19
+
20
+ from ..branding import banshee_cmd
21
+ from ..legacy_alerts.alert_lookup import lookup_alert
22
+ from ..legacy_alerts.alert_search import search_alerts
23
+ from ..legacy_alerts.alert_update import update_alerts
24
+ from ..legacy_alerts.constants import AlertStatus
25
+ from ..legacy_alerts.rules_search import search_alert_rules
26
+ from .args import OPT_PRETTY_PRINT
27
+ from .epilogs import (
28
+ EPILOG_ALERT_LOOKUP,
29
+ EPILOG_ALERT_RULES_SEARCH,
30
+ EPILOG_ALERT_SEARCH,
31
+ EPILOG_ALERT_UPDATE,
32
+ )
33
+
34
+ CMD_NAME = 'ca'
35
+ CMD_HELP = 'Search and lookup Classic Alerts'
36
+ CMD_RICH_HELP = 'Recorded Future Classic Alerts'
37
+
38
+ app = Typer(no_args_is_help=True)
39
+
40
+ ALERT_ID_INVALID_MSG = "Alert ID '{}' is not valid. Alert ID should be at least 6 characters long." # noqa: E501
41
+
42
+ ###################################
43
+ # Callbacks
44
+ ###################################
45
+
46
+
47
+ def validate_alert_id(alert_id: str):
48
+ # if value is less than 6 char long
49
+ if len(alert_id) < 6:
50
+ raise BadParameter(ALERT_ID_INVALID_MSG.format(alert_id))
51
+
52
+ return alert_id
53
+
54
+
55
+ def parse_alert_ids_input(value: list[str]):
56
+ if not value:
57
+ raise BadParameter('No Alert IDs supplied')
58
+
59
+ alert_ids = value
60
+ if isinstance(value, str):
61
+ alert_ids = [x for x in re.split(r'[\s]+', value) if x]
62
+
63
+ if not len(alert_ids):
64
+ raise BadParameter('No Alert IDs provided')
65
+
66
+ # Now check that each ID is valid
67
+ for alert_id in alert_ids:
68
+ validate_alert_id(alert_id)
69
+
70
+ return alert_ids
71
+
72
+
73
+ def parse_triggered(value: str):
74
+ if not value.startswith('[') and not value.startswith('('):
75
+ value = f'-{value.strip()}'
76
+
77
+ return value
78
+
79
+
80
+ ###################################
81
+ # Commands
82
+ ###################################
83
+
84
+
85
+ @banshee_cmd(app=app, help_='Lookup a single Classic Alert', epilog=EPILOG_ALERT_LOOKUP)
86
+ def lookup(
87
+ alert_id: Annotated[
88
+ str, Argument(help='Alert ID to lookup', callback=validate_alert_id, show_default=False)
89
+ ],
90
+ pretty: OPT_PRETTY_PRINT = False,
91
+ ):
92
+ lookup_alert(id_=alert_id, pretty=pretty)
93
+
94
+
95
+ @banshee_cmd(app=app, help_='Search for Classic Alerts', epilog=EPILOG_ALERT_SEARCH)
96
+ def search(
97
+ triggered: Annotated[
98
+ str,
99
+ Option(
100
+ '--triggered',
101
+ '-t',
102
+ callback=parse_triggered,
103
+ help='Filter on triggered time, e.g. 1d; 12h; [2024-08-01, 2024-08-14]; [2024-09-23 12:03:58.000, 2024-09-23 12:03:58.567)', # noqa: E501
104
+ show_default=True,
105
+ ),
106
+ ] = '1d',
107
+ alert_rules: Annotated[
108
+ list[str],
109
+ Option('--rule', '-r', help='Filter by an alert rule name (freetext)', show_default=False),
110
+ ] = None,
111
+ status: Annotated[
112
+ AlertStatus, Option('-s', '--status', help='Filter by alert status', show_default=False)
113
+ ] = None,
114
+ pretty: OPT_PRETTY_PRINT = False,
115
+ ):
116
+ search_alerts(
117
+ triggered=triggered,
118
+ alert_rules=alert_rules,
119
+ status=status,
120
+ pretty=pretty,
121
+ )
122
+
123
+
124
+ @banshee_cmd(app=app, help_='Search Classic Alert rules', epilog=EPILOG_ALERT_RULES_SEARCH)
125
+ def rules(
126
+ freetext: Annotated[str, Argument(help='Freetext to search in alert rules')] = None,
127
+ pretty: OPT_PRETTY_PRINT = False,
128
+ ):
129
+ search_alert_rules(pretty=pretty, freetext=freetext)
130
+
131
+
132
+ @banshee_cmd(app=app, help_='Update a classic alert', epilog=EPILOG_ALERT_UPDATE)
133
+ def update(
134
+ alert_ids: list[str] = Argument( # noqa: B008
135
+ ... if sys.stdin.isatty() else None, # noqa: B008
136
+ show_default=False,
137
+ help='One or more whitespace separated Alert ID',
138
+ ),
139
+ status: Annotated[
140
+ AlertStatus, Option('-s', '--status', help='New alert status', show_default=False)
141
+ ] = None,
142
+ note: Annotated[str, Option('-n', '--note', help='Add a text note', show_default=False)] = None,
143
+ note_append: Annotated[
144
+ bool,
145
+ Option(
146
+ '-A',
147
+ '--append',
148
+ help='Append to the existing text note, instead of overwriting it.',
149
+ show_default=True,
150
+ ),
151
+ ] = False,
152
+ assignee: Annotated[
153
+ str,
154
+ Option(
155
+ '--assignee',
156
+ '-a',
157
+ help='New user to assign the alert(s) to. Accepts uhash or email address of the user, for example: uhash:3aXZxdkM12; analyst@acme.com', # noqa: E501
158
+ show_default=False,
159
+ ),
160
+ ] = None,
161
+ ):
162
+ if alert_ids is None:
163
+ alert_ids = sys.stdin.read()
164
+
165
+ parsed_ids = parse_alert_ids_input(alert_ids)
166
+
167
+ if status is None and note is None and assignee is None:
168
+ raise BadParameter('At least one of --status, --note or --assignee must be privded.')
169
+
170
+ if note_append and note is None:
171
+ raise BadParameter('note argument must be provided when append option is set')
172
+
173
+ update_alerts(
174
+ alert_ids=parsed_ids, status=status, note=note, note_append=note_append, assignee=assignee
175
+ )
@@ -0,0 +1,54 @@
1
+ ##################################### TERMS OF USE ###########################################
2
+ # The following code is provided for demonstration purpose only, and should not be used #
3
+ # without independent verification. Recorded Future makes no representations or warranties, #
4
+ # express, implied, statutory, or otherwise, regarding any aspect of this code or of the #
5
+ # information it may retrieve, and provides it both strictly “as-is” and without assuming #
6
+ # responsibility for any information it may retrieve. Recorded Future shall not be liable #
7
+ # for, and you assume all risk of using, the foregoing. By using this code, Customer #
8
+ # represents that it is solely responsible for having all necessary licenses, permissions, #
9
+ # rights, and/or consents to connect to third party APIs, and that it is solely responsible #
10
+ # for having all necessary licenses, permissions, rights, and/or consents to any data #
11
+ # accessed from any third party API. #
12
+ ##############################################################################################
13
+
14
+ from typing import Annotated
15
+
16
+ from typer import Argument, Option, Typer
17
+
18
+ from ..branding import banshee_cmd
19
+ from ..entity_match import EntityType, entity_lookup, entity_search
20
+ from .args import OPT_PRETTY_PRINT
21
+ from .epilogs import EPILOG_ENTITY_LOOKUP, EPILOG_ENTITY_SEARCH
22
+
23
+ CMD_NAME = 'entity'
24
+ CMD_HELP = 'Search and lookup entities'
25
+ CMD_RICH_HELP = 'Entity Match'
26
+
27
+ app = Typer(no_args_is_help=True)
28
+
29
+
30
+ @banshee_cmd(app=app, help_='Lookup an entity by its ID', epilog=EPILOG_ENTITY_LOOKUP)
31
+ def lookup(
32
+ entity_id: str = Argument(show_default=False, help='ID of the entity to lookup'),
33
+ pretty: OPT_PRETTY_PRINT = False,
34
+ ):
35
+ entity_lookup(entity_id=entity_id, pretty=pretty)
36
+
37
+
38
+ @banshee_cmd(
39
+ app=app, help_='Search entities by name and optically by type', epilog=EPILOG_ENTITY_SEARCH
40
+ )
41
+ def search(
42
+ name: str = Argument(show_default=False, help='Name of the entity to search for'),
43
+ type_: Annotated[
44
+ list[EntityType],
45
+ Option(
46
+ '-t', '--type', help='One or more type of the entity to search for', show_default=False
47
+ ),
48
+ ] = None,
49
+ limit: Annotated[
50
+ int, Option('-l', '--limit', help='Limit number of results', min=1, max=100)
51
+ ] = 100,
52
+ pretty: OPT_PRETTY_PRINT = False,
53
+ ):
54
+ entity_search(name=name, type_=type_, limit=limit, pretty=pretty)