pyattackforge 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ pyattackforge/__init__.py,sha256=ebRH36uyrbMl6C4H9JejeW0cA6S9xTTzScyD69I0Jso,97
2
+ pyattackforge/cache.py,sha256=zTGWzL4F6n4u6opCNCi0CYkkSWPx5ShZMVmDagMpPQ0,933
3
+ pyattackforge/client.py,sha256=C_nCWuQByRr3GwZVIVUjdsrNA5j-Gv0ttkqig1GkwFg,5664
4
+ pyattackforge/config.py,sha256=d71w7hlV34uIWI_YeyrWE77eEpMPBEL3GuA8Jq6gRTo,2240
5
+ pyattackforge/exceptions.py,sha256=YFzV7VQ3UkOGXKpHhXctuM7fZUtR4LgYuPR_po4pksA,592
6
+ pyattackforge/transport.py,sha256=slYM9zqleyWlTiUpZZfF0CVB95I0u8UMkqsK09Qa9W4,6500
7
+ pyattackforge/resources/__init__.py,sha256=Tim25zMXM8FoprSyh_r2PJQjouWUq4FxfqMvNT6RI_g,646
8
+ pyattackforge/resources/assets.py,sha256=cVe4PrLp3Afxv52SBekQZaiDvQpV7zCKN6bLkUHl-uA,1420
9
+ pyattackforge/resources/base.py,sha256=x5C8SG2MfwCtOkcRi8plDTF6TkJqXz-b58KS4qkP0Zw,1286
10
+ pyattackforge/resources/findings.py,sha256=krl-IODoUFQ1pfsx4SkTCuKICdSsp1Zc1MWwrF2iYRM,34147
11
+ pyattackforge/resources/groups.py,sha256=vnQjY_RCsgLuE2igqtDLd9d-hvISiYR7uszcN8QqS6w,618
12
+ pyattackforge/resources/notes.py,sha256=r-TR3QuatrhGzwmoR7AQt7wiHXTrvmMvm7rYtkBCOkQ,5741
13
+ pyattackforge/resources/projects.py,sha256=1QP-rs53LVqSWXpVglsQdk19qWgqcNrdTp7ezpyTRVs,8893
14
+ pyattackforge/resources/reports.py,sha256=43wDK8SB2qqz-tjerjFBOV4G9EcgLk5WL3O8H-On5b0,805
15
+ pyattackforge/resources/users.py,sha256=8SF_3QdNQalsyU-60V_oJtsJbo6nHkI3WPbCBebEkrk,2275
16
+ pyattackforge/resources/writeups.py,sha256=iBShGQFrwYie3Gx8F0ekSOW0rf_ZzziRDsRpdQYUsSg,3001
17
+ pyattackforge-0.2.2.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
18
+ pyattackforge-0.2.2.dist-info/METADATA,sha256=mFEmP0KNy-Au5eZETE1TbvwniRcVPH7J2a-YcF62ZHU,46131
19
+ pyattackforge-0.2.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
+ pyattackforge-0.2.2.dist-info/top_level.txt,sha256=1rDeMkWvFWuX3MS8V65no7KuybYyvtfIgbYSt5m_uPU,14
21
+ pyattackforge-0.2.2.dist-info/RECORD,,
@@ -1,178 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pyattackforge
3
- Version: 0.2.0
4
- Summary: Python SDK for the AttackForge SSAPI
5
- Requires-Python: >=3.10
6
- Description-Content-Type: text/markdown
7
- License-File: LICENSE
8
- Requires-Dist: httpx>=0.27
9
- Requires-Dist: h2>=4.1.0
10
- Provides-Extra: dev
11
- Requires-Dist: pytest>=8.0; extra == "dev"
12
- Requires-Dist: python-dotenv>=1.0; extra == "dev"
13
- Dynamic: license-file
14
-
15
- # PyAttackForge
16
-
17
- Next-generation Python SDK for the AttackForge SSAPI (Python 3.10+).
18
-
19
- ## AI Documentation
20
-
21
- `DOCUMENTATION.md` is written for AI coding assistants (Codex/Claude) to implement or extend the library.
22
-
23
- ## Install (local)
24
-
25
- ```bash
26
- pip install -e .
27
- ```
28
-
29
- ## Install (PyPI)
30
-
31
- ```bash
32
- pip install pyattackforge
33
- ```
34
-
35
- ## Build
36
-
37
- ```bash
38
- python -m build --sdist --wheel
39
- ```
40
-
41
- ## Configuration
42
-
43
- Environment variables:
44
- - `ATTACKFORGE_BASE_URL`
45
- - `ATTACKFORGE_API_KEY`
46
- - `ATTACKFORGE_TEST_PROJECT_ID` (only needed for live integration tests)
47
- - `ATTACKFORGE_FINDINGS_VISIBLE_DEFAULT` (optional, set to `true` to make new findings visible; default is pending/hidden)
48
- - `ATTACKFORGE_FINDINGS_SUBSTATUS_KEY` (optional, default `substatus`)
49
- - `ATTACKFORGE_FINDINGS_SUBSTATUS_VALUE` (optional, default `Observed`)
50
- - `ATTACKFORGE_UI_BASE_URL` (optional, UI base URL for project testcase uploads/verification)
51
- - `ATTACKFORGE_UI_TOKEN` (optional, UI authorization token for project testcase uploads/verification)
52
-
53
- Example `.env`:
54
-
55
- ```env
56
- ATTACKFORGE_BASE_URL=https://demo.attackforge.com
57
- ATTACKFORGE_API_KEY=replace-me
58
- ATTACKFORGE_TEST_PROJECT_ID=replace-me
59
- ATTACKFORGE_FINDINGS_VISIBLE_DEFAULT=false
60
- ATTACKFORGE_FINDINGS_SUBSTATUS_KEY=substatus
61
- ATTACKFORGE_FINDINGS_SUBSTATUS_VALUE=Observed
62
- ATTACKFORGE_UI_BASE_URL=https://demo.attackforge.com
63
- ATTACKFORGE_UI_TOKEN=replace-me
64
- ```
65
-
66
- ## Usage (sync)
67
-
68
- ```python
69
- from pyattackforge import AttackForgeClient
70
-
71
- with AttackForgeClient() as client:
72
- projects = client.projects.get_projects()
73
- print(projects)
74
- ```
75
-
76
- Touch a testcase (updates `last_tested` and `testcase_type` in `project_testcase_custom_fields`):
77
-
78
- ```python
79
- from pyattackforge import AttackForgeClient
80
-
81
- with AttackForgeClient() as client:
82
- client.testcases.touch_testcase("project_id", "testcase_id")
83
- ```
84
-
85
- By default, the SDK merges `last_tested` and `testcase_type` into existing project testcase custom fields. Use `overwrite=True` to replace the list.
86
- Default format for `last_tested` is `YYYY-MM-DD` (date picker friendly). Override by supplying `timestamp=`.
87
- Default `testcase_type` is `Security Test Case`. Override by supplying `testcase_type=`.
88
-
89
- Create a testcase note with optional deduplication (case-insensitive, trimmed):
90
-
91
- ```python
92
- from pyattackforge import AttackForgeClient
93
-
94
- with AttackForgeClient() as client:
95
- payload = {"note": "Observed weak password policy", "note_type": "PLAINTEXT"}
96
- client.testcases.create_testcase_note("project_id", "testcase_id", payload, dedupe=True)
97
- ```
98
-
99
- When `dedupe=True`, the SDK compares against notes returned by the project testcase listing. If notes are not included in that response, the check is best-effort and the note will be created.
100
- If a UI token is configured (`ATTACKFORGE_UI_TOKEN`), the SDK will also check the UI notes endpoint to avoid duplicates.
101
-
102
- Upload vulnerability evidence with FIFO retention and dedupe:
103
-
104
- ```python
105
- from pyattackforge import AttackForgeClient
106
-
107
- with AttackForgeClient() as client:
108
- client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png")
109
- # keep_last defaults to 2 (FIFO, keep most recent). Set keep_last=None to disable.
110
- client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png", dedupe=True)
111
- ```
112
-
113
- For more reliable FIFO/dedupe, pass `project_id` so the SDK can use the project vulnerability listing (which contains evidence metadata):
114
-
115
- ```python
116
- client.findings.upload_vulnerability_evidence("vuln_id", "evidence.png", project_id="project_id")
117
- ```
118
-
119
- Upload project testcase evidence with FIFO retention and dedupe:
120
-
121
- ```python
122
- from pyattackforge import AttackForgeClient
123
-
124
- with AttackForgeClient() as client:
125
- client.testcases.upload_testcase_file("project_id", "testcase_id", "evidence.png")
126
- # keep_last defaults to 2 (FIFO, keep most recent). Set keep_last=None to disable.
127
- client.testcases.upload_testcase_file("project_id", "testcase_id", "evidence.png", dedupe=True)
128
- ```
129
-
130
- When a UI token is configured, FIFO cleanup for testcase evidence uses the UI delete endpoint:
131
- `/api/projects/:projectId/meta/:fileId/delete` (UI expects GET/POST semantics).
132
-
133
- Helper methods (examples):
134
-
135
- ```python
136
- with AttackForgeClient() as client:
137
- project = client.projects.find_project_by_name("Tantalum Labs Fake Pentest")
138
- suite = client.testsuites.find_testsuite_by_name("OWASP Web App Penetration Test")
139
- if suite:
140
- testcases = client.testsuites.get_testsuite_testcases(suite["id"])
141
- client.link_vulnerability_to_testcases("project_id", "vuln_id", ["testcase_id"])
142
- ```
143
-
144
- ## Testing
145
-
146
- Unit tests:
147
-
148
- ```bash
149
- python3 -m pytest
150
- ```
151
-
152
- Integration tests (require env vars):
153
-
154
- ```bash
155
- python3 -m pytest -m integration
156
- ```
157
-
158
- Integration tests create and modify data in the target tenant and will attempt cleanup. They read `ATTACKFORGE_BASE_URL`, `ATTACKFORGE_API_KEY`, and `ATTACKFORGE_TEST_PROJECT_ID`.
159
-
160
- ## Status
161
-
162
- This is a from-scratch rewrite. See `COVERAGE.md` for endpoint coverage and assumptions.
163
-
164
- ## Scripts
165
-
166
- Import writeups from a JSON export:
167
-
168
- ```bash
169
- python3 scripts/import_writeups.py --input writeups.json
170
- ```
171
-
172
- By default the script will ensure custom libraries exist. If the SSAPI returns an error for a custom library key, it will create a small bootstrap writeup in that library. Use `--no-ensure-library` to skip.
173
-
174
- Add missing writeup custom fields (Settings -> Writeups) based on the import file:
175
-
176
- ```bash
177
- python3 scripts/import_writeups.py --input writeups.json --ensure-writeup-fields
178
- ```
@@ -1,20 +0,0 @@
1
- pyattackforge/__init__.py,sha256=ebRH36uyrbMl6C4H9JejeW0cA6S9xTTzScyD69I0Jso,97
2
- pyattackforge/cache.py,sha256=zTGWzL4F6n4u6opCNCi0CYkkSWPx5ShZMVmDagMpPQ0,933
3
- pyattackforge/client.py,sha256=E99KuD71q_geRiwMLdcJMUi_hdRJJUu8lPyC6Q-hVAk,5590
4
- pyattackforge/config.py,sha256=U7kkUIDdC-ES8BC4jI-gM3dOyVNvvtRD644xPQKhOkQ,2240
5
- pyattackforge/exceptions.py,sha256=YFzV7VQ3UkOGXKpHhXctuM7fZUtR4LgYuPR_po4pksA,592
6
- pyattackforge/transport.py,sha256=5vUc4PASo_8PBdXPw54n7eAG0NiFTFDtmI5Zbn4SpmQ,4535
7
- pyattackforge/resources/__init__.py,sha256=n0C-HZDqBHKfxM7utqKXkGtDES3i-7OzEHcRyUstXHY,589
8
- pyattackforge/resources/assets.py,sha256=cVe4PrLp3Afxv52SBekQZaiDvQpV7zCKN6bLkUHl-uA,1420
9
- pyattackforge/resources/base.py,sha256=x5C8SG2MfwCtOkcRi8plDTF6TkJqXz-b58KS4qkP0Zw,1286
10
- pyattackforge/resources/findings.py,sha256=w1S8Ex-rFLcaVa7mE3MkexmgBW3Z09RilM-KFgG6hSI,27945
11
- pyattackforge/resources/notes.py,sha256=r-TR3QuatrhGzwmoR7AQt7wiHXTrvmMvm7rYtkBCOkQ,5741
12
- pyattackforge/resources/projects.py,sha256=6pDvOp7s81KvzNgONo04rqWzVXGggbdPXvOnEnBEz9A,7262
13
- pyattackforge/resources/reports.py,sha256=43wDK8SB2qqz-tjerjFBOV4G9EcgLk5WL3O8H-On5b0,805
14
- pyattackforge/resources/users.py,sha256=8SF_3QdNQalsyU-60V_oJtsJbo6nHkI3WPbCBebEkrk,2275
15
- pyattackforge/resources/writeups.py,sha256=iBShGQFrwYie3Gx8F0ekSOW0rf_ZzziRDsRpdQYUsSg,3001
16
- pyattackforge-0.2.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
17
- pyattackforge-0.2.0.dist-info/METADATA,sha256=-U3I0OQrPuONAZvP1mLbGSWadBGPQ6I0RMvbhGggG0A,5827
18
- pyattackforge-0.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
19
- pyattackforge-0.2.0.dist-info/top_level.txt,sha256=1rDeMkWvFWuX3MS8V65no7KuybYyvtfIgbYSt5m_uPU,14
20
- pyattackforge-0.2.0.dist-info/RECORD,,