@jfrog/opencode-jfrog-plugin 0.0.2 → 0.0.4
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.
- package/README.md +105 -51
- package/dist/index.js +30 -238
- package/package.json +6 -6
- package/skills/jfrog/SKILL.md +529 -0
- package/skills/jfrog/assets/.gitkeep +0 -0
- package/skills/jfrog/references/apptrust-entities.md +154 -0
- package/skills/jfrog/references/artifactory-api-gaps.md +206 -0
- package/skills/jfrog/references/artifactory-aql-syntax.md +656 -0
- package/skills/jfrog/references/artifactory-entities.md +236 -0
- package/skills/jfrog/references/artifactory-operations.md +178 -0
- package/skills/jfrog/references/catalog-entities.md +219 -0
- package/skills/jfrog/references/general-bulk-operations-and-agent-patterns.md +93 -0
- package/skills/jfrog/references/general-parallel-execution.md +131 -0
- package/skills/jfrog/references/general-use-case-hints.md +27 -0
- package/skills/jfrog/references/jfrog-brand-html-report.md +98 -0
- package/skills/jfrog/references/jfrog-cli-install-upgrade.md +30 -0
- package/skills/jfrog/references/jfrog-entity-index.md +112 -0
- package/skills/jfrog/references/jfrog-login-flow.md +132 -0
- package/skills/jfrog/references/jfrog-url-references.md +51 -0
- package/skills/jfrog/references/onemodel-common-patterns.md +323 -0
- package/skills/jfrog/references/onemodel-graphql.md +446 -0
- package/skills/jfrog/references/onemodel-query-examples.md +753 -0
- package/skills/jfrog/references/platform-access-entities.md +200 -0
- package/skills/jfrog/references/platform-admin-api-gaps.md +164 -0
- package/skills/jfrog/references/platform-admin-operations.md +58 -0
- package/skills/jfrog/references/projects-api.md +241 -0
- package/skills/jfrog/references/release-lifecycle-entities.md +180 -0
- package/skills/jfrog/references/stored-packages-entities.md +165 -0
- package/skills/jfrog/references/xray-entities.md +740 -0
- package/skills/jfrog/scripts/check-environment.sh +224 -0
- package/skills/jfrog/scripts/jfrog-login-register-session.sh +84 -0
- package/skills/jfrog/scripts/jfrog-login-save-credentials.sh +128 -0
- package/skills/jfrog-package-safety-and-download/SKILL.md +275 -0
- package/sync-skills-vendor.json +5 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jfrog-package-safety-and-download
|
|
3
|
+
description: >-
|
|
4
|
+
Check JFrog Public Catalog and stored packages for a version, interpret
|
|
5
|
+
catalog security signals, and download through Artifactory (JFrog Platform
|
|
6
|
+
locations, remote cache, curation-aware package managers, or repo proxy).
|
|
7
|
+
Use when the user asks whether a package is safe, allowed, curated, or
|
|
8
|
+
wants to download npm, Maven, PyPI, Go, or similar packages via JFrog.
|
|
9
|
+
Do NOT use for pure CVE or vulnerability lookups (e.g. "details on
|
|
10
|
+
CVE-2021-23337") — those are handled by the jfrog skill's Public security
|
|
11
|
+
domain queries without this workflow.
|
|
12
|
+
metadata:
|
|
13
|
+
role: workflow
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# JFrog Package Safety and Download
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- Read `../jfrog/SKILL.md` for JFrog Platform concepts, domain model, CLI setup, and API patterns.
|
|
21
|
+
- **OneModel shapes drift by server version.** Before inventing GraphQL fields or `where` filters, read `../jfrog/references/onemodel-graphql.md` (schema fetch workflow) and `../jfrog/references/onemodel-query-examples.md` (**Public packages**, **Stored packages**). Regenerate or verify queries against `GET "$JFROG_URL/onemodel/api/v1/supergraph/schema"` when examples fail validation.
|
|
22
|
+
|
|
23
|
+
## Workflow overview
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
flowchart TD
|
|
27
|
+
A[User requests package check / download] --> B{Package in Public Catalog?}
|
|
28
|
+
B -->|Yes| C[Get latest version from Catalog]
|
|
29
|
+
B -->|No| D{Package in JFrog Platform Stored Packages?}
|
|
30
|
+
D -->|Yes| E[Get latest version from Stored Packages]
|
|
31
|
+
D -->|No| F[Package not found — stop]
|
|
32
|
+
C --> G{Latest version in JFrog Platform?}
|
|
33
|
+
E --> G
|
|
34
|
+
G -->|Yes| H[Safe — download from JFrog Platform]
|
|
35
|
+
G -->|No| I{Curation entitled?}
|
|
36
|
+
I -->|Yes| J[Check curation policy via API]
|
|
37
|
+
I -->|No| K[Download via remote repo]
|
|
38
|
+
J -->|200 Allowed| K
|
|
39
|
+
J -->|403 Blocked| M[Report curation blocked — stop]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Parallelization opportunities
|
|
43
|
+
|
|
44
|
+
Several steps in this workflow are independent and can run in parallel to
|
|
45
|
+
reduce total latency:
|
|
46
|
+
|
|
47
|
+
- **Step 1 + Step 1 fallback**: When package type is known, query both the
|
|
48
|
+
Public Catalog (`getPackage`) and Stored Packages (`getPackage`) in
|
|
49
|
+
parallel. Use whichever returns data; if the Public Catalog returns a hit,
|
|
50
|
+
prefer its `latestVersion` for Step 2.
|
|
51
|
+
- **Step 3 + Step 5**: After determining the version, query stored package
|
|
52
|
+
versions (JFrog Platform check) and curation entitlement
|
|
53
|
+
(`/api/system/version`) in parallel. Both are independent reads — the
|
|
54
|
+
curation result is needed immediately if the JFrog Platform check returns
|
|
55
|
+
empty.
|
|
56
|
+
|
|
57
|
+
When issuing parallel Shell calls, each `jf api` call authenticates
|
|
58
|
+
independently against the active `jf config` server; no shell state needs
|
|
59
|
+
to be passed between calls.
|
|
60
|
+
|
|
61
|
+
## Step 1: Find the package
|
|
62
|
+
|
|
63
|
+
Search the **Public Catalog** first via OneModel GraphQL, then fall back to
|
|
64
|
+
**Stored Packages** if not found.
|
|
65
|
+
|
|
66
|
+
Execute the query through `jf api` as described in
|
|
67
|
+
`../jfrog/references/onemodel-graphql.md`; refer to
|
|
68
|
+
`../jfrog/references/onemodel-query-examples.md` for concrete query shapes.
|
|
69
|
+
|
|
70
|
+
**When package type is known** (e.g. `npm`, `maven`, `pypi`), use
|
|
71
|
+
`publicPackages.getPackage(type:, name:)` (see *Get a public package*).
|
|
72
|
+
Include the `latestVersion { version }` selection set — `latestVersion` is
|
|
73
|
+
an object, not a scalar.
|
|
74
|
+
|
|
75
|
+
**When type is unknown**, use `publicPackages.searchPackages` with
|
|
76
|
+
`nameContains` (see *Search public packages*). Add `type:` when the user
|
|
77
|
+
narrows the ecosystem.
|
|
78
|
+
|
|
79
|
+
- **Found** → note `type` and `latestVersion.version`. Proceed to Step 2.
|
|
80
|
+
- **Not found** → the package may be 1st/2nd party. Search **Stored Packages**
|
|
81
|
+
using `storedPackages.searchPackages` or `storedPackages.getPackage` (see
|
|
82
|
+
*Stored packages domain* in `onemodel-query-examples.md`). Prefer
|
|
83
|
+
filtering by `type` when known; if not, use `nameContains` alone.
|
|
84
|
+
- **Found** → note `type` and `latestVersionName` (or derive a version from
|
|
85
|
+
`versionsConnection`). Proceed to Step 2.
|
|
86
|
+
- **Not found in either** → report "package not found" and stop.
|
|
87
|
+
|
|
88
|
+
If multiple results with different `type` values, ask the user which package
|
|
89
|
+
type they mean.
|
|
90
|
+
|
|
91
|
+
## Step 2: Determine latest version
|
|
92
|
+
|
|
93
|
+
| Source | Version field |
|
|
94
|
+
|--------|--------------|
|
|
95
|
+
| Public Catalog | `latestVersion.version` (object selection required) |
|
|
96
|
+
| JFrog Platform Stored Packages | `latestVersionName` on `StoredPackage`, or highest entry from `versionsConnection` |
|
|
97
|
+
|
|
98
|
+
## Step 3: Check if package + latest version exists in JFrog Platform
|
|
99
|
+
|
|
100
|
+
Query stored package versions using `storedPackages.searchPackageVersions`
|
|
101
|
+
with a `hasPackageWith` filter (see `../jfrog/references/onemodel-query-examples.md`
|
|
102
|
+
→ *Search stored package versions*). Add a `version` filter for the specific
|
|
103
|
+
version from Step 2, and request `locationsConnection` to get repository
|
|
104
|
+
details (`repositoryKey`, `repositoryType`, `leadArtifactPath`).
|
|
105
|
+
|
|
106
|
+
Execute the query through `jf api` (see
|
|
107
|
+
`../jfrog/references/onemodel-graphql.md` for the invocation pattern).
|
|
108
|
+
|
|
109
|
+
- **Found with locations** → package is in the JFrog Platform. Report as **safe to
|
|
110
|
+
download**. Proceed to Step 4.
|
|
111
|
+
- **Not found** → proceed to Step 5.
|
|
112
|
+
|
|
113
|
+
## Step 4: Download from JFrog Platform
|
|
114
|
+
|
|
115
|
+
Use the location info from Step 3. Binary artifact downloads go through
|
|
116
|
+
`jf rt dl` — **not** `jf api`. `jf api` is the unified entry point for the
|
|
117
|
+
JFrog REST APIs (metadata, admin, curation, etc.) and does not expose the
|
|
118
|
+
`-L` / `-o` flags needed to stream binary content through a redirect chain.
|
|
119
|
+
|
|
120
|
+
**`<target>` must be a full file path** (e.g.
|
|
121
|
+
`./downloads/lodash-4.18.1.tgz`), not a bare directory. `jf rt dl --flat`
|
|
122
|
+
treats the target as a file name; passing a directory causes a misleading
|
|
123
|
+
"open path: is a directory" error.
|
|
124
|
+
|
|
125
|
+
| `repositoryType` | Strategy |
|
|
126
|
+
|-------------------|----------|
|
|
127
|
+
| `local` or `federated` | `jf rt dl "<repositoryKey>/<leadArtifactPath>" <target-file> --flat` |
|
|
128
|
+
| `remote` | `jf rt dl` against the **base** remote repo (strip any trailing `-cache`) — it transparently triggers the remote fetch when the artifact is not yet cached |
|
|
129
|
+
|
|
130
|
+
**local / federated / remote download:**
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
jf rt dl "<baseRepoKey>/<leadArtifactPath>" <target-file> --flat
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Resolving the remote repo key:** The `repositoryKey` returned by OneModel
|
|
137
|
+
for remote locations often already ends in `-cache` (e.g.
|
|
138
|
+
`devNPM-remote-cache`). `jf rt dl` needs the **base remote repo name**
|
|
139
|
+
(without `-cache`). Strip the `-cache` suffix when present (e.g.
|
|
140
|
+
`devNPM-remote-cache` → `devNPM-remote`). If the key does not end in
|
|
141
|
+
`-cache`, use it as-is.
|
|
142
|
+
|
|
143
|
+
See the **Protocol endpoints** table below for the package-type-specific
|
|
144
|
+
path format inside the repo.
|
|
145
|
+
|
|
146
|
+
## Step 5: Check curation entitlement
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
jf api /artifactory/api/system/version \
|
|
150
|
+
| jq '.addons | index("curation") != null'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- `true` → curation is entitled. Proceed to Step 6a.
|
|
154
|
+
- `false` → curation not available. Proceed to Step 6b.
|
|
155
|
+
|
|
156
|
+
## Step 6a: Check curation policy and download
|
|
157
|
+
|
|
158
|
+
When curation is entitled, use the Xray curation API to check whether the
|
|
159
|
+
package version is allowed across all repositories before downloading.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
RESPONSE_FILE="/tmp/curation-status-$$.json"
|
|
163
|
+
PAYLOAD_FILE="/tmp/curation-payload-$$.json"
|
|
164
|
+
STDERR_FILE="/tmp/curation-err-$$.log"
|
|
165
|
+
|
|
166
|
+
jq -n \
|
|
167
|
+
--arg type "<TYPE>" \
|
|
168
|
+
--arg name "<NAME>" \
|
|
169
|
+
--arg version "<VERSION>" \
|
|
170
|
+
'{packageType:$type, packageName:$name, packageVersion:$version}' \
|
|
171
|
+
> "$PAYLOAD_FILE"
|
|
172
|
+
|
|
173
|
+
set +e
|
|
174
|
+
jf api /xray/api/v1/curation/package_status/all_repos \
|
|
175
|
+
-X POST -H "Content-Type: application/json" \
|
|
176
|
+
--input "$PAYLOAD_FILE" \
|
|
177
|
+
> "$RESPONSE_FILE" 2> "$STDERR_FILE"
|
|
178
|
+
RC=$?
|
|
179
|
+
set -e
|
|
180
|
+
echo "RC=$RC"; echo "$RESPONSE_FILE"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Supported `packageType` values: `npm`, `pypi`, `maven`, `go`, `nuget`,
|
|
184
|
+
`docker`, `gradle`.
|
|
185
|
+
|
|
186
|
+
**Interpreting the result with `jf api`**: unlike plain `curl`, `jf api`
|
|
187
|
+
surfaces the HTTP result through its **exit code** and a
|
|
188
|
+
`"<hh:mm:ss> [Warn] ... returned 4xx/5xx"` line on **stderr** (not a
|
|
189
|
+
`%{http_code}` suffix in stdout). The response body is always written to
|
|
190
|
+
stdout. Parse both:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
if [ "$RC" -eq 0 ]; then
|
|
194
|
+
echo "Package is allowed by curation."
|
|
195
|
+
elif grep -q 'returned 403' "$STDERR_FILE"; then
|
|
196
|
+
echo "Blocked by curation policy:"
|
|
197
|
+
cat "$RESPONSE_FILE"
|
|
198
|
+
else
|
|
199
|
+
echo "Curation check failed (rc=$RC):"
|
|
200
|
+
cat "$STDERR_FILE"
|
|
201
|
+
fi
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Evaluate the outcome:**
|
|
205
|
+
|
|
206
|
+
- **exit 0** → package is **allowed** by curation policy. Proceed to
|
|
207
|
+
download via a remote repo (same as Step 6b).
|
|
208
|
+
- **`returned 403` on stderr** → package is **blocked** by a curation
|
|
209
|
+
policy. The response body explains which policy rule blocked it. Report
|
|
210
|
+
the block reason to the user and stop — do not attempt to download.
|
|
211
|
+
- **Any other non-zero exit** → treat as an operational failure (auth, DNS,
|
|
212
|
+
endpoint disabled) and report.
|
|
213
|
+
|
|
214
|
+
## Step 6b: Download without curation
|
|
215
|
+
|
|
216
|
+
When curation is not entitled and the package is not in the JFrog Platform,
|
|
217
|
+
download directly through a remote repo.
|
|
218
|
+
|
|
219
|
+
1. **Find a remote repo** of the right package type:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
jf api \
|
|
223
|
+
"/artifactory/api/repositories?type=remote&packageType=<TYPE>" \
|
|
224
|
+
| jq '.[].key'
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
2. **Download** — use `jf rt dl` against the base remote repo (without
|
|
228
|
+
`-cache`); it handles both cached and uncached artifacts:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
jf rt dl "<repo>/<artifact-path>" <target-file> --flat
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Artifact paths by package type
|
|
235
|
+
|
|
236
|
+
Use these path patterns when `leadArtifactPath` is not available from
|
|
237
|
+
OneModel. The leading `<repo>/` is the base repo key you pass to `jf rt dl`.
|
|
238
|
+
|
|
239
|
+
| Type | `jf rt dl` target pattern |
|
|
240
|
+
|--------|-------------------------------------------------------------------------|
|
|
241
|
+
| `npm` | `<repo>/<pkg>/-/<pkg>-<version>.tgz` |
|
|
242
|
+
| `pypi` | `<repo>/<pkg>/<version>/<pkg>-<version>.tar.gz` |
|
|
243
|
+
| `maven`| `<repo>/<group-path>/<artifact>/<version>/<artifact>-<version>.jar` |
|
|
244
|
+
| `go` | `<repo>/<module>/@v/<version>.zip` |
|
|
245
|
+
|
|
246
|
+
## Gotchas
|
|
247
|
+
|
|
248
|
+
- **Binary downloads vs. `jf api`**: `jf api` is for REST APIs, not binary
|
|
249
|
+
content. It does not follow redirects transparently into a binary payload
|
|
250
|
+
and does not expose `-L` / `-o`. Always use `jf rt dl` (against the base
|
|
251
|
+
remote repo, not the `-cache` one) for the actual artifact download.
|
|
252
|
+
- **`jf rt dl` and uncached remotes**: `jf rt dl "<remote>/<path>"` —
|
|
253
|
+
targeting the **base** remote repo rather than `<remote>-cache/<path>` —
|
|
254
|
+
transparently triggers the remote fetch and caches the artifact. Do not
|
|
255
|
+
try to pre-query the proxy via `jf api`.
|
|
256
|
+
- **`jf rt dl --flat` target must be a file path**: When downloading a
|
|
257
|
+
single artifact, pass a full output **file** path (e.g.
|
|
258
|
+
`./downloads/lodash-4.18.1.tgz`), not a directory. The CLI opens the target
|
|
259
|
+
path as a file; a directory causes a cryptic "open path: is a directory"
|
|
260
|
+
error that retries four times before failing. Derive the filename from
|
|
261
|
+
`leadArtifactPath` (take the segment after the last `/`).
|
|
262
|
+
- **Package type detection**: If the user doesn't specify the package type,
|
|
263
|
+
the Public Catalog search by name alone may return multiple types. Ask the
|
|
264
|
+
user to disambiguate before proceeding.
|
|
265
|
+
- **Curation endpoint lives under Xray**: use
|
|
266
|
+
`/xray/api/v1/curation/package_status/all_repos` (via `jf api`). Do not
|
|
267
|
+
prefix it with `/artifactory`.
|
|
268
|
+
- **Curation result discrimination with `jf api`**: the 200/403 signal comes
|
|
269
|
+
from `jf api`'s **exit code** plus a `returned NNN` line on **stderr**,
|
|
270
|
+
not from a `%{http_code}` appended to stdout. Capture stderr to a file
|
|
271
|
+
(`2> "$STDERR_FILE"`) and branch on `RC` + `grep 'returned 403'` as shown
|
|
272
|
+
in Step 6a.
|
|
273
|
+
- **Curation API package type values**: Must be lowercase and match one of
|
|
274
|
+
`npm`, `pypi`, `maven`, `go`, `nuget`, `docker`, `gradle`. Other values
|
|
275
|
+
will return an error.
|