secator 0.1.0__tar.gz → 0.2.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.
Potentially problematic release.
This version of secator might be problematic. Click here for more details.
- secator-0.2.0/CHANGELOG.md +14 -0
- {secator-0.1.0 → secator-0.2.0}/PKG-INFO +23 -1
- {secator-0.1.0 → secator-0.2.0}/README.md +20 -0
- {secator-0.1.0 → secator-0.2.0}/pyproject.toml +4 -1
- secator-0.2.0/scripts/install.sh +32 -0
- {secator-0.1.0 → secator-0.2.0}/secator/cli.py +157 -90
- {secator-0.1.0 → secator-0.2.0}/secator/definitions.py +41 -13
- {secator-0.1.0 → secator-0.2.0}/secator/runners/command.py +27 -13
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/ffuf.py +2 -5
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/katana.py +1 -1
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/msfconsole.py +1 -1
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/naabu.py +1 -1
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/wpscan.py +1 -1
- {secator-0.1.0 → secator-0.2.0}/tests/integration/test_scans.py +2 -2
- {secator-0.1.0 → secator-0.2.0}/tests/integration/test_tasks.py +2 -2
- {secator-0.1.0 → secator-0.2.0}/tests/integration/test_workflows.py +2 -2
- secator-0.1.0/scripts/install.sh +0 -21
- {secator-0.1.0 → secator-0.2.0}/.flake8 +0 -0
- {secator-0.1.0 → secator-0.2.0}/.gitignore +0 -0
- {secator-0.1.0 → secator-0.2.0}/CONTRIBUTING.md +0 -0
- {secator-0.1.0 → secator-0.2.0}/Dockerfile +0 -0
- {secator-0.1.0 → secator-0.2.0}/LICENSE +0 -0
- {secator-0.1.0 → secator-0.2.0}/SECURITY.md +0 -0
- {secator-0.1.0 → secator-0.2.0}/cloudbuild.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/aliases.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/aliases.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/demo.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/demo.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/fmt.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/fmt.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/help.png +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/input.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/input.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/pipe.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/pipe.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/short_demo.cast +0 -0
- {secator-0.1.0 → secator-0.2.0}/images/short_demo.gif +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/download_cves.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/install_asciinema.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/install_go.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/install_ruby.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msf/exploit_cve.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msf/ftp_anonymous.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msf/ftp_version.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msf/redis.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/msfinstall.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/STORY.md +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/aliases.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/demo.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/fmt.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/input.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/pipe.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/scripts/stories/short_demo.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/.gitignore +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/celery.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/config.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/profiles/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/profiles/aggressive.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/profiles/default.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/profiles/stealth.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/domain.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/host.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/network.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/subdomain.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/scans/url.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/cidr_recon.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/code_scan.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/host_recon.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/port_scan.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/subdomain_recon.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/url_crawl.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/url_dirsearch.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/url_fuzz.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/url_nuclei.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/url_vuln.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/user_hunt.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/configs/workflows/wordpress.yaml +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/decorators.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/_base.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/csv.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/gdrive.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/json.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/table.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/exporters/txt.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/hooks/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/hooks/mongodb.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/_base.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/exploit.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/ip.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/port.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/progress.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/record.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/subdomain.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/tag.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/target.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/url.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/user_account.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/output_types/vulnerability.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/report.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/rich.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/_base.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/_helpers.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/scan.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/task.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/runners/workflow.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/serializers/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/serializers/dataclass.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/serializers/json.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/serializers/regex.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/_categories.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/cariddi.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/dalfox.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/dirsearch.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/dnsx.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/dnsxbrute.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/feroxbuster.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/fping.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/gau.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/gf.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/gospider.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/grype.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/h8mail.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/httpx.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/maigret.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/mapcidr.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/nmap.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/nuclei.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/searchsploit.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/tasks/subfinder.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/utils.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/secator/utils_test.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/fixtures/h8mail_breach.txt +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/fixtures/msfconsole_input.rc +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/fixtures/nmap_output.xml +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/inputs.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/outputs.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/setup.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/teardown.sh +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/wordlist.txt +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/wordlist_dns.txt +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/integration/wordpress_toolbox/Makefile +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/performance/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/performance/loadtester.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/__init__.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/test_celery.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/test_scans.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/test_serializers.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/test_tasks.py +0 -0
- {secator-0.1.0 → secator-0.2.0}/tests/unit/test_workflows.py +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.0](https://github.com/freelabz/secator/compare/v0.1.1...v0.2.0) (2024-04-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add build & release CLI commands ([#247](https://github.com/freelabz/secator/issues/247)) ([775eba1](https://github.com/freelabz/secator/commit/775eba16d3a6f9d8cbc83f81daed85fb806fe6db))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* docker build & push ([#250](https://github.com/freelabz/secator/issues/250)) ([7cebd9f](https://github.com/freelabz/secator/commit/7cebd9fe61f6dbb76e9f78fcbcd3514d68204c87))
|
|
14
|
+
* install issues & docs ([#243](https://github.com/freelabz/secator/issues/243)) ([0447148](https://github.com/freelabz/secator/commit/0447148c89f13884cbc14579d953e0d3e067cbe2)), closes [#242](https://github.com/freelabz/secator/issues/242) [#241](https://github.com/freelabz/secator/issues/241) [#240](https://github.com/freelabz/secator/issues/240) [#239](https://github.com/freelabz/secator/issues/239)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: secator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: The pentester's swiss knife.
|
|
5
5
|
Project-URL: Homepage, https://github.com/freelabz/secator
|
|
6
6
|
Project-URL: Issues, https://github.com/freelabz/secator/issues
|
|
@@ -34,6 +34,8 @@ Requires-Dist: rich-click<1.7
|
|
|
34
34
|
Requires-Dist: rich<14
|
|
35
35
|
Requires-Dist: validators<1
|
|
36
36
|
Requires-Dist: xmltodict<1
|
|
37
|
+
Provides-Extra: build
|
|
38
|
+
Requires-Dist: hatch<2; extra == 'build'
|
|
37
39
|
Provides-Extra: dev
|
|
38
40
|
Requires-Dist: asciinema-automation<1; extra == 'dev'
|
|
39
41
|
Requires-Dist: coverage<8; extra == 'dev'
|
|
@@ -319,6 +321,26 @@ secator install addons trace
|
|
|
319
321
|
|
|
320
322
|
</details>
|
|
321
323
|
|
|
324
|
+
<details>
|
|
325
|
+
<summary>build</summary>
|
|
326
|
+
|
|
327
|
+
Add `hatch` for building and publishing the PyPI package.
|
|
328
|
+
|
|
329
|
+
```sh
|
|
330
|
+
secator install addons build
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
</details>
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
### Install CVEs
|
|
337
|
+
|
|
338
|
+
`secator` makes remote API calls to https://cve.circl.lu/ to get in-depth information about the CVEs it encounters.
|
|
339
|
+
We provide a subcommand to download all known CVEs locally so that future lookups are made from disk instead:
|
|
340
|
+
```sh
|
|
341
|
+
secator install cves
|
|
342
|
+
```
|
|
343
|
+
|
|
322
344
|
### Checking installation health
|
|
323
345
|
|
|
324
346
|
To figure out which languages or tools are installed on your system (along with their version):
|
|
@@ -262,6 +262,26 @@ secator install addons trace
|
|
|
262
262
|
|
|
263
263
|
</details>
|
|
264
264
|
|
|
265
|
+
<details>
|
|
266
|
+
<summary>build</summary>
|
|
267
|
+
|
|
268
|
+
Add `hatch` for building and publishing the PyPI package.
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
secator install addons build
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
</details>
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
### Install CVEs
|
|
278
|
+
|
|
279
|
+
`secator` makes remote API calls to https://cve.circl.lu/ to get in-depth information about the CVEs it encounters.
|
|
280
|
+
We provide a subcommand to download all known CVEs locally so that future lookups are made from disk instead:
|
|
281
|
+
```sh
|
|
282
|
+
secator install cves
|
|
283
|
+
```
|
|
284
|
+
|
|
265
285
|
### Checking installation health
|
|
266
286
|
|
|
267
287
|
To figure out which languages or tools are installed on your system (along with their version):
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "secator"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
authors = [{ name = "FreeLabz", email = "sales@freelabz.com" }]
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
description = "The pentester's swiss knife."
|
|
@@ -55,6 +55,9 @@ dev = [
|
|
|
55
55
|
'watchdog < 3',
|
|
56
56
|
'asciinema-automation < 1',
|
|
57
57
|
]
|
|
58
|
+
build = [
|
|
59
|
+
'hatch < 2',
|
|
60
|
+
]
|
|
58
61
|
trace = [
|
|
59
62
|
'memray < 2',
|
|
60
63
|
'pyinstrument < 5',
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
YELLOW='\033[0;93m'
|
|
3
|
+
GREEN='\033[0;92m'
|
|
4
|
+
NC='\033[0m' # No Color
|
|
5
|
+
|
|
6
|
+
echo -e "🗄 ${YELLOW}Running apt update ...${NC}"
|
|
7
|
+
sudo apt update
|
|
8
|
+
echo -e "🗄 ${GREEN}Ran apt update successfully !${NC}\n"
|
|
9
|
+
|
|
10
|
+
echo -e "🗄 ${YELLOW}Installing Python and pipx ...${NC}"
|
|
11
|
+
sudo apt install -y python3-pip pipx
|
|
12
|
+
echo -e "🗄 ${GREEN}pipx installed successfully !${NC}\n"
|
|
13
|
+
|
|
14
|
+
echo -e "🗄 ${YELLOW}Setting \$PATH ...${NC}"
|
|
15
|
+
export PATH=$PATH:~/.local/bin:~/go/bin
|
|
16
|
+
echo -e "🗄 ${GREEN}\$PATH modified successfully !${NC}\n"
|
|
17
|
+
|
|
18
|
+
echo -e "🗄 ${YELLOW}Installing secator and dependencies ...${NC}"
|
|
19
|
+
pipx install secator
|
|
20
|
+
secator install langs go
|
|
21
|
+
secator install langs ruby
|
|
22
|
+
secator install tools
|
|
23
|
+
secator install addons redis
|
|
24
|
+
secator install addons worker
|
|
25
|
+
secator install addons google
|
|
26
|
+
secator install addons mongodb
|
|
27
|
+
echo -e "🗄 ${GREEN}secator installed successfully !${NC}\n"
|
|
28
|
+
|
|
29
|
+
echo -e "🗄 ${YELLOW}Adding ~/go/bin and ~/.local/bin to \$PATH in .bashrc ...${NC}"
|
|
30
|
+
echo "export PATH=$PATH:~/go/bin:~/.local/bin" >> ~/.bashrc
|
|
31
|
+
source ~/.bashrc
|
|
32
|
+
echo -e "🗄 ${GREEN}\$PATH modified successfully !${NC}\n"
|
|
@@ -12,10 +12,12 @@ from rich.rule import Rule
|
|
|
12
12
|
|
|
13
13
|
from secator.config import ConfigLoader
|
|
14
14
|
from secator.decorators import OrderedGroup, register_runner
|
|
15
|
-
from secator.definitions import (ASCII, CVES_FOLDER, DATA_FOLDER,
|
|
15
|
+
from secator.definitions import (ASCII, CVES_FOLDER, DATA_FOLDER, # noqa: F401
|
|
16
|
+
BUILD_ADDON_ENABLED, DEV_ADDON_ENABLED, DEV_PACKAGE,
|
|
17
|
+
GOOGLE_ADDON_ENABLED, LIB_FOLDER, MONGODB_ADDON_ENABLED,
|
|
16
18
|
OPT_NOT_SUPPORTED, PAYLOADS_FOLDER,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
REDIS_ADDON_ENABLED, REVSHELLS_FOLDER, ROOT_FOLDER,
|
|
20
|
+
TRACE_ADDON_ENABLED, VERSION, WORKER_ADDON_ENABLED)
|
|
19
21
|
from secator.rich import console
|
|
20
22
|
from secator.runners import Command
|
|
21
23
|
from secator.serializers.dataclass import loads_dataclass
|
|
@@ -28,10 +30,6 @@ ALL_TASKS = discover_tasks()
|
|
|
28
30
|
ALL_CONFIGS = ConfigLoader.load_all()
|
|
29
31
|
ALL_WORKFLOWS = ALL_CONFIGS.workflow
|
|
30
32
|
ALL_SCANS = ALL_CONFIGS.scan
|
|
31
|
-
DEFAULT_CMD_OPTS = {
|
|
32
|
-
'no_capture': True,
|
|
33
|
-
'print_cmd': True,
|
|
34
|
-
}
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
#-----#
|
|
@@ -48,7 +46,11 @@ def cli(ctx, no_banner, version):
|
|
|
48
46
|
print(ASCII, file=sys.stderr)
|
|
49
47
|
if ctx.invoked_subcommand is None:
|
|
50
48
|
if version:
|
|
51
|
-
print(f'Current
|
|
49
|
+
console.print(f'[bold gold3]Current version[/]: v{VERSION}', highlight=False)
|
|
50
|
+
console.print(f'[bold gold3]Python binary[/]: {sys.executable}')
|
|
51
|
+
if DEV_PACKAGE:
|
|
52
|
+
console.print(f'[bold gold3]Root folder[/]: {ROOT_FOLDER}')
|
|
53
|
+
console.print(f'[bold gold3]Lib folder[/]: {LIB_FOLDER}')
|
|
52
54
|
else:
|
|
53
55
|
ctx.get_help()
|
|
54
56
|
|
|
@@ -142,11 +144,7 @@ def worker(hostname, concurrency, reload, queue, pool, check, dev, stop, show):
|
|
|
142
144
|
if reload:
|
|
143
145
|
patterns = "celery.py;tasks/*.py;runners/*.py;serializers/*.py;output_types/*.py;hooks/*.py;exporters/*.py"
|
|
144
146
|
cmd = f'watchmedo auto-restart --directory=./ --patterns="{patterns}" --recursive -- {cmd}'
|
|
145
|
-
Command.
|
|
146
|
-
cmd,
|
|
147
|
-
name='secator worker',
|
|
148
|
-
**DEFAULT_CMD_OPTS
|
|
149
|
-
)
|
|
147
|
+
Command.execute(cmd, name='secator worker')
|
|
150
148
|
|
|
151
149
|
|
|
152
150
|
#--------#
|
|
@@ -211,11 +209,7 @@ def which(command):
|
|
|
211
209
|
Returns:
|
|
212
210
|
secator.Command: Command instance.
|
|
213
211
|
"""
|
|
214
|
-
return Command.
|
|
215
|
-
f'which {command}',
|
|
216
|
-
quiet=True,
|
|
217
|
-
print_errors=False
|
|
218
|
-
)
|
|
212
|
+
return Command.execute(f'which {command}', quiet=True, print_errors=False)
|
|
219
213
|
|
|
220
214
|
|
|
221
215
|
def version(cls):
|
|
@@ -245,11 +239,7 @@ def get_version(version_cmd):
|
|
|
245
239
|
str: Version string.
|
|
246
240
|
"""
|
|
247
241
|
regex = r'[0-9]+\.[0-9]+\.?[0-9]*\.?[a-zA-Z]*'
|
|
248
|
-
ret = Command.
|
|
249
|
-
version_cmd,
|
|
250
|
-
quiet=True,
|
|
251
|
-
print_errors=False
|
|
252
|
-
)
|
|
242
|
+
ret = Command.execute(version_cmd, quiet=True, print_errors=False)
|
|
253
243
|
match = re.findall(regex, ret.output)
|
|
254
244
|
if not match:
|
|
255
245
|
return 'n/a'
|
|
@@ -265,7 +255,7 @@ def health(json, debug):
|
|
|
265
255
|
status = {'tools': {}, 'languages': {}, 'secator': {}}
|
|
266
256
|
|
|
267
257
|
def print_status(cmd, return_code, version=None, bin=None, category=None):
|
|
268
|
-
s = '[bold green]ok
|
|
258
|
+
s = '[bold green]ok [/]' if return_code == 0 else '[bold red]missing [/]'
|
|
269
259
|
s = f'[bold magenta]{cmd:<15}[/] {s} '
|
|
270
260
|
if return_code == 0 and version:
|
|
271
261
|
if version == 'N/A':
|
|
@@ -287,12 +277,12 @@ def health(json, debug):
|
|
|
287
277
|
|
|
288
278
|
# Check languages
|
|
289
279
|
console.print('\n:wrench: [bold gold3]Checking installed languages ...[/]')
|
|
290
|
-
version_cmds = {'go': 'version', 'python3': '--version', 'ruby': '--version'
|
|
280
|
+
version_cmds = {'go': 'version', 'python3': '--version', 'ruby': '--version'}
|
|
291
281
|
for lang, version_flag in version_cmds.items():
|
|
292
282
|
ret = which(lang)
|
|
293
283
|
ret2 = get_version(f'{lang} {version_flag}')
|
|
294
284
|
if not json:
|
|
295
|
-
print_status(lang, ret.return_code, ret2, ret.output, '
|
|
285
|
+
print_status(lang, ret.return_code, ret2, ret.output, 'langs')
|
|
296
286
|
status['languages'][lang] = {'installed': ret.return_code == 0}
|
|
297
287
|
|
|
298
288
|
# Check tools
|
|
@@ -305,6 +295,14 @@ def health(json, debug):
|
|
|
305
295
|
print_status(tool.__name__, ret.return_code, ret2, ret.output, 'tools')
|
|
306
296
|
status['tools'][tool.__name__] = {'installed': ret.return_code == 0}
|
|
307
297
|
|
|
298
|
+
# Check addons
|
|
299
|
+
console.print('\n:wrench: [bold gold3]Checking installed addons ...[/]')
|
|
300
|
+
for addon in ['google', 'mongodb', 'redis', 'dev', 'trace', 'build']:
|
|
301
|
+
addon_var = globals()[f'{addon.upper()}_ADDON_ENABLED']
|
|
302
|
+
ret = 0 if addon_var == 1 else 1
|
|
303
|
+
bin = None if addon_var == 0 else ' '
|
|
304
|
+
print_status(addon, ret, 'N/A', bin, 'addons')
|
|
305
|
+
|
|
308
306
|
# Print JSON health
|
|
309
307
|
if json:
|
|
310
308
|
console.print(status)
|
|
@@ -316,12 +314,7 @@ def health(json, debug):
|
|
|
316
314
|
|
|
317
315
|
def run_install(cmd, title, next_steps=None):
|
|
318
316
|
with console.status(f'[bold yellow] Installing {title}...'):
|
|
319
|
-
ret = Command.
|
|
320
|
-
cmd,
|
|
321
|
-
cls_attributes={'shell': True},
|
|
322
|
-
print_cmd=True,
|
|
323
|
-
print_line=True
|
|
324
|
-
)
|
|
317
|
+
ret = Command.execute(cmd, cls_attributes={'shell': True}, print_cmd=True, print_line=True)
|
|
325
318
|
if ret.return_code != 0:
|
|
326
319
|
console.print(f':exclamation_mark: Failed to install {title}.', style='bold red')
|
|
327
320
|
else:
|
|
@@ -349,7 +342,7 @@ def addons():
|
|
|
349
342
|
def install_worker():
|
|
350
343
|
"Install worker addon."
|
|
351
344
|
run_install(
|
|
352
|
-
cmd=f'{sys.executable} -m pip install
|
|
345
|
+
cmd=f'{sys.executable} -m pip install .[worker]',
|
|
353
346
|
title='worker addon',
|
|
354
347
|
next_steps=[
|
|
355
348
|
'Run "secator worker" to run a Celery worker using the file system as a backend and broker.',
|
|
@@ -363,7 +356,7 @@ def install_worker():
|
|
|
363
356
|
def install_google():
|
|
364
357
|
"Install google addon."
|
|
365
358
|
run_install(
|
|
366
|
-
cmd=f'{sys.executable} -m pip install
|
|
359
|
+
cmd=f'{sys.executable} -m pip install .[google]',
|
|
367
360
|
title='google addon',
|
|
368
361
|
next_steps=[
|
|
369
362
|
'Set the "GOOGLE_CREDENTIALS_PATH" and "GOOGLE_DRIVE_PARENT_FOLDER_ID" environment variables.',
|
|
@@ -376,7 +369,7 @@ def install_google():
|
|
|
376
369
|
def install_mongodb():
|
|
377
370
|
"Install mongodb addon."
|
|
378
371
|
run_install(
|
|
379
|
-
cmd=f'{sys.executable} -m pip install
|
|
372
|
+
cmd=f'{sys.executable} -m pip install .[mongodb]',
|
|
380
373
|
title='mongodb addon',
|
|
381
374
|
next_steps=[
|
|
382
375
|
'[dim]\[optional][/] Run "docker run --name mongo -p 27017:27017 -d mongo:latest" to run a local MongoDB instance.',
|
|
@@ -390,7 +383,7 @@ def install_mongodb():
|
|
|
390
383
|
def install_redis():
|
|
391
384
|
"Install redis addon."
|
|
392
385
|
run_install(
|
|
393
|
-
cmd=f'{sys.executable} -m pip install
|
|
386
|
+
cmd=f'{sys.executable} -m pip install .[redis]',
|
|
394
387
|
title='redis addon',
|
|
395
388
|
next_steps=[
|
|
396
389
|
'[dim]\[optional][/] Run "docker run --name redis -p 6379:6379 -d redis" to run a local Redis instance.',
|
|
@@ -416,6 +409,34 @@ def install_dev():
|
|
|
416
409
|
)
|
|
417
410
|
|
|
418
411
|
|
|
412
|
+
@addons.command('trace')
|
|
413
|
+
def install_trace():
|
|
414
|
+
"Install trace addon."
|
|
415
|
+
run_install(
|
|
416
|
+
cmd=f'{sys.executable} -m pip install secator[trace]',
|
|
417
|
+
title='dev addon',
|
|
418
|
+
next_steps=[
|
|
419
|
+
'Run "secator test lint" to run lint tests.',
|
|
420
|
+
'Run "secator test unit" to run unit tests.',
|
|
421
|
+
'Run "secator test integration" to run integration tests.',
|
|
422
|
+
]
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@addons.command('build')
|
|
427
|
+
def install_build():
|
|
428
|
+
"Install build addon."
|
|
429
|
+
run_install(
|
|
430
|
+
cmd=f'{sys.executable} -m pip install secator[build]',
|
|
431
|
+
title='build addon',
|
|
432
|
+
next_steps=[
|
|
433
|
+
'Run "secator test lint" to run lint tests.',
|
|
434
|
+
'Run "secator test unit" to run unit tests.',
|
|
435
|
+
'Run "secator test integration" to run integration tests.',
|
|
436
|
+
]
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
|
|
419
440
|
@install.group()
|
|
420
441
|
def langs():
|
|
421
442
|
"Install languages."
|
|
@@ -427,7 +448,10 @@ def install_go():
|
|
|
427
448
|
"""Install Go."""
|
|
428
449
|
run_install(
|
|
429
450
|
cmd='wget -O - https://raw.githubusercontent.com/freelabz/secator/main/scripts/install_go.sh | sudo sh',
|
|
430
|
-
title='Go'
|
|
451
|
+
title='Go',
|
|
452
|
+
next_steps=[
|
|
453
|
+
'Add ~/go/bin to your $PATH'
|
|
454
|
+
]
|
|
431
455
|
)
|
|
432
456
|
|
|
433
457
|
|
|
@@ -459,21 +483,13 @@ def install_tools(cmds):
|
|
|
459
483
|
@install.command('cves')
|
|
460
484
|
@click.option('--force', is_flag=True)
|
|
461
485
|
def install_cves(force):
|
|
462
|
-
"""Install CVEs
|
|
486
|
+
"""Install CVEs (enables passive vulnerability search)."""
|
|
463
487
|
cve_json_path = f'{CVES_FOLDER}/circl-cve-search-expanded.json'
|
|
464
488
|
if not os.path.exists(cve_json_path) or force:
|
|
465
489
|
with console.status('[bold yellow]Downloading zipped CVEs from cve.circl.lu ...[/]'):
|
|
466
|
-
Command.
|
|
467
|
-
'wget https://cve.circl.lu/static/circl-cve-search-expanded.json.gz',
|
|
468
|
-
cwd=CVES_FOLDER,
|
|
469
|
-
**DEFAULT_CMD_OPTS
|
|
470
|
-
)
|
|
490
|
+
Command.execute('wget https://cve.circl.lu/static/circl-cve-search-expanded.json.gz', cwd=CVES_FOLDER)
|
|
471
491
|
with console.status('[bold yellow]Unzipping CVEs ...[/]'):
|
|
472
|
-
Command.
|
|
473
|
-
f'gunzip {CVES_FOLDER}/circl-cve-search-expanded.json.gz',
|
|
474
|
-
cwd=CVES_FOLDER,
|
|
475
|
-
**DEFAULT_CMD_OPTS
|
|
476
|
-
)
|
|
492
|
+
Command.execute(f'gunzip {CVES_FOLDER}/circl-cve-search-expanded.json.gz', cwd=CVES_FOLDER)
|
|
477
493
|
with console.status(f'[bold yellow]Installing CVEs to {CVES_FOLDER} ...[/]'):
|
|
478
494
|
with open(cve_json_path, 'r') as f:
|
|
479
495
|
for line in f:
|
|
@@ -591,8 +607,8 @@ def utils():
|
|
|
591
607
|
@utils.command()
|
|
592
608
|
@click.option('--timeout', type=float, default=0.2, help='Proxy timeout (in seconds)')
|
|
593
609
|
@click.option('--number', '-n', type=int, default=1, help='Number of proxies')
|
|
594
|
-
def
|
|
595
|
-
"""Get
|
|
610
|
+
def proxy(timeout, number):
|
|
611
|
+
"""Get random proxies from FreeProxy."""
|
|
596
612
|
proxy = FreeProxy(timeout=timeout, rand=True, anonym=True)
|
|
597
613
|
for _ in range(number):
|
|
598
614
|
url = proxy.get()
|
|
@@ -605,8 +621,9 @@ def get_proxy(timeout, number):
|
|
|
605
621
|
@click.option('--port', '-p', type=int, default=9001, show_default=True, help='Specify PORT for revshell')
|
|
606
622
|
@click.option('--interface', '-i', type=str, help='Interface to use to detect IP')
|
|
607
623
|
@click.option('--listen', '-l', is_flag=True, default=False, help='Spawn netcat listener on specified port')
|
|
608
|
-
|
|
609
|
-
|
|
624
|
+
@click.option('--force', is_flag=True)
|
|
625
|
+
def revshell(name, host, port, interface, listen, force):
|
|
626
|
+
"""Show reverse shell source codes and run netcat listener (-l)."""
|
|
610
627
|
if host is None: # detect host automatically
|
|
611
628
|
host = detect_host(interface)
|
|
612
629
|
if not host:
|
|
@@ -615,7 +632,18 @@ def revshells(name, host, port, interface, listen):
|
|
|
615
632
|
style='bold red')
|
|
616
633
|
return
|
|
617
634
|
|
|
618
|
-
|
|
635
|
+
# Download reverse shells JSON from repo
|
|
636
|
+
revshells_json = f'{REVSHELLS_FOLDER}/revshells.json'
|
|
637
|
+
if not os.path.exists(revshells_json) or force:
|
|
638
|
+
ret = Command.execute(
|
|
639
|
+
f'wget https://raw.githubusercontent.com/freelabz/secator/main/scripts/revshells.json && mv revshells.json {REVSHELLS_FOLDER}', # noqa: E501
|
|
640
|
+
cls_attributes={'shell': True}
|
|
641
|
+
)
|
|
642
|
+
if not ret.return_code == 0:
|
|
643
|
+
sys.exit(1)
|
|
644
|
+
|
|
645
|
+
# Parse JSON into shells
|
|
646
|
+
with open(revshells_json) as f:
|
|
619
647
|
shells = json.loads(f.read())
|
|
620
648
|
for sh in shells:
|
|
621
649
|
sh['alias'] = '_'.join(sh['name'].lower()
|
|
@@ -663,10 +691,7 @@ def revshells(name, host, port, interface, listen):
|
|
|
663
691
|
if listen:
|
|
664
692
|
console.print(f'Starting netcat listener on port {port} ...', style='bold gold3')
|
|
665
693
|
cmd = f'nc -lvnp {port}'
|
|
666
|
-
Command.
|
|
667
|
-
cmd,
|
|
668
|
-
**DEFAULT_CMD_OPTS
|
|
669
|
-
)
|
|
694
|
+
Command.execute(cmd)
|
|
670
695
|
|
|
671
696
|
|
|
672
697
|
@utils.command()
|
|
@@ -675,10 +700,10 @@ def revshells(name, host, port, interface, listen):
|
|
|
675
700
|
@click.option('--port', '-p', type=int, default=9001, help='HTTP server port')
|
|
676
701
|
@click.option('--interface', '-i', type=str, default=None, help='Interface to use to auto-detect host IP')
|
|
677
702
|
def serve(directory, host, port, interface):
|
|
678
|
-
"""
|
|
703
|
+
"""Run HTTP server to serve payloads."""
|
|
679
704
|
LSE_URL = 'https://github.com/diego-treitos/linux-smart-enumeration/releases/latest/download/lse.sh'
|
|
680
705
|
LINPEAS_URL = 'https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh'
|
|
681
|
-
SUDOKILLER_URL = 'https://raw.githubusercontent.com/TH3xACE/SUDO_KILLER/
|
|
706
|
+
SUDOKILLER_URL = 'https://raw.githubusercontent.com/TH3xACE/SUDO_KILLER/V3/SUDO_KILLERv3.sh'
|
|
682
707
|
PAYLOADS = [
|
|
683
708
|
{
|
|
684
709
|
'fname': 'lse.sh',
|
|
@@ -703,20 +728,11 @@ def serve(directory, host, port, interface):
|
|
|
703
728
|
with console.status(f'[bold yellow][{ix}/{len(PAYLOADS)}] Downloading {fname} [dim]({descr})[/] ...[/]'):
|
|
704
729
|
cmd = payload['command']
|
|
705
730
|
console.print(f'[bold magenta]{fname} [dim]({descr})[/] ...[/]', )
|
|
706
|
-
|
|
707
|
-
opts['no_capture'] = False
|
|
708
|
-
Command.run_command(
|
|
709
|
-
cmd,
|
|
710
|
-
cls_attributes={'shell': True},
|
|
711
|
-
cwd=directory,
|
|
712
|
-
**opts
|
|
713
|
-
)
|
|
731
|
+
Command.execute(cmd, cls_attributes={'shell': True}, cwd=directory)
|
|
714
732
|
console.print()
|
|
715
733
|
|
|
716
734
|
console.print(Rule())
|
|
717
735
|
console.print(f'Available payloads in {directory}: ', style='bold yellow')
|
|
718
|
-
opts = DEFAULT_CMD_OPTS.copy()
|
|
719
|
-
opts['print_cmd'] = False
|
|
720
736
|
for fname in os.listdir(directory):
|
|
721
737
|
if not host:
|
|
722
738
|
host = detect_host(interface)
|
|
@@ -731,12 +747,8 @@ def serve(directory, host, port, interface):
|
|
|
731
747
|
console.print(f'wget http://{host}:{port}/{fname}', style='dim italic')
|
|
732
748
|
console.print('')
|
|
733
749
|
console.print(Rule())
|
|
734
|
-
console.print('
|
|
735
|
-
Command.
|
|
736
|
-
f'{sys.executable} -m http.server {port}',
|
|
737
|
-
cwd=directory,
|
|
738
|
-
**DEFAULT_CMD_OPTS
|
|
739
|
-
)
|
|
750
|
+
console.print(f'Started HTTP server on port {port}, waiting for incoming connections ...', style='bold yellow')
|
|
751
|
+
Command.execute(f'{sys.executable} -m http.server {port}', cwd=directory)
|
|
740
752
|
|
|
741
753
|
|
|
742
754
|
@utils.command()
|
|
@@ -772,18 +784,15 @@ def record(record_name, script, interactive, width, height, output_dir):
|
|
|
772
784
|
console.print(f'Removed existing {output_cast_path}', style='bold green')
|
|
773
785
|
|
|
774
786
|
with console.status('[bold gold3]Recording with asciinema ...[/]'):
|
|
775
|
-
Command.
|
|
787
|
+
Command.execute(
|
|
776
788
|
f'asciinema-automation -aa "-c /bin/sh" {script} {output_cast_path} --timeout 200',
|
|
777
789
|
cls_attributes=attrs,
|
|
778
790
|
raw=True,
|
|
779
|
-
**DEFAULT_CMD_OPTS,
|
|
780
791
|
)
|
|
781
792
|
console.print(f'Generated {output_cast_path}', style='bold green')
|
|
782
793
|
elif interactive:
|
|
783
794
|
os.environ.update(attrs['env'])
|
|
784
|
-
Command.
|
|
785
|
-
f'asciinema rec -c /bin/bash --stdin --overwrite {output_cast_path}',
|
|
786
|
-
)
|
|
795
|
+
Command.execute(f'asciinema rec -c /bin/bash --stdin --overwrite {output_cast_path}')
|
|
787
796
|
|
|
788
797
|
# Resize cast file
|
|
789
798
|
if os.path.exists(output_cast_path):
|
|
@@ -810,11 +819,10 @@ def record(record_name, script, interactive, width, height, output_dir):
|
|
|
810
819
|
|
|
811
820
|
# Edit cast file to reduce long timeouts
|
|
812
821
|
with console.status('[bold gold3] Editing cast file to reduce long commands ...'):
|
|
813
|
-
Command.
|
|
822
|
+
Command.execute(
|
|
814
823
|
f'asciinema-edit quantize --range 1 {output_cast_path} --out {output_cast_path}.tmp',
|
|
815
824
|
cls_attributes=attrs,
|
|
816
825
|
raw=True,
|
|
817
|
-
**DEFAULT_CMD_OPTS,
|
|
818
826
|
)
|
|
819
827
|
if os.path.exists(f'{output_cast_path}.tmp'):
|
|
820
828
|
os.replace(f'{output_cast_path}.tmp', output_cast_path)
|
|
@@ -822,14 +830,78 @@ def record(record_name, script, interactive, width, height, output_dir):
|
|
|
822
830
|
|
|
823
831
|
# Convert to GIF
|
|
824
832
|
with console.status(f'[bold gold3]Converting to {output_gif_path} ...[/]'):
|
|
825
|
-
Command.
|
|
833
|
+
Command.execute(
|
|
826
834
|
f'agg {output_cast_path} {output_gif_path}',
|
|
827
835
|
cls_attributes=attrs,
|
|
828
|
-
**DEFAULT_CMD_OPTS,
|
|
829
836
|
)
|
|
830
837
|
console.print(f'Generated {output_gif_path}', style='bold green')
|
|
831
838
|
|
|
832
839
|
|
|
840
|
+
@utils.group('build')
|
|
841
|
+
def build():
|
|
842
|
+
"""Build secator."""
|
|
843
|
+
pass
|
|
844
|
+
|
|
845
|
+
|
|
846
|
+
@build.command('pypi')
|
|
847
|
+
def build_pypi():
|
|
848
|
+
"""Build secator PyPI package."""
|
|
849
|
+
if not DEV_PACKAGE:
|
|
850
|
+
console.print('[bold red]You MUST use a development version of secator to make builds.[/]')
|
|
851
|
+
sys.exit(1)
|
|
852
|
+
if not BUILD_ADDON_ENABLED:
|
|
853
|
+
console.print('[bold red]Missing build addon: please run `secator install addons build`')
|
|
854
|
+
sys.exit(1)
|
|
855
|
+
with console.status('[bold gold3]Building PyPI package...[/]'):
|
|
856
|
+
ret = Command.execute(f'{sys.executable} -m hatch build', name='hatch build', cwd=ROOT_FOLDER)
|
|
857
|
+
sys.exit(ret.return_code)
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
@build.command('docker')
|
|
861
|
+
@click.option('--dev', '-dev', is_flag=True, default=False, help='Build dev version')
|
|
862
|
+
def build_docker(dev):
|
|
863
|
+
"""Build secator Docker image."""
|
|
864
|
+
version = 'dev' if dev else VERSION
|
|
865
|
+
with console.status('[bold gold3]Building Docker image...[/]'):
|
|
866
|
+
ret = Command.execute(f'docker build -t freelabz/secator:{version} .', name='docker build', cwd=ROOT_FOLDER)
|
|
867
|
+
sys.exit(ret.return_code)
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
@utils.group('publish')
|
|
871
|
+
def publish():
|
|
872
|
+
"""Publish secator."""
|
|
873
|
+
pass
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
@publish.command('pypi')
|
|
877
|
+
def publish_pypi():
|
|
878
|
+
"""Publish secator PyPI package."""
|
|
879
|
+
if not DEV_PACKAGE:
|
|
880
|
+
console.print('[bold red]You MUST use a development version of secator to make builds.[/]')
|
|
881
|
+
sys.exit(1)
|
|
882
|
+
if not BUILD_ADDON_ENABLED:
|
|
883
|
+
console.print('[bold red]Missing build addon: please run `secator install addons build`')
|
|
884
|
+
sys.exit(1)
|
|
885
|
+
os.environ['HATCH_INDEX_USER'] = '__token__'
|
|
886
|
+
hatch_token = os.environ.get('HATCH_INDEX_AUTH')
|
|
887
|
+
if not hatch_token:
|
|
888
|
+
console.print('[bold red]Missing PyPI auth token (HATCH_INDEX_AUTH env variable).')
|
|
889
|
+
sys.exit(1)
|
|
890
|
+
with console.status('[bold gold3]Publishing PyPI package...[/]'):
|
|
891
|
+
ret = Command.execute(f'{sys.executable} -m hatch publish', name='hatch publish', cwd=ROOT_FOLDER)
|
|
892
|
+
sys.exit(ret.return_code)
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
@publish.command('docker')
|
|
896
|
+
@click.option('--dev', '-dev', is_flag=True, default=False, help='Build dev version')
|
|
897
|
+
def publish_docker(dev):
|
|
898
|
+
"""Publish secator Docker image."""
|
|
899
|
+
version = 'dev' if dev else VERSION
|
|
900
|
+
with console.status('[bold gold3]Publishing PyPI package...[/]'):
|
|
901
|
+
ret = Command.execute(f'docker push freelabz/secator:{version}', name='docker push', cwd=ROOT_FOLDER)
|
|
902
|
+
sys.exit(ret.return_code)
|
|
903
|
+
|
|
904
|
+
|
|
833
905
|
#------#
|
|
834
906
|
# TEST #
|
|
835
907
|
#------#
|
|
@@ -854,12 +926,7 @@ def run_test(cmd, name):
|
|
|
854
926
|
cmd: Command to run.
|
|
855
927
|
name: Name of the test.
|
|
856
928
|
"""
|
|
857
|
-
result = Command.
|
|
858
|
-
cmd,
|
|
859
|
-
name=name + ' tests',
|
|
860
|
-
cwd=ROOT_FOLDER,
|
|
861
|
-
**DEFAULT_CMD_OPTS
|
|
862
|
-
)
|
|
929
|
+
result = Command.execute(cmd, name=name + ' tests', cwd=ROOT_FOLDER)
|
|
863
930
|
if result.return_code == 0:
|
|
864
931
|
console.print(f':tada: {name.capitalize()} tests passed !', style='bold green')
|
|
865
932
|
sys.exit(result.return_code)
|
|
@@ -10,13 +10,13 @@ load_dotenv(find_dotenv(usecwd=True), override=False)
|
|
|
10
10
|
# Globals
|
|
11
11
|
VERSION = get_distribution('secator').version
|
|
12
12
|
ASCII = f"""
|
|
13
|
-
|
|
13
|
+
__
|
|
14
14
|
________ _________ _/ /_____ _____
|
|
15
15
|
/ ___/ _ \/ ___/ __ `/ __/ __ \/ ___/
|
|
16
16
|
(__ / __/ /__/ /_/ / /_/ /_/ / /
|
|
17
17
|
/____/\___/\___/\__,_/\__/\____/_/ v{VERSION}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
freelabz.com
|
|
20
20
|
""" # noqa: W605,W291
|
|
21
21
|
|
|
22
22
|
# Secator folders
|
|
@@ -157,27 +157,55 @@ WORDS = 'words'
|
|
|
157
157
|
|
|
158
158
|
# Check worker addon
|
|
159
159
|
try:
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
import eventlet # noqa: F401
|
|
161
|
+
WORKER_ADDON_ENABLED = 1
|
|
162
162
|
except ModuleNotFoundError:
|
|
163
|
-
|
|
163
|
+
WORKER_ADDON_ENABLED = 0
|
|
164
|
+
|
|
165
|
+
# Check google addon
|
|
166
|
+
try:
|
|
167
|
+
import gspread # noqa: F401
|
|
168
|
+
GOOGLE_ADDON_ENABLED = 1
|
|
169
|
+
except ModuleNotFoundError:
|
|
170
|
+
GOOGLE_ADDON_ENABLED = 0
|
|
164
171
|
|
|
165
172
|
# Check mongodb addon
|
|
166
173
|
try:
|
|
167
|
-
|
|
168
|
-
|
|
174
|
+
import pymongo # noqa: F401
|
|
175
|
+
MONGODB_ADDON_ENABLED = 1
|
|
176
|
+
except ModuleNotFoundError:
|
|
177
|
+
MONGODB_ADDON_ENABLED = 0
|
|
178
|
+
|
|
179
|
+
# Check redis addon
|
|
180
|
+
try:
|
|
181
|
+
import redis # noqa: F401
|
|
182
|
+
REDIS_ADDON_ENABLED = 1
|
|
169
183
|
except ModuleNotFoundError:
|
|
170
|
-
|
|
184
|
+
REDIS_ADDON_ENABLED = 0
|
|
171
185
|
|
|
172
186
|
# Check dev addon
|
|
173
187
|
try:
|
|
174
|
-
|
|
175
|
-
|
|
188
|
+
import flake8 # noqa: F401
|
|
189
|
+
DEV_ADDON_ENABLED = 1
|
|
190
|
+
except ModuleNotFoundError:
|
|
191
|
+
DEV_ADDON_ENABLED = 0
|
|
192
|
+
|
|
193
|
+
# Check build addon
|
|
194
|
+
try:
|
|
195
|
+
import hatch # noqa: F401
|
|
196
|
+
BUILD_ADDON_ENABLED = 1
|
|
197
|
+
except ModuleNotFoundError:
|
|
198
|
+
BUILD_ADDON_ENABLED = 0
|
|
199
|
+
|
|
200
|
+
# Check trace addon
|
|
201
|
+
try:
|
|
202
|
+
import memray # noqa: F401
|
|
203
|
+
TRACE_ADDON_ENABLED = 1
|
|
176
204
|
except ModuleNotFoundError:
|
|
177
|
-
|
|
205
|
+
TRACE_ADDON_ENABLED = 0
|
|
178
206
|
|
|
179
207
|
# Check dev package
|
|
180
208
|
if not os.path.exists(TESTS_FOLDER):
|
|
181
|
-
|
|
209
|
+
DEV_PACKAGE = 0
|
|
182
210
|
else:
|
|
183
|
-
|
|
211
|
+
DEV_PACKAGE = 1
|