mcpField
J
jfrog-package-safety-and-download

jfrog-package-safety-and-download

github.com/jfrog安全25101 次安装1 周前更新
代码仓库

关于 jfrog-package-safety-and-download

指导使用 JFrog Platform 检查并下载软件包的安全与下载流程,适合管理包依赖的开发者和运维人员。流程先查公共目录与存储包,再检查平台存储及适用的策展策略。

主要功能

  1. 01搜索公共目录与存储包
  2. 02确定软件包最新版本
  3. 03检查平台中是否已有版本
  4. 04按仓库类型下载制品
  5. 05检查策展许可与策略

适用场景

  1. 01下载前检查软件包是否已存储
  2. 02依据策展策略判断是否允许下载
  3. 03从 JFrog 远程仓库获取制品

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jfrog/jfrog-skills --skill jfrog-package-safety-and-download

安装后在 Claude Code 中输入/jfrog-package-safety-and-download确认已加载。

详细介绍

JFrog 软件包安全性与下载

前提条件

  • 阅读 ../jfrog/SKILL.md 了解 JFrog Platform 概念、领域模型、CLI 设置和 API 模式。
  • OneModel 的结构会随服务器版本而变化。 在自行构造 GraphQL 字段或 where 过滤器之前,请阅读 ../jfrog/references/onemodel-graphql.md(schema 获取工作流)和 ../jfrog/references/onemodel-query-examples.md(公共软件包、已存储软件包)。当示例无法通过验证时,请根据 GET "$JFROG_URL/onemodel/api/v1/supergraph/schema" 重新生成或验证查询。

工作流概览

flowchart TD
    A[User requests package check / download] --> B{Package in Public Catalog?}
    B -->|Yes| C[Get latest version from Catalog]
    B -->|No| D{Package in JFrog Platform Stored Packages?}
    D -->|Yes| E[Get latest version from Stored Packages]
    D -->|No| F[Package not found — stop]
    C --> G{Latest version in JFrog Platform?}
    E --> G
    G -->|Yes| H[Safe — download from JFrog Platform]
    G -->|No| I{Curation entitled?}
    I -->|Yes| J[Check curation policy via API]
    I -->|No| K[Download via remote repo]
    J -->|200 Allowed| K
    J -->|403 Blocked| M[Report curation blocked — stop]
并行化机会

此工作流中的若干步骤相互独立,可以并行运行以减少总延迟:

  • 步骤 1 + 步骤 1 回退:当软件包类型已知时,并行查询公共目录(getPackage)和已存储软件包(getPackage)。使用返回数据的那个;如果公共目录返回命中结果,则优先将其 latestVersion 用于步骤 2。
  • 步骤 3 + 步骤 5:确定版本后,并行查询已存储软件包版本(JFrog Platform 检查)和 curation 授权(/api/system/version)。两者都是独立的读取操作 —— 如果 JFrog Platform 检查返回为空,则立即需要 curation 结果。

在发出并行 Shell 调用时,每个 jf api 调用都会针对当前活动的 jf config 服务器独立进行身份验证;调用之间无需传递任何 shell 状态。

步骤 1:查找软件包

首先通过 OneModel GraphQL 搜索公共目录,如果未找到,则回退到已存储软件包。

按照 ../jfrog/references/onemodel-graphql.md 中的说明通过 jf api 执行查询;具体查询形态请参考 ../jfrog/references/onemodel-query-examples.md。

当软件包类型已知时(例如 npm、maven、pypi),使用 publicPackages.getPackage(type:, name:)(参见 获取公共软件包)。包含 latestVersion { version } 选择集 —— latestVersion 是一个对象,不是标量。

当类型未知时,使用带 nameContains 的 publicPackages.searchPackages(参见 搜索公共软件包)。当用户缩小生态系统范围时,添加 type:。

  • 找到 → 记下 type 和 latestVersion.version。继续步骤 2。
  • 未找到 → 该软件包可能属于第一方/第二方。使用 storedPackages.searchPackages 或 storedPackages.getPackage 搜索已存储软件包(参见 onemodel-query-examples.md 中的 已存储软件包领域)。已知时优先按 type 过滤;否则仅使用 nameContains。
    • 找到 → 记下 type 和 latestVersionName(或从 versionsConnection 推导出版本)。继续步骤 2。
    • 两者均未找到 → 报告“未找到软件包”并停止。

如果出现多个具有不同 type 值的结果,请询问用户指的是哪种软件包类型。

步骤 2:确定最新版本

来源版本字段
公共目录latestVersion.version(需要对象选择集)
JFrog Platform 已存储软件包StoredPackage 上的 latestVersionName,或来自 versionsConnection 的最高条目

步骤 3:检查软件包 + 最新版本是否存在于 JFrog Platform 中

使用带 hasPackageWith 过滤器的 storedPackages.searchPackageVersions 查询已存储软件包版本(参见 ../jfrog/references/onemodel-query-examples.md → 搜索已存储软件包版本)。为步骤 2 中的特定版本添加 version 过滤器,并请求 locationsConnection 以获取仓库详情(repositoryKey、repositoryType、leadArtifactPath)。

通过 jf api 执行查询(调用模式参见 ../jfrog/references/onemodel-graphql.md)。

  • 找到且带有位置信息 → 软件包位于 JFrog Platform 中。报告为可安全下载。继续步骤 4。
  • 未找到 → 继续步骤 5。

步骤 4:从 JFrog Platform 下载

使用步骤 3 中的位置信息。二进制构件下载通过 jf rt dl 进行——而不是 jf api。jf api 是 JFrog REST API(元数据、管理、策展等)的统一入口,并不提供 通过重定向链流式传输二进制内容所需的 -L / -o 标志。

<target> 必须是完整的文件路径(例如 ./downloads/lodash-4.18.1.tgz),而不是单纯的目录。jf rt dl --flat 会将目标视为文件名;传入目录会导致具有误导性的 "open path: is a directory" 错误。

repositoryType策略
local 或 federatedjf rt dl "<repositoryKey>/<leadArtifactPath>" <target-file> --flat
remote针对基础远程仓库(去掉末尾的 -cache)执行 jf rt dl —— 当构件尚未缓存时,它会透明地触发远程拉取

local / federated / remote 下载:

jf rt dl "<baseRepoKey>/<leadArtifactPath>" <target-file> --flat

解析远程仓库键: OneModel 为远程位置返回的 repositoryKey 通常已经以 -cache 结尾(例如 devNPM-remote-cache)。jf rt dl 需要的是基础远程仓库名称 (不带 -cache)。存在 -cache 后缀时将其去掉(例如 devNPM-remote-cache → devNPM-remote)。如果该键不以 -cache 结尾,则按原样使用。

仓库内特定包类型的路径格式请参见下方的 Protocol endpoints 表。

步骤 5:检查策展授权

jf api /artifactory/api/system/version \
  | jq '.addons | index("curation") != null'
  • true → 已获得策展授权。继续执行步骤 6a。
  • false → 策展不可用。继续执行步骤 6b。

步骤 6a:检查策展策略并下载

当已获得策展授权时,在下载前使用 Xray 策展 API 检查该 包版本是否在所有仓库中均被允许。

RESPONSE_FILE="/tmp/curation-status-$$.json"
PAYLOAD_FILE="/tmp/curation-payload-$$.json"
STDERR_FILE="/tmp/curation-err-$$.log"

jq -n \
  --arg type    "<TYPE>"    \
  --arg name    "<NAME>"    \
  --arg version "<VERSION>" \
  '{packageType:$type, packageName:$name, packageVersion:$version}' \
  > "$PAYLOAD_FILE"

set +e
jf api /xray/api/v1/curation/package_status/all_repos \
  -X POST -H "Content-Type: application/json" \
  --input "$PAYLOAD_FILE" \
  > "$RESPONSE_FILE" 2> "$STDERR_FILE"
RC=$?
set -e
echo "RC=$RC"; echo "$RESPONSE_FILE"

支持的 packageType 值:npm、pypi、maven、go、nuget、 docker、gradle。

使用 jf api 解读结果:与普通的 curl 不同,jf api 通过其退出码以及 stderr 上的一行 "<hh:mm:ss> [Warn] ... returned 4xx/5xx" 来呈现 HTTP 结果(而不是 stdout 中的 %{http_code} 后缀)。响应体始终写入 stdout。需同时解析两者:

if [ "$RC" -eq 0 ]; then
  echo "Package is allowed by curation."
elif grep -q 'returned 403' "$STDERR_FILE"; then
  echo "Blocked by curation policy:"
  cat "$RESPONSE_FILE"
else
  echo "Curation check failed (rc=$RC):"
  cat "$STDERR_FILE"
fi

评估结果:

  • 退出码 0 → 该包被策展策略允许。继续通过远程仓库 下载(与步骤 6b 相同)。
  • stderr 上出现 returned 403 → 该包被策展 策略阻止。响应体说明了是哪条策略规则阻止了它。向用户报告 阻止原因并停止——不要尝试下载。
  • 任何其他非零退出码 → 视为操作性失败(认证、DNS、 端点已禁用)并报告。

步骤 6b:在没有策展的情况下下载

当未获得策展授权且该包不在 JFrog Platform 中时, 直接通过远程仓库下载。

  1. 查找正确包类型的远程仓库:

    jf api \
      "/artifactory/api/repositories?type=remote&packageType=<TYPE>" \
      | jq '.[].key'
    
  2. 下载——针对基础远程仓库(不带 -cache)使用 jf rt dl;它会同时处理已缓存和未缓存的构件:

    jf rt dl "<repo>/<artifact-path>" <target-file> --flat
    

按包类型划分的构件路径

当 leadArtifactPath 无法从 OneModel 获取时,使用这些路径模式。开头的 <repo>/ 是你传给 jf rt dl 的基础仓库键。

Typejf rt dl 目标模式
npm<repo>/<pkg>/-/<pkg>-<version>.tgz
pypi<repo>/<pkg>/<version>/<pkg>-<version>.tar.gz
maven<repo>/<group-path>/<artifact>/<version>/<artifact>-<version>.jar
go<repo>/<module>/@v/<version>.zip

注意事项

  • 二进制下载与 jf api 的区别:jf api 用于 REST API,而不是二进制内容。它不会透明地跟随重定向获取二进制载荷,也不支持 -L / -o。请始终使用 jf rt dl(针对基础远程仓库,而非 -cache 仓库)来实际下载制品。
  • jf rt dl 与未缓存的远程仓库:jf rt dl "<remote>/<path>" —— 针对基础远程仓库而不是 <remote>-cache/<path> —— 会透明地触发远程拉取并缓存制品。不要尝试通过 jf api 预先查询代理。
  • jf rt dl --flat 的目标必须是文件路径:下载单个制品时,请传入完整的输出文件路径(例如 ./downloads/lodash-4.18.1.tgz),而不是目录。CLI 会将目标路径作为文件打开;传入目录会导致晦涩的 "open path: is a directory" 错误,并在失败前重试四次。请从 leadArtifactPath 推导文件名(取最后一个 / 之后的部分)。
  • 包类型检测:如果用户未指定包类型,仅按名称进行 Public Catalog 搜索可能会返回多种类型。请让用户先澄清后再继续。
  • 策展端点位于 Xray 下:使用 /xray/api/v1/curation/package_status/all_repos(通过 jf api)。不要为其添加 /artifactory 前缀。
  • 使用 jf api 判别策展结果:200/403 信号来自 jf api 的退出码以及 stderr 上的 returned NNN 行,而不是追加到 stdout 的 %{http_code}。请将 stderr 捕获到文件(2> "$STDERR_FILE"),并根据 RC + grep 'returned 403' 进行分支判断,如步骤 6a 所示。
  • 策展 API 的包类型取值:必须为小写,且匹配 npm、pypi、maven、go、nuget、docker、gradle 之一。其他值将返回错误。

评论

支持 Markdown