返回资讯中心
外部精选
软件工程
#开发者实时流

N6k 发布工具,让用户和 AI 代理在生产数据库上运行未受信任的 SQL

来源标题:N6k – Let users and agents run untrusted SQL on production databases

N6k 通过 WebSocket 以 n6k 协议对外提供 DuckDB catalog,使客户端和 AI 代理能在生产库上执行 SQL,但受行级与写入权限限制。它支持 OIDC 登录隔离各客户端数据行,并可将 BigQuery 数据集与本地表在同一进程中联合查询,云凭证保留在服务端。安装脚本支持 Linux 与 arm64 macOS。

Hacker News 最新srossross2026/11/8 · 今天19 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

通过 WebSocket 以 n6k 协议提供 DuckDB 目录服务。 curl -fsSL https://n6k-io.github.io/n6kd/get.sh | sh 安装最新版本及其扩展,适用于 Linux 或 arm64 上的 macOS。N6KD_VERSION 用于选择版本,N6KD_HOME 指定解压位置(/.n6kd),N6KD_BIN_DIR 指定 n6kd 符号链接的放置位置(/.local/bin)。快速上手:在本地用 NYC 数据运行 n6kd,控制客户端能看到哪些行以及可以写入什么。无需账号。让 AI agent 查询它:将 Claude Code 这类 MCP agent 指向快速上手服务器。它获得的限制与其他任何客户端相同。为每个客户端分配独立行:通过 OIDC 让客户端登录,使每个客户端只能看到和编辑自己的行。需要一个 OIDC issuer。组合 BigQuery 和本地数据:在同一个进程中同时提供 BigQuery 数据集和本地表,并支持跨源 join。云凭证保留在服务器上。需要一个 Google Cloud 项目。构建 go build -o n6kd . ./n6kd install # 下载 n6k DuckDB 扩展 若要对本地扩展构建运行,请将 N6K_EXTENSION_DIR 指向它们的 build/release/extension 目录,以操作系统路径列表形式提供(Unix 上用 :,Windows 上用 ;);每个目录中会查找 <name>/<name>.duckdb_extension。vcatbridge 来自 duckdb-virtual-catalog,n6k_client 和 n6k_server 来自 duckdb-n6k-protocol。未设置时测试会跳过。 n6kd -f schema.sql --perms perms.yml 启动 SQL 按 -f(文件)、-t(模板文件)和 -c(语句)给出的顺序执行。没有 --perms 时,加载数据库中的每个 catalog 都以读写、未桥接方式提供服务。-t 文件是先经 Go text/template 渲染的 -f 文件,用于 DuckDB 仅接受字面量的值,例如 ATTACH 字符串。{{ env "NAME" }} 插入环境变量,未设置时启动失败: ATTACH 'project=bigquery-public-data dataset=new_york_taxi_trips billing_project={{ env "BQ_BILLING_PROJECT" }}' AS taxi (TYPE bigquery); 使用 --listen=<path>(或 N6K_LISTEN=<path>)时,n6kd 监听该 Unix socket 而非 --addr,并以 n6k 流帧格式为每个连接的客户端在各自会话中提供服务。陈旧的 socket 文件会被替换,被活跃服务器占用的会被拒绝,文件权限为 0600,退出时删除。拨号的父进程负责认证;HELLO token 不被检查,--api-key / --oidc-* 在启动时被拒绝。

Flag Description -f, --file 启动时运行的 SQL 文件;可重复 -t, --template 经 Go text/template 渲染后在启动时运行的 SQL 文件;可重复 -c, --command 启动时运行的 SQL;可重复 --perms perms.yml,指定要以桥接方式提供的 catalog --addr 监听地址(默认 :8080,或 $PORT) --listen 要监听的 Unix socket,替代 --addr(N6K_LISTEN) --api-key 客户端必须提供的 token(N6KD_API_KEY) --oidc-issuer-url 客户端必须提供其 JWT 的 OIDC issuer(N6KD_OIDC_ISSUER_URL);不能与 --api-key 同用 --oidc-audience 客户端 JWT 必须携带的 aud claim(N6KD_OIDC_AUDIENCE);与 --oidc-issuer-url 一起必需 --oidc-client-id n6kd auth login 用于让用户登录的公共客户端,在 /.well-known/oauth-protected-resource 公布(N6KD_OIDC_CLIENT_ID) --load-dotenv[=path] 先从 .env(或 path)加载环境变量;已设置的变量优先 --allow-origin 允许连接的浏览器源;可重复,默认任意(N6KD_ALLOW_ORIGIN,逗号分隔) --lockdown / --no-lockdown 拒绝所服务连接的文件系统和扩展访问 --memory-limit / --threads 由 --lockdown 锁定,按会话数据库;默认使用 DuckDB 的(N6KD_MEMORY_LIMIT、N6KD_THREADS) --boot-only 运行启动 SQL 后退出,不提供服务 --debug 按连接和按 catalog 记录日志 --pprof 提供 Go net/http/pprof 的地址,默认关闭(N6KD_PPROF) --json-logging 带 Cloud Logging 严重性字段的 JSON 日志

Commands n6kd install — 将扩展下载到 DuckDB 的扩展目录 n6kd selftest — 端到端桥接一个临时 catalog n6kd quack — 改为通过 DuckDB 的 quack 协议提供服务;见下文 Quack n6kd quack -f schema.sql --perms perms.yml --token super_secret -- 从任意 DuckDB 客户端 INSTALL quack; LOAD quack; CREATE SECRET (TYPE quack, TOKEN 'super_secret'); ATTACH 'quack:localhost:8080' AS app; 与 n6k 不同的一种模型:一个数据库由所有客户端共享,一个 token,没有用户和 JWT claim。使用 --perms 时,perms.yml 必须恰好指定一个 catalog,以桥接方式作为主数据库提供,因为这是 quack 客户端 ATTACH 所能看到的全部;策略不会获得 $name 上下文值。没有 --perms 时,加载的数据库直接提供服务。Quack 使用纯 HTTP,因此请将 TLS 放在代理中。Quack 的 ATTACH 无法执行 UPDATE 或 DELETE;请通过 quack_query('quack:localhost:8080', '...') 发送这些操作。接受 -f、-c、--perms、lockdown 标志和 --boot-only 如上,外加: 设置 N6K_EXTENSION_DIR 时,本地 vcatbridge 构建会先安装到 DuckDB 的扩展目录:桥接的主数据库按名称加载它,源也必须加载同一副本。quack 和 httpfs 也从那里加载(n6kd install 会下载它们)。 catalogs: app: tables: main.users: primary_key: [id] select: true insert: true update: true delete: true main.audit_log: select: true main.orders: select: "status <> 'deleted'" insert: "amount > 0" update: { using: "status = 'open'", check: "amount > 0" } delete: "status = 'closed'" 每个 catalog 的值是一个 vcatbridge 策略文档,按原样传递给 vcatbridge_configure_policy;policy_version 默认为 1。有关所有设置(schemas、functions、foreign_keys 等),请参阅 bridge 的 docs/policy-v1.schema.json。bridge 在启动时验证文档,并在每次桥接该 catalog 时再次验证(按客户端,或在 quack 下仅一次),未列出的动词会被拒绝。update 和 delete 需要主键。当 bridge 无法从 schema 中发现主键时,primary_key 会覆盖它。每个 catalog 以其自己的名称提供服务: ATTACH 'n6k://localhost:8080' AS eggs (TYPE n6k, CATALOG 'app'); SELECT * FROM eggs.main.users; 别名由客户端自行选择;CATALOG 选择所服务的 catalog。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →