Skip to content

Commit 1f46b26

Browse files
obarreraOrlando Barrera IIdacoburn
authored
Orgs full scans (#5)
* Added the Purl API endpoint * Updated Readme * Added the Fullscans API functions GET, POST * Updated FullScans class name to Camel Case for linting. Changes the nested if clause to a for loop for easier readability and future proofing new params * Updated the Fullscans def * Updated the Fullscans class * Updated FullScans and Readme --------- Co-authored-by: Orlando Barrera II <[email protected]> Co-authored-by: Douglas Coburn <[email protected]>
1 parent 909e411 commit 1f46b26

File tree

4 files changed

+255
-1
lines changed

4 files changed

+255
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ venv
66
*.zip
77
*.pyc
88
test.py
9+
.venv

README.rst

+115-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Purpose
66
-------
77

88
The Socket.dev Python SDK provides a wrapper around the Socket.dev REST API to simplify making calls to the API from Python.
9+
Socket API v0 - https://docs.socket.dev/reference/introduction-to-socket-api
910

1011
Initializing the module
1112
-----------------------
@@ -256,4 +257,117 @@ Retrieve the package information for a purl post
256257
**PARAMETERS:**
257258

258259
- **license (str)** - The license parameter if enabled will show alerts and license information. If disabled will only show the basic package metadata and scores. Default is true
259-
- **components (array{dict})** - The components list of packages urls
260+
- **components (array{dict})** - The components list of packages urls
261+
262+
fullscans.get(org_slug)
263+
""""""""""""""""""""""
264+
Retrieve the Fullscans information for around Organization
265+
266+
**Usage:**
267+
268+
.. code-block::
269+
270+
from socketdev import SocketDev
271+
socket = SocketDev("REPLACE_ME")
272+
print(socket.fullscans.get("org_slug"))
273+
274+
**PARAMETERS:**
275+
276+
- **org_slug (str)** - The organization name
277+
278+
fullscans.post(files, params)
279+
""""""""""""""""""""""
280+
Create a full scan from a set of package manifest files. Returns a full scan including all SBOM artifacts.
281+
282+
**Usage:**
283+
284+
.. code-block::
285+
286+
from socketdev import SocketDev
287+
socket = SocketDev("REPLACE_ME")
288+
files = [
289+
"/path/to/manifest/package.json"
290+
]
291+
params = {
292+
"org_slug": "org_name",
293+
"repo": "TestRepo",
294+
"branch": "main",
295+
"commit_message": "Test Commit Message",
296+
"commit_hash": "",
297+
"pull_request": "",
298+
"committers": "commiter",
299+
"make_default_branch": False,
300+
"set_as_pending_head": False,
301+
"tmp": ""
302+
}
303+
304+
print(socket.fullscans.post(files, params))
305+
306+
**PARAMETERS:**
307+
308+
- **files (list)** - List of file paths of manifest files
309+
- **params (dict)** - List of parameters to create a fullscan
310+
311+
| Parameter | Required | Description |
312+
|:----------------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------|
313+
| --org_slug | True | The string name in a git approved name for organization. |
314+
| --repo | True | The string name in a git approved name for repositories. |
315+
| --branch | False | The string name in a git approved name for branches. |
316+
| --committers | False | The string name of the person doing the commit or running the CLI. Can be specified multiple times to have more than one committer |
317+
| --pull_request | False | The integer for the PR or MR number |
318+
| --commit_message | False | The string for a commit message if there is one |
319+
| --make_default_branch | False | If the flag is specified this will signal that this is the default branch. |
320+
| --commit_hash | False | Optional git commit hash |
321+
| --set_as_pending_head | False | |
322+
| --tmp | False | |
323+
324+
fullscans.delete(org_slug, full_scan_id)
325+
""""""""""""""""""""""
326+
Delete an existing full scan.
327+
328+
**Usage:**
329+
330+
.. code-block::
331+
332+
from socketdev import SocketDev
333+
socket = SocketDev("REPLACE_ME")
334+
print(socket.fullscans.delete(org_slug, full_scan_id))
335+
336+
**PARAMETERS:**
337+
338+
- **org_slug (str)** - The organization name
339+
- **full_scan_id (str)** - The ID of the full scan
340+
341+
fullscans.stream(org_slug, full_scan_id)
342+
""""""""""""""""""""""
343+
Stream all SBOM artifacts for a full scan.
344+
345+
**Usage:**
346+
347+
.. code-block::
348+
349+
from socketdev import SocketDev
350+
socket = SocketDev("REPLACE_ME")
351+
print(socket.fullscans.stream(org_slug, full_scan_id))
352+
353+
**PARAMETERS:**
354+
355+
- **org_slug (str)** - The organization name
356+
- **full_scan_id (str)** - The ID of the full scan
357+
358+
fullscans.metadata(org_slug, full_scan_id)
359+
""""""""""""""""""""""
360+
Get metadata for a single full scan
361+
362+
**Usage:**
363+
364+
.. code-block::
365+
366+
from socketdev import SocketDev
367+
socket = SocketDev("REPLACE_ME")
368+
print(socket.fullscans.metadata(org_slug, full_scan_id))
369+
370+
**PARAMETERS:**
371+
372+
- **org_slug (str)** - The organization name
373+
- **full_scan_id (str)** - The ID of the full scan

socketdev/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from socketdev.report import Report
1111
from socketdev.sbom import Sbom
1212
from socketdev.purl import Purl
13+
from socketdev.fullscans import FullScans
1314
from socketdev.repositories import Repositories
1415
from socketdev.settings import Settings
1516
from socketdev.socket_classes import Dependency, Org, Response
@@ -91,5 +92,6 @@ def __init__(self, token: str):
9192
self.report = Report()
9293
self.sbom = Sbom()
9394
self.purl = Purl()
95+
self.fullscans = FullScans()
9496
self.repositories = Repositories()
9597
self.settings = Settings()

socketdev/fullscans/__init__.py

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import socketdev
2+
from socketdev.tools import load_files
3+
import json
4+
5+
class FullScans:
6+
7+
@staticmethod
8+
def create_params_string(
9+
params: dict
10+
) -> str:
11+
12+
param_str = ""
13+
14+
for name in params:
15+
value = params[name]
16+
if value:
17+
param_str += f"&{name}={value}"
18+
19+
param_str = "?" + param_str.lstrip("&")
20+
21+
return param_str
22+
23+
@staticmethod
24+
def get(
25+
org_slug: str,
26+
params: dict) -> dict:
27+
28+
params_arg = FullScans.create_params_string(params)
29+
30+
path = "orgs/" + org_slug + "/full-scans" + str(params_arg)
31+
headers = None
32+
payload = None
33+
34+
response = socketdev.do_request(
35+
path=path,
36+
headers=headers,
37+
payload=payload
38+
)
39+
40+
if response.status_code == 200:
41+
result = response.json()
42+
else:
43+
result = {}
44+
45+
return result
46+
47+
@staticmethod
48+
def post(
49+
files: list,
50+
params: dict
51+
) -> dict:
52+
53+
loaded_files = []
54+
loaded_files = load_files(files, loaded_files)
55+
56+
params_arg = FullScans.create_params_string(params)
57+
58+
path = "orgs/" + str(params["org_slug"]) + "/full-scans" + str(params_arg)
59+
60+
response = socketdev.do_request(
61+
path=path,
62+
method="POST",
63+
files=loaded_files
64+
)
65+
66+
if response.status_code == 201:
67+
result = response.json()
68+
else:
69+
print(f"Error posting {files} to the Fullscans API")
70+
print(response.text)
71+
result = response.text
72+
73+
return result
74+
75+
@staticmethod
76+
def delete(org_slug: str,
77+
full_scan_id: str) -> dict:
78+
79+
path = "orgs/" + org_slug + "/full-scans/" + full_scan_id
80+
81+
response = socketdev.do_request(
82+
path=path,
83+
method="DELETE"
84+
)
85+
86+
if response.status_code == 200:
87+
result = response.json()
88+
else:
89+
result = {}
90+
91+
return result
92+
93+
@staticmethod
94+
def stream(org_slug: str,
95+
full_scan_id: str) -> dict:
96+
97+
path = "orgs/" + org_slug + "/full-scans/" + full_scan_id
98+
99+
response = socketdev.do_request(
100+
path=path,
101+
method="GET"
102+
)
103+
104+
if response.status_code == 200:
105+
stream_str = []
106+
stream_dict = {}
107+
result = response.text
108+
result.strip('"')
109+
result.strip()
110+
for line in result.split("\n"):
111+
if line != '"' and line != "" and line is not None:
112+
item = json.loads(line)
113+
stream_str.append(item)
114+
for val in stream_str:
115+
stream_dict[val['id']] = val
116+
else:
117+
stream_dict = {}
118+
119+
return stream_dict
120+
121+
@staticmethod
122+
def metadata(org_slug: str,
123+
full_scan_id: str) -> dict:
124+
125+
path = "orgs/" + org_slug + "/full-scans/" + full_scan_id + "/metadata"
126+
127+
response = socketdev.do_request(
128+
path=path,
129+
method="GET"
130+
)
131+
132+
if response.status_code == 200:
133+
result = response.json()
134+
else:
135+
result = {}
136+
137+
return result

0 commit comments

Comments
 (0)