thinkst/package-proxy

GitHub: thinkst/package-proxy

部署于 Cloudflare Workers 的软件包仓库内联代理,为 pip、cargo、npm 等包管理器提供安装行为的可观测性与供应链安全策略控制。

Stars: 49 | Forks: 4

## Package Proxy 这是一个 Cloudflare Worker,可以被设置为 `uv/pip` 的 `index-url`、`cargo` 的 `registry` 或 `npm` 的 `registry`,并无缝地将请求代理到官方仓库。欲了解更多信息,请查看[博客文章](https://blog.thinkst.com/2026/06/introducing-package-proxy-supply-chain-safety-checks-without-client-side-software.html)。 ### 安装说明 [![部署到 Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https%3A%2F%2Fgithub.com%2Fthinkst%2Fpackage-proxy) #### 客户端配置 在 `./scripts/SetupPackageProxy.sh` 中有一个适用于 MacOS 的便捷设置脚本,只需使用你的 Cloudflare worker [子]域名编辑 `PACKAGE_PROXY_HOST`,并将其分发到你的整个设备群中。 或者,以下是手动步骤: 1. 将变量 `DOMAIN` 设置为 Worker 正在运行的 [子]域名: ```$ export DOMAIN=thinkst-package-proxy.mypackageproxy.workers.dev``` 2. **pip**: ```$ pip config set global.index-url https://$USER@$DOMAIN$/pypi/``` 3. **uv**: ```$ echo "index-url = \"https://$USER@$DOMAIN/pypi/\"" >> ~/.config/uv/uv.toml``` 4. **cargo**: ```$ echo -e "[registries]\npackage-proxy = { index = \"sparse+https://$USER@$DOMAIN/\" }\n[source.crates-io]\nreplace-with = \"package-proxy\"" >> ~/.cargo/config.toml``` 5. **npm**: ```$ npm config set registry https://$DOMAIN && npm config set //$DOMAIN/:_auth=$(echo -n "$USER:" | base64)``` ### 用法 像往常一样使用包管理器,不过如果某个包版本已被下架,客户端将直接报告未找到(HTTP 404),而不会显示其下架的具体错误/原因。 ### 包规则 代理默认配置为阻止安装符合以下条件的包: - 发布时间少于 10 天的版本 (`MIN_AGE_DAYS`) - 未被“撤回”的版本 (`ALLOW_YANKED`) - 发布方式不如前一版本可靠的版本 (`ALLOW_CHANGED_PUBLISHER`) - 特定的已知恶意版本(以 [PURL 类型](https://github.com/package-url/purl-spec)开头),例如 `npm/axios==0.30.4`,或 `pypi/base-x-64: ALL` (`blocklist`) 其余配置选项包括: - `npm audit` 是否可以绕过最低时间限制 (`ALLOW_AUDIT_OVERRIDE`) - 下载内容本身是否应通过代理提供服务(这也是执行日志记录的环节)(`REWRITE_DOWNLOAD_URLS`) - 特定版本的允许列表 (`allowlist`) - 可以定义一个 webhook URL (`webhook-url`),某些被阻止下载的详细信息将被发送到该地址。这在例如集成了 Slack 的环境中非常有用,可以为包无法安装提供上下文说明。 #### 划分配置范围 这些配置可以针对组织内的逻辑单元进行指定。如果提供了组织名称(子域名),那么 代理将在 KV store 中查找 `org-`(例如,acme.packageproxy.dev 将在 `org-acme` 中配置)。否则, 将使用 `default` 键的配置。如果不存在任何配置,系统将创建一个默认配置,其中包含 `./scripts/default-kv.json` 中的值。可以使用 `npx wrangler kv` 命令或通过 [Web 仪表板](https://dash.cloudflare.com)编辑此文件并将其推送到 KV store。 #### 修改规则值 规则存储在 KV store 中。为了手动修改它们: 1. 登录 Cloudflare [仪表板](https://dash.cloudflare.com) 2. 点击 "Storage & databases" > "Workers KV" 3. 点击与你的 Package Proxy 关联的 KV store 4. 点击 "KV Pairs" 标签页 5. 点击 `org-` 键上的 "View",然后点击 "Edit" 6. 更新你想要修改的配置值,然后点击 "Save"。更改将立即(在一两秒内)对 Worker 生效,无需进行任何进一步操作。 也可以使用 wrangler: 1. 获取当前设置: ``` $ namespace_id=$( \ npx wrangler kv namespace list | \ jq -r '.[] | select(.title | endswith("package-proxy")) | .id' \ ) $ org_name=$(npx wrangler kv key list --remote --namespace-id "${namespace_id}" | jq -r '.[] | select(.name | startswith("org-")) | .name') $ npx wrangler kv key get --remote --namespace-id "${namespace_id}" "${org_name}" > "${org_name}.json" ``` 2. 现在编辑 `${org_name}.json`,更新你的规则并保存。 3. 确认它仍然是有效的 JSON: ``` $ jq . "${org_name}.json" ``` 4. 最后,写回 Cloudflare: ``` $ npx wrangler kv key put --remote --namespace-id "${namespace_id}" "${org_name}" "$(cat ${org_name}.json)" ``` ## 可观测性 一旦代理被用于安装包,它将把用户和组织记录到已创建的 D1 数据库中。可以通过 [Cloudflare 仪表板](https://dash.cloudflare.com)、`wrangler` CLI 或 [API](https://developers.cloudflare.com/api/resources/d1) 查询或探索这些数据。 一些示例查询包括: - 返回所有安装过特定包的用户(及相应版本):`SELECT DISTINCT UserId, CONCAT(PackageName, '@', PackageVersion) as Installed FROM Installs WHERE PackageName LIKE ?;` - 获取已安装包的总数:`SELECT COUNT(*) FROM Installs;` - 获取所有已安装包的名称:`SELECT DISTINCT PackageName FROM Installs;` 使用 Wrangler,这些操作变为: ``` # 已安装的所有 packages 的名称 $ npx wrangler d1 execute install-logs --remote --command 'SELECT DISTINCT PackageName FROM Installs' # 查明谁安装了 requests $ npx wrangler d1 execute install-logs --remote --command "SELECT DISTINCT UserId, CONCAT(PackageName, '@', PackageVersion) as Installed FROM Installs WHERE PackageName LIKE '%requests'" # 已安装的 packages 总数 $ npx wrangler d1 execute install-logs --remote --command 'SELECT COUNT(*) FROM Installs' ```
标签:代理服务, 依赖管理, 安全策略, 提示词设计, 数据可视化, 程序员工具, 自动化攻击