Skip to content

Configuration Guide Community

Querycop の全環境変数リファレンスです。全ての設定は環境変数で行います。一部の設定はCLIフラグでも指定可能です。


基本的なプロキシ動作を制御する設定です。

環境変数デフォルトCLIフラグ説明
GATEKEEPER_LISTEN_PORT5432--listen-portプロキシのリッスンポート。クライアント(psql, DBeaver等)はこのポートに接続します
GATEKEEPER_BACKEND_HOSTlocalhost--backend-hostバックエンドデータベースのホスト名またはIPアドレス
GATEKEEPER_BACKEND_PORT5433--backend-portバックエンドデータベースのポート番号
GATEKEEPER_API_PORT8080--api-port管理API/ダッシュボードのHTTPポート
GATEKEEPER_APPROVAL_TIMEOUT30--approval-timeout承認待ちのタイムアウト秒数。超過するとクエリは自動的に却下されます
GATEKEEPER_PENDING_MAX10000-同時保持する pending 承認待ちクエリの上限。超過時は新規リクエストを即座に拒否(DoS 耐性)
GATEKEEPER_DB_TYPEpostgresql-データベースのWire Protocol種別。postgresql または mysql
Terminal window
# ポートをカスタマイズ
export GATEKEEPER_LISTEN_PORT=15432
export GATEKEEPER_BACKEND_HOST=db.example.com
export GATEKEEPER_BACKEND_PORT=5432
export GATEKEEPER_API_PORT=9090
export GATEKEEPER_APPROVAL_TIMEOUT=60
Terminal window
# MySQL接続の場合
export GATEKEEPER_DB_TYPE=mysql
export GATEKEEPER_BACKEND_PORT=3306

Managed cloud DB (AWS RDS / Aurora / Cloud SQL / AlloyDB / Neon / Supabase / PlanetScale 等) は全て TLS 強制が前提なので、Querycop はバックエンド (GATEKEEPER_BACKEND_HOST) への接続でも TLS をネゴシエートできます。 PostgreSQL・MySQL とも対応済み

環境変数デフォルト説明
GATEKEEPER_BACKEND_TLS_MODEDBType 別。PostgreSQL: prefer / MySQL: disablelibpq の sslmode と同じ値: disable / prefer / require / verify-ca / verify-full
GATEKEEPER_BACKEND_TLS_CA_FILE(なし)PEM 形式の CA bundle ファイル。verify-ca / verify-full必須 — 暗黙的な system root pool への fallback は意図的に無効化 (環境差を減らすため)
GATEKEEPER_BACKEND_TLS_SERVER_NAME(なし、空なら BACKEND_HOST から派生)SNI / hostname verification のためのサーバー名 override。Neon の compute endpoint や Supabase の pooler のように SNI でルーティングする managed DB では必須

default が DBType 別になっている理由

Section titled “default が DBType 別になっている理由”
  • PostgreSQL の prefer: libpq の既定と一致。SSLRequest → サーバが SN を返すクリーンな negotiation contract があり、N での plaintext fallback が安全に書ける。既存 plaintext-only PostgreSQL deployment はそのまま動く。
  • MySQL の disable: MySQL の CLIENT_SSL capability flag は handshake の前半 (auth 前) に立てる必要があり、PG の “S or N” のような明示的拒否表現がない。prefer を default にすると negotiation の見え方が複雑で「TLS-attempt 失敗時の plaintext fallback」が runtime ログから読み取りづらいので、初期値は最も安全な disable。managed MySQL を使う場合は cookbook で require / verify-full を明示推奨。
mode振る舞い
disableTLS 一切ネゴシエートしない (素の TCP)
prefer (PG default)SSLRequest を送り、backend が S を返せば TLS upgrade、N を返せば plaintext で続行 (INFO ログ)
requireTLS 必須。証明書検証はしない。N を受けたら fail
verify-caTLS 必須 + 証明書チェーンを CA bundle で検証 (hostname 検証はスキップ)。CA file 必須
verify-fullTLS 必須 + チェーン検証 + hostname 検証。CA file + ServerName 必須。IP literal の host は検証不能 (明示エラーで起動拒否)
mode振る舞い
disable (MySQL default)TLS 一切ネゴシエートしない
preferInitial Handshake で server が CLIENT_SSL capability を advertise していれば TLS upgrade (SSL Request Packet を seq=1 で送る → tls.Client handshake → 以降の client Response は seq=2 に rewrite)。CLIENT_SSL が無ければ plaintext で続行 (INFO ログ)
requireTLS 必須。server が CLIENT_SSL を advertise していなければ first-connection error (server capability は起動時には見られないので、最初の connection 時に検出)
verify-caTLS 必須 + チェーン検証。CA file 必須。CLIENT_SSL 無しは first-connection error
verify-fullTLS 必須 + チェーン検証 + hostname 検証。CA file + ServerName 必須。IP literal は起動時 fail-fast

検証エラーの起動時 fail-fast (PG + MySQL 共通)

Section titled “検証エラーの起動時 fail-fast (PG + MySQL 共通)”

設定ミスは起動時に検出して fail-fast します:

  • verify-ca / verify-fullCA_FILE 未設定 → 起動拒否
  • verify-fullSERVER_NAME 未設定かつ BACKEND_HOST が IP literal → 起動拒否
  • CA_FILE が読めない / PEM ブロックを含まない → 起動拒否
  • 未知の MODE 値 → 起動拒否

MySQL 固有の first-connection error: require / verify-* で MySQL backend が CLIENT_SSL を advertise していない場合は、起動時には検出できず最初の connection で失敗します (server capability は initial handshake 時にしか分からない)。これは documented behavior。

Client→proxy TLS (MySQL) は未実装: Querycop は MySQL では proxy↔backend (= Querycop ↔ DB) の TLS を terminate しますが、client↔proxy (= app ↔ Querycop) の MySQL TLS handshake は未実装です。そのため Querycop は backend から受け取った Initial Handshake の CLIENT_SSL capability bit を client に転送する前にクリアします (これをしないと、ssl-mode=PREFERRED の MySQL client が proxy 相手に TLS upgrade を試みてしまい handshake が破綻する)。PostgreSQL では client TLS termination が利用可能 (GATEKEEPER_PROXY_TLS_CERT/KEY)。MySQL でも同じことをしたい場合は proxy の前段に TLS terminating LB (HAProxy、stunnel など) を置いてください。client→proxy MySQL TLS は将来の epic で扱います。


Managed cloud DB の IAM 認証 (AWS RDS IAM auth / Cloud SQL IAM auth / AlloyDB IAM 等) では、固定パスワードの代わりに 短命 (15分等) の token をパスワード フィールドに入れて認証します。Querycop はこれを proxy が接続ごとに mint する 方式でサポートします。

環境変数デフォルト説明
GATEKEEPER_BACKEND_TOKEN_CMD(なし、空)Operator が指定する shell command。Querycop は接続ごとにこれを実行し、stdout (trim 後) を IAM token としてバックエンドの認証フィールドに埋め込む

接続が来ると Querycop は以下を行います:

  1. QUERYCOP_BACKEND_USER (DB user 名) / QUERYCOP_BACKEND_HOST (backend host:port) を 環境変数として 設定して shell command を実行 (10s timeout)
  2. stdout を strings.TrimSpace、empty なら error → connection abort
  3. PostgreSQL backend:
    • StartupMessage を forward
    • server の Authentication* request を読む
    • AuthenticationCleartextPassword (R=3): token を PasswordMessage として送信
    • AuthenticationMD5Password (R=5): server-supplied salt と user から MD5 hash を計算 (md5(md5(token + user) + salt))、md5... prefix 付きで PasswordMessage 送信
    • AuthenticationSASL/SCRAM (R=10/11/12): 現状は非対応、connection abort。SCRAM 対応は将来予定
  4. MySQL backend:
    • 既存の Phase 1/2 handshake で server greeting を読み、TLS upgrade
    • client の Handshake Response Packet を読む
    • client の auth plugin が mysql_clear_password の場合のみ、auth-data field を token で書き換えて backend に送信
    • それ以外の plugin (mysql_native_password 等) なら connection abort (fail-closed)
  5. token mint command 失敗 (non-zero exit / empty stdout / timeout) → connection abort、client password fallback はしない。fallback すると IAM auth が落ちているのに通常 password で通る可能性があり operator に気づかれにくいため

安全ガード: TLS mode が require 以上必須

Section titled “安全ガード: TLS mode が require 以上必須”

GATEKEEPER_BACKEND_TOKEN_CMD が設定されている場合、Querycop は起動時に GATEKEEPER_BACKEND_TLS_MODErequire / verify-ca / verify-full のいずれかであることを確認します。それ以外 (disable / prefer / 未設定) は 起動拒否

prefer は backend が 'N' (no SSL) を返した時 plaintext fallback に降りる 可能性があり、その場合 IAM token が cleartext で送られてしまいます。 これを防ぐため、cookbook では require 以上を必須要件とします。

  • MySQL client の plugin 指定: AWS の MySQL IAM auth は cleartext plugin 経由なので、client 側で --enable-cleartext-plugin (mysql client) や useSSL=true&useServerPrepStmts=false + cleartext plugin (JDBC connector) 等を設定する必要があります。Querycop は cleartext plugin 以外を fail-closed で拒否するので、client config を上手く揃えないと connection が立ちません
  • shell interpolation 防止: command 文字列内で $QUERYCOP_BACKEND_USER / $QUERYCOP_BACKEND_HOST を referenced できますが、%s 等の Go-side interpolation は しません。これは shell metacharacter (;, &&, backtick) が user 名に紛れ込んだ場合の injection を防ぐためです
  • token は決してログに出ません。command の stderr は失敗時のみ 256 bytes に truncate してログ出力します
  • connection per token: command は 接続ごとに 1 回 実行されます。 接続が長寿命でも token は再 mint されません (短命 token を使う設計上、 接続中に expire する可能性がある — proxy topology epic で扱う)
Terminal window
export GATEKEEPER_BACKEND_HOST=mydb.cluster-xxxxx.us-east-1.rds.amazonaws.com
export GATEKEEPER_BACKEND_PORT=5432
export GATEKEEPER_BACKEND_TLS_MODE=verify-full
export GATEKEEPER_BACKEND_TLS_CA_FILE=/etc/ssl/certs/rds-ca-rsa2048-g1.pem
export GATEKEEPER_BACKEND_TOKEN_CMD='aws rds generate-db-auth-token \
--hostname "$QUERYCOP_BACKEND_HOST" --port 5432 \
--region us-east-1 --username "$QUERYCOP_BACKEND_USER"'
Terminal window
export GATEKEEPER_BACKEND_HOST=10.20.30.40 # private IP via Cloud SQL Auth Proxy not needed if direct IP
export GATEKEEPER_BACKEND_PORT=5432
export GATEKEEPER_BACKEND_TLS_MODE=verify-full
export GATEKEEPER_BACKEND_TLS_CA_FILE=/etc/cloudsql/server-ca.pem
export GATEKEEPER_BACKEND_TOKEN_CMD='gcloud sql generate-login-token'
Terminal window
export GATEKEEPER_DB_TYPE=mysql # Pro license required
export GATEKEEPER_BACKEND_HOST=mymysql.cluster-xxxxx.us-east-1.rds.amazonaws.com
export GATEKEEPER_BACKEND_PORT=3306
export GATEKEEPER_BACKEND_TLS_MODE=verify-full
export GATEKEEPER_BACKEND_TLS_CA_FILE=/etc/ssl/certs/rds-ca-rsa2048-g1.pem
export GATEKEEPER_BACKEND_TOKEN_CMD='aws rds generate-db-auth-token \
--hostname "$QUERYCOP_BACKEND_HOST" --port 3306 \
--region us-east-1 --username "$QUERYCOP_BACKEND_USER"'
# Client must use mysql_clear_password plugin:
# mysql --enable-cleartext-plugin -u iam_user -h querycop ...
  • SASL/SCRAM 非対応 (PostgreSQL): 将来対応予定
  • MySQL は mysql_clear_password plugin 限定: 他の plugin は fail-closed
  • connection 中の token rotation 未対応: 接続ごと 1 回 mint。長時間接続で token が expire したら connection drop → 再接続が必要

managed DB 別の推奨設定 (詳細は cloud-db cookbook を参照)

Section titled “managed DB 別の推奨設定 (詳細は cloud-db cookbook を参照)”
ProviderDBTypeMODECA fileSNI
AWS RDS / Aurora PostgreSQLpostgresqlverify-fullRDS が公開する rds-ca-rsa2048-g1 等デフォルト OK
Cloud SQL PostgreSQL (direct)postgresqlverify-fullCloud SQL の server CA を exportデフォルト OK
Neonpostgresqlverify-fullLet’s Encrypt<endpoint-id>.<region>.aws.neon.tech を明示 (compute routing)
Supabase poolerpostgresqlverify-fullLet’s Encryptデフォルト OK
AlloyDB (direct)postgresqlverify-fullAlloyDB CA bundleデフォルト OK
AWS RDS / Aurora MySQLmysqlverify-fullrds-ca-rsa2048-g1 等 (PG と同じ)デフォルト OK
PlanetScalemysqlrequire または verify-fullsystem root から Let’s Encrypt を exportデフォルト OK
自前運用 PostgreSQL/MySQL (TLS なし)disable
  • PostgreSQL: default の prefer は既存 plaintext PostgreSQL も壊しません。SSLRequestN が返り INFO ログ 1 行 (backend declined TLS; continuing in plaintext) を残して plaintext で続行。ログを完全に静かにしたい場合は GATEKEEPER_BACKEND_TLS_MODE=disable を明示。
  • MySQL: default の disable は従来どおりの挙動。managed MySQL を使う場合は 明示的に require 以上を設定してください。プレーン MySQL 環境からの upgrade では何も変わりません。

Querycop の backend が PgBouncer / Supavisor / RDS Proxy / Vitess (PlanetScale) 等の connection pooler を経由している場合、その topology を Querycop に 伝えるためのフラグです。観測性専用 — Querycop はこの値を見て client SQL を 検査・拒否したりはしません。Pool 層の制約 (transaction-mode で session GUC が 切れる等) は pool 層自身が client に error を返すのが正しい責務分担で、 Querycop が二重に enforce すると複数 port を併用する topology を壊します。

環境変数デフォルト説明
GATEKEEPER_BACKEND_POOLER(空、silent default)Backend pooler topology hint。none / pgbouncer-txn / pgbouncer-session / vitess のいずれか。不正値は起動時 fail-fast
該当する topology起動時の挙動
"" / none直接接続 (pooler なし)silent — 起動ログを汚さない
pgbouncer-txnPgBouncer / Supavisor / RDS Proxy が transaction modeINFO 1 行 — session GUC / LISTEN/NOTIFY / advisory lock / temp table が COMMIT を跨がない / SQL-level PREPARE/EXECUTE が永続しない、を一覧
pgbouncer-sessionPgBouncer / Supavisor が session modeINFO 1 行 — connection density 経路だが session 意味論は維持
vitessVitess proxy (PlanetScale 等)INFO 1 行 — docs/cloud-db/planetscale.md の Vitess gotcha 節をクロスリンク
  • 値が "" または none の場合、Querycop は何も log せず、proxy の挙動は フラグ未導入時と完全に同一です。Library embedder が Config.BackendPooler を 未設定で proxy.New(cfg) を呼ぶケースも同様。
  • 不正値 (大文字小文字混在、typo、provider 名の推測等) は起動時に os.Exit(1) で fail-fast。BACKEND_TLS_MODE / BACKEND_TOKEN_CMD の validation と同じパターンで、typo silent fallback を防ぎます。
  • 値は metric label には載りません (現状は deferred、ダッシュボードの 需要が顕在化したら follow-up で追加予定)。

docs/cloud-db/index.md の “Pooler awareness flag” 表を参照してください。 要約:

  • Neon-pooler endpoint → pgbouncer-txn
  • Supabase Supavisor (port 6543) → pgbouncer-txn
  • Supabase Supavisor (port 5432) → pgbouncer-session
  • PlanetScale (常時 Vitess 経由) → vitess
  • それ以外の cookbook ページ (RDS direct, Cloud SQL, AlloyDB, Azure PG, CockroachDB Cloud, Timescale Cloud 等) → 未設定 (= none)

AIリスク評価エンジンの設定です。SQLクエリの危険度を0-100でスコアリングします。

環境変数デフォルト説明
AI_PROVIDERopenaiAIプロバイダー。openai / anthropic / gemini / ollama のいずれか
AI_API_KEY(なし)AIプロバイダーのAPIキー。ollama 以外は必須
AI_ENDPOINT(プロバイダー既定)AIのAPIエンドポイントURL。カスタムエンドポイントやプロキシ経由で接続する場合に設定
AI_MODEL(プロバイダー既定)使用するモデル名 (FeatureAdvancedAIProvider, Pro+)。Community では設定しても無視され provider 既定モデルが使われる (起動時に INFO ログ)。AI_SYSTEM_PROMPT と同じ二層 gate (起動時 build + AnalyzeSQL ごとに live license 再確認 → heartbeat downgrade 時は即座に既定モデルへ戻る)。multi-provider / fallback は未実装 (roadmap)
AI_SYSTEM_PROMPT(なし、組み込み既定 prompt)リスクスコアリングの system prompt を上書きする (FeatureCustomAIPrompt, Pro+)。Community では設定しても無視され組み込み既定 prompt が使われる (起動時に INFO ログ)。二層 gate: 起動時に license を見て build、かつ AnalyzeSQL ごとに live license を再確認するため heartbeat downgrade 時は即座に既定 prompt に戻る。注意: ここに入れた prompt は operator が信頼する設定として LLM へそのまま渡される。SQL payload 側の PII redaction (GATEKEEPER_AI_PII_REDACTION) は引き続き適用される
GATEKEEPER_AI_PII_REDACTIONtrueAI 送信前に SQL 中の PII (email/電話番号/クレジットカード/SSN/マイナンバー/IPアドレス) を [EMAIL] / [PHONE] / [CC] / [SSN] / [MYNUMBER] / [IP] などの placeholder に置換する。false / 0 / off / no で opt-out

注意: AI_API_KEY が未設定かつプロバイダーが ollama 以外の場合、AIリスク評価は無効になります。その場合、RBACポリシーのみで判定が行われます。

Querycop はデフォルトで、外部 AI プロバイダ (OpenAI / Anthropic / Gemini) に SQL を送信する前に、SQL 中の PII を placeholder に置換します。

PII 種別placeholder検知パターン例
メールアドレス[EMAIL]victim@example.com
クレジットカード番号[CC]4111-1111-1111-1111 / 4111 1111 1111 1111
電話番号[PHONE]+81-90-1234-5678 / 090-1234-5678 / 03-1234-5678
SSN (米国)[SSN]123-45-6789
マイナンバー[MYNUMBER]1234 5678 9012
郵便番号 (〒)[POSTAL]〒123-4567
IPv4 アドレス[IP]192.168.1.1
  • スコアリング品質を保つため、PII は削除ではなく placeholder 化します。AI は「email 列の検索」「credit card のバルク更新」といった文脈を失いません。
  • 既定値は true。ローカル推論 (AI_PROVIDER=ollama) でも redaction は適用されます。Opt-out するには GATEKEEPER_AI_PII_REDACTION=false を設定。
  • 保守的 (false positive 許容) に実装しているため、偶発的な数字列が placeholder に置換されることがあります。スコア判定への影響は軽微です。
Terminal window
export AI_PROVIDER=openai
export AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxx
export AI_MODEL=gpt-4o # オプション
Terminal window
export AI_PROVIDER=anthropic
export AI_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxx
export AI_MODEL=claude-sonnet-4-20250514 # オプション
Terminal window
export AI_PROVIDER=gemini
export AI_API_KEY=AIzaXXXXXXXXXXXXXXXXXXXX
export AI_MODEL=gemini-pro # オプション
Terminal window
export AI_PROVIDER=ollama
# AI_API_KEYは不要
export AI_ENDPOINT=http://localhost:11434 # オプション(Ollamaデフォルト)
export AI_MODEL=llama3 # オプション

ロールベースアクセス制御の設定です。

環境変数デフォルト説明
GATEKEEPER_ROLES(なし)ユーザーへのロール割り当て。形式: role:user1,user2;role2:user3
GATEKEEPER_POLICY_FILE(なし)JSONポリシーファイルのパス。カスタムルールやロール設定を定義

優先順位: GATEKEEPER_POLICY_FILE が設定されている場合、GATEKEEPER_ROLES は無視されます。どちらも未設定の場合、全ユーザーが junior_dev ロールとして扱われます。

ロール名:ユーザー1,ユーザー2;ロール名:ユーザー3
Terminal window
# 設定例
export GATEKEEPER_ROLES="read_only:viewer1,viewer2;junior_dev:dev1,dev2;senior_dev:lead1;admin:dba_admin"
Terminal window
export GATEKEEPER_POLICY_FILE=/etc/gatekeeper/policy.json

ポリシーファイルの詳細な書き方は rbac-policy-guide.md を参照してください。


管理APIの認証と接続レートリミットの設定です。

環境変数デフォルト説明
ADMIN_API_KEY(なし)管理API認証用のBearer Token。未設定かつ OIDC 未設定の場合は起動停止(後述 S-01 参照)
GATEKEEPER_ADMIN_ALLOW_UNAUTH(なし)1 を設定した場合のみ、ADMIN_API_KEY も OIDC も未設定の状態での起動を許可する(非推奨・開発用
GATEKEEPER_ADMIN_REQUIRE_TLS(なし)true にすると TLS cert/key 未設定時に起動を拒否(本番 fail-closed)
GATEKEEPER_SESSION_MAX10000同時保持する admin session の上限。login 連打での OOM 防御。到達時は 503 を返す
GATEKEEPER_RATE_LIMIT100IP単位の1秒あたりの最大リクエスト数(Token Bucket方式)
GATEKEEPER_RATE_BURST200バーストサイズ。瞬間的に許容するリクエスト数の上限
GATEKEEPER_RATE_BLOCK_SECONDS60レートリミット超過時のIPブロック秒数

⚠️ Security Warning: The /debug/pprof/ profiling endpoint is exposed on the admin API port. Always set ADMIN_API_KEY in production to prevent unauthorized access to memory and CPU dumps.

GATEKEEPER_TLS_CERT + GATEKEEPER_TLS_KEY が未設定で、かつ GATEKEEPER_LISTEN_ADDR が loopback (127.0.0.1 / localhost / ::1) 以外の場合、起動時に CRITICAL 警告が 出ます。本番で admin API を外部ネットワークから到達可能にする場合は、以下のいずれかを 必ず実施してください:

  • 推奨: TLS-terminating リバースプロキシ(nginx / Envoy / CDN)の背後に置く
  • プロキシ本体で TLS を終端する(GATEKEEPER_TLS_CERT + GATEKEEPER_TLS_KEY
  • 外部到達を避ける(GATEKEEPER_LISTEN_ADDR=127.0.0.1

さらに強制したい場合は GATEKEEPER_ADMIN_REQUIRE_TLS=true を設定すると、TLS 未設定時に 起動を拒否 します(fail-closed)。

Admin API 認証の fail-closed 挙動(S-01)

Section titled “Admin API 認証の fail-closed 挙動(S-01)”

v0 以降、ADMIN_API_KEY も OIDC(GATEKEEPER_OIDC_ISSUER)も未設定のまま起動しようとすると、Querycop は fatal ログを出して起動を拒否 します(fail-closed)。誤って無認証のまま本番公開する事故を防ぐためです。

どうしても無認証で起動したい場合(ローカル開発など)は、明示的に opt-in してください:

Terminal window
export GATEKEEPER_ADMIN_ALLOW_UNAUTH=1

ただし GATEKEEPER_ADMIN_ALLOW_UNAUTH=1 を設定していても、GATEKEEPER_LISTEN_ADDR が外部から到達可能なアドレス(0.0.0.0::、空文字、RFC1918 IP、公開 IP、解決不能ホスト名など)の場合は起動を拒否します。

  • 許可される listen アドレス(無認証モード時): 127.0.0.1, ::1, localhost
  • 拒否される listen アドレス: 0.0.0.0, ::, 192.168.x.x, 外部 IP, ホスト名

この制約を外す唯一の方法は、ADMIN_API_KEY または OIDC を設定することです。

Terminal window
# 管理API認証を有効化
export ADMIN_API_KEY=my-secret-admin-token
# レートリミットのカスタマイズ
export GATEKEEPER_RATE_LIMIT=50 # 1秒あたり50リクエスト
export GATEKEEPER_RATE_BURST=100 # バースト100
export GATEKEEPER_RATE_BLOCK_SECONDS=120 # 超過時2分間ブロック

ADMIN_API_KEY を設定すると、GET /(ダッシュボード)以外の全APIエンドポイントに Authorization ヘッダーが必要になります。

Terminal window
# 認証ありでリクエスト一覧を取得
curl -H "Authorization: Bearer my-secret-admin-token" \
http://localhost:8080/requests

大容量リード遮断(Data Exfiltration防止)とデータマスキングの設定です。

環境変数デフォルト説明
GATEKEEPER_MAX_RESPONSE_MB100単一レスポンスの最大サイズ(MB)。超過するとクエリが遮断されます
GATEKEEPER_MAX_WINDOW_MB50060秒間のスライディングウィンドウでの累積転送量上限(MB)
GATEKEEPER_MASKING_FILE(なし)データマスキング設定ファイル(JSON)のパス
Terminal window
# データガードの設定
export GATEKEEPER_MAX_RESPONSE_MB=50 # 単一レスポンス50MBまで
export GATEKEEPER_MAX_WINDOW_MB=200 # 60秒間で200MBまで
# データマスキングの有効化
export GATEKEEPER_MASKING_FILE=/etc/gatekeeper/masking.json
{
"rules": [
{
"table": "users",
"column": "email",
"mask_type": "partial",
"apply_to": ["junior_dev", "read_only"]
},
{
"table": "users",
"column": "password_hash",
"mask_type": "full"
},
{
"table": "payments",
"column": "card_number",
"mask_type": "partial",
"exempt_from": ["admin"]
},
{
"table": "",
"column": "ssn",
"mask_type": "hash",
"apply_to": ["junior_dev"]
}
]
}

マスキングタイプ:

  • full - 値を完全にマスク(例: ****
  • partial - 一部のみ表示(例: t***@example.com
  • hash - ハッシュ値に置換

Just-In-Timeアクセス(申請 → 承認 → 一時ユーザー生成 → 自動失効)の設定です。

環境変数デフォルト説明
GATEKEEPER_JIT_MAX_TTL28800JITアクセスの最大有効期間(秒)。デフォルトは8時間(28800秒)
Terminal window
# JITアクセスの最大TTLを4時間に制限
export GATEKEEPER_JIT_MAX_TTL=14400

承認待ちクエリの通知設定です。

環境変数デフォルト説明
GATEKEEPER_SLACK_WEBHOOK_URL(なし)Slack Incoming WebhookのURL。設定するとBlock Kit形式で承認リクエスト通知を送信

未設定の場合、通知はコンソール(標準出力)に出力されます。

Terminal window
export GATEKEEPER_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX

Break-Glass緊急アクセスモードの設定です。緊急時に通常のポリシーをバイパスし、全操作を記録します。

環境変数デフォルト説明
GATEKEEPER_BREAKGLASS_MAX_TTL3600Break-Glassセッションの最大有効期間(秒)。デフォルトは1時間
GATEKEEPER_BREAKGLASS_TOKEN(なし)Break-Glass 専用トークン。設定時は activate/deactivate で これ必須(ADMIN_API_KEY では通らない)
Terminal window
# Break-Glassの最大TTLを30分に制限
export GATEKEEPER_BREAKGLASS_MAX_TTL=1800

環境変数デフォルトカテゴリ
GATEKEEPER_LISTEN_PORT5432プロキシ
GATEKEEPER_BACKEND_HOSTlocalhostプロキシ
GATEKEEPER_BACKEND_PORT5433プロキシ
GATEKEEPER_API_PORT8080プロキシ
GATEKEEPER_APPROVAL_TIMEOUT30プロキシ
GATEKEEPER_DB_TYPEpostgresqlプロキシ
AI_PROVIDERopenaiAI
AI_API_KEY(なし)AI
AI_ENDPOINT(プロバイダー既定)AI
AI_MODEL(プロバイダー既定)AI
GATEKEEPER_ROLES(なし)RBAC
GATEKEEPER_POLICY_FILE(なし)RBAC
ADMIN_API_KEY(なし)セキュリティ
GATEKEEPER_ADMIN_ALLOW_UNAUTH(なし)セキュリティ
GATEKEEPER_RATE_LIMIT100セキュリティ
GATEKEEPER_RATE_BURST200セキュリティ
GATEKEEPER_RATE_BLOCK_SECONDS60セキュリティ
GATEKEEPER_MAX_RESPONSE_MB100データ保護
GATEKEEPER_MAX_WINDOW_MB500データ保護
GATEKEEPER_MASKING_FILE(なし)データ保護
GATEKEEPER_JIT_MAX_TTL28800JIT
GATEKEEPER_JIT_PG_DSN(なし)JIT
GATEKEEPER_JIT_PG_ROLE_READ_ONLYqg_read_onlyJIT
GATEKEEPER_JIT_PG_ROLE_JUNIOR_DEVqg_junior_devJIT
GATEKEEPER_JIT_PG_ROLE_SENIOR_DEVqg_senior_devJIT
GATEKEEPER_JIT_PG_ROLE_ADMINqg_adminJIT
GATEKEEPER_SLACK_WEBHOOK_URL(なし)通知
GATEKEEPER_BREAKGLASS_MAX_TTL3600Break-Glass
GATEKEEPER_LISTEN_ADDR127.0.0.1プロキシ
GATEKEEPER_TLS_CERT(なし)セキュリティ
GATEKEEPER_TLS_KEY(なし)セキュリティ
GATEKEEPER_LOG_FORMATtext運用
GATEKEEPER_HTTP_RATE_LIMIT10セキュリティ
GATEKEEPER_HTTP_RATE_BURST30セキュリティ
GATEKEEPER_AUDIT_FILE(なし)監査
GATEKEEPER_AUDIT_HMAC_KEY(なし)監査(tamper evidence: 設定時は JSONL に HMAC hash chain を追記)
GATEKEEPER_AUDIT_RETENTION_DAYS(なし = license limit)監査(retention 窓 override、Enterprise FeatureAuditRetentionControls。詳細 §10.4)
GATEKEEPER_WEBHOOK_FILE(なし)通知
GATEKEEPER_CORS_ORIGIN(なし)セキュリティ
GATEKEEPER_EXTERNAL_URL(なし)通知
GATEKEEPER_ENABLE_PPROF(なし)デバッグ
QUERYGUARD_LICENSE_KEY(なし)ライセンス token (env)。後方互換のため env 名は維持
GATEKEEPER_LICENSE_FILE(なし)ライセンス token のファイルパス。env 未設定時の fallback
QUERYGUARD_LICENSE_PUBLIC_KEY(同梱の公式公開鍵)検証用公開鍵 (env)。指定がなければビルド時 embed の公式鍵
GATEKEEPER_LICENSE_PUBLIC_KEY_FILE(なし)公開鍵をファイルから読む場合のパス
GATEKEEPER_LICENSE_HEARTBEAT_URLtier 別(§11.4)online activation server URL。paid Pro(trial でない Pro)は未設定でも公式 server に default-on、それ以外は空 = OFF。off / disabled / none で明示無効化
GATEKEEPER_LICENSE_HEARTBEAT_INTERVAL_SECONDS86400heartbeat 間隔 (24h)
GATEKEEPER_LICENSE_HEARTBEAT_TIMEOUT_SECONDS30heartbeat per-ping timeout
GATEKEEPER_LICENSE_OFFLINE_GRACE_SECONDS604800オフライン猶予 (7 日)。超過で Pro 機能 disable
GATEKEEPER_OIDC_ISSUER(なし)SSO
GATEKEEPER_OIDC_CLIENT_ID(なし)SSO
GATEKEEPER_OIDC_ROLE_CLAIMgroupsSSO
(no env)SafeTransportSSO: OIDC discovery / token / JWKS fetch は SSRF 防御付き HTTP client を使い、private / link-local / IMDS 等へのリダイレクト接続を拒否
GATEKEEPER_OIDC_CLIENT_SECRET(なし)SSO
GATEKEEPER_OIDC_REDIRECT_URI(なし)SSO
GATEKEEPER_OIDC_ROLE_MAP(なし)SSO
GATEKEEPER_SLACK_MODEwebhook通知
GATEKEEPER_SLACK_SIGNING_SECRET(なし)通知
GATEKEEPER_CLUSTER_MODEmemoryクラスタ
GATEKEEPER_REDIS_ADDR(なし)クラスタ
GATEKEEPER_REDIS_PASSWORD(なし)クラスタ
GATEKEEPER_REDIS_DB0クラスタ
GATEKEEPER_CLUSTER_KEY_PREFIXquerycopクラスタ
GATEKEEPER_REDIS_KEY_PREFIX(deprecated alias)クラスタ
GATEKEEPER_BILLING_PROVIDERnone課金
GATEKEEPER_STRIPE_API_KEY(なし)課金
GATEKEEPER_STRIPE_METER_ID(なし)課金
GATEKEEPER_BILLING_CUSTOMER_IDdefault課金
GATEKEEPER_BILLING_BUFFER_SIZE1000課金
GATEKEEPER_BREAKGLASS_TOKEN(なし)Break-Glass
GATEKEEPER_PROXY_TLS_CERT(なし)プロキシTLS
GATEKEEPER_PROXY_TLS_KEY(なし)プロキシTLS
GATEKEEPER_SESSION_MAX1000セッション記録
GATEKEEPER_SESSION_FILE(なし)セッション永続化

9. QueryGuard → Querycop リネームに伴う移行ガイド

Section titled “9. QueryGuard → Querycop リネームに伴う移行ガイド”

対象: プロダクト名を QueryGuard から Querycop にリネームしました。既存デプロイで wire-level に使われていた名前空間も同時に更新されています。旧名を引き続き使う互換手段を用意していますが、deprecation 期間中のみ有効です

項目旧デフォルト新デフォルト互換性
Redis key prefixqueryguard:*querycop:*既存 queryguard を使い続けるには GATEKEEPER_CLUSTER_KEY_PREFIX=queryguard を設定
Pub/Sub channel prefixqueryguard:resolve:*querycop:resolve:*同上(prefix は同じ env 変数で統一される)

既存デプロイの扱い:

  • Redis に queryguard:* キーが残っている環境では、移行期間中は GATEKEEPER_CLUSTER_KEY_PREFIX=queryguard を設定して旧動作を維持してください。
  • 新規デプロイはデフォルト (querycop) を使用してください。
  • GATEKEEPER_REDIS_KEY_PREFIXdeprecated alias として引き続き認識されます (値が空でなければ GATEKEEPER_CLUSTER_KEY_PREFIX より低い優先度で採用)。次メジャーで削除予定。

移行推奨手順 (クラスタ稼働中のローリング更新):

  1. 1 ノードを GATEKEEPER_CLUSTER_KEY_PREFIX=queryguard で新バージョン起動 → 従来の pending セッション継続
  2. 全ノード更新完了後、一度サービス停止できるメンテウィンドウで querycop に切り替え
  3. 旧 key は Redis 側で DEL queryguard:* や TTL 失効で破棄

9.2 Slack interactive buttons の action_id

Section titled “9.2 Slack interactive buttons の action_id”
項目
block_idqueryguard_actionsquerycop_actions
approve action_idqueryguard_approvequerycop_approve
reject action_idqueryguard_rejectquerycop_reject

互換性: /slack/interactions エンドポイントは 旧 action_id も引き続き受け付けます。Slack に残る旧メッセージのボタンをクリックしても正しく動作します。新規送信メッセージは querycop_* で送られます。

項目
source フィールド"queryguard""querycop"
User-AgentQueryGuard-Webhook/1.0Querycop-Webhook/1.0

影響: 外部システム側で source == "queryguard" をハードコードしている場合は "querycop" に更新してください。移行期間中の両対応は 呼び出し側で実装する必要があります (Querycop 本体は新値のみ送信)。

Helm チャートのディレクトリ・チャート名・テンプレートのリソース名を queryguard から querycop にリネームしました。

項目互換性
チャートディレクトリcharts/queryguard/charts/querycop/パス参照を更新。レジストリ配布はないのでローカルパス参照のみ影響。旧パスには移行先を案内する tombstone README を残置
Chart 名 (Chart.yaml)queryguardquerycophelm install の release 名は任意なので影響なし
リソース名<release>-queryguard<release>-querycop既存リリースの in-place upgrade には --set nameOverride=queryguard が必須
selector labelapp: queryguardapp: querycopDeployment の selector は immutablenameOverride=queryguard を渡さないと helm upgrade が Kubernetes に拒否される
image.repository デフォルトqueryguard (誤り)querycop公開イメージ名は元々 querycop。旧デフォルトは存在しないイメージを pull する bug だった
cluster.redis.keyPrefix デフォルトqueryguardquerycop§9.1 の code デフォルトと一致。既存 queryguard:* キーがある環境は --set cluster.redis.keyPrefix=queryguard を設定

新規デプロイ:

Terminal window
helm install <release> ./charts/querycop \
--set backend.host=my-postgres \
--set api.adminApiKey=your-secret-key

既存デプロイの in-place upgrade (旧 queryguard 名で稼働中):

Terminal window
helm upgrade <release> ./charts/querycop \
--set nameOverride=queryguard \
--set cluster.redis.keyPrefix=queryguard # Redis backend を使う場合のみ

nameOverride=queryguard を渡すと、レンダリングされるリソース名 (<release>-queryguard) と selector label (app: queryguard) が リネーム前と byte-identical になり、Deployment selector の immutability 制約に抵触せず in-place upgrade が成立します。

クリーンな新名称への移行: メンテナンス枠で helm uninstallhelm install してください。persistence.auditFile を使っている場合は PVC の retain policy に注意 (デフォルトの ReadWriteOnce PVC は release 削除時に削除され得ます)。


監査ログは 2 つの独立したシンク に書き込まれます。それぞれ持つフィールドと API での見え方が違うので、運用設計時に意識する必要があります。

シンク永続化フィールド設定
メモリストア (audit.MemoryStore)プロセス内 (最大 10,000 件、再起動で消失)標準フィールドのみデフォルトで常に有効
JSONL ファイルログ (audit.FileStore)永続標準フィールド + prev_hash / hash(HMAC chain 設定時)GATEKEEPER_AUDIT_FILE で有効化
Webhook 連携外部基盤 (Datadog / Splunk / 自前) で永続標準フィールドGATEKEEPER_WEBHOOK_FILE

重要: REST API GET /auditメモリストアからのみ 取得します。HMAC chain の prev_hash / hashJSONL ファイルにのみ 追記されるため、API レスポンスには含まれません。改ざん検知の検証はファイルを直接読む別ツールで行ってください(pkg/audit.VerifyChain を使えるオフライン検証ツールが組み込み可能)。

10.2 HMAC hash chain (S-07, tamper evidence)

Section titled “10.2 HMAC hash chain (S-07, tamper evidence)”

GATEKEEPER_AUDIT_HMAC_KEY を設定すると、JSONL の各エントリに以下が追記されます:

{
"id":"...","timestamp":"...","event_type":"approved",
"prev_hash":"<前 entry の hash、最初は空>",
"hash":"<HMAC-SHA256(key, prev_hash || canonical(entry))>"
}

pkg/audit.VerifyChain(reader, key) で先頭から順に検証でき、改ざん箇所のインデックスを FirstBadIndex で返します。

HMAC キーの管理: HMAC キーが Querycop と同居していると、ホスト侵害時に攻撃者が改ざん + 再ハッシュできるため、tamper evidence は半減します。本番では Vault / KMS / HSM など別ストアでキーを管理してください。

本番環境では以下を併用することを推奨します:

  1. JSONL + HMAC: ファイル保管 (GATEKEEPER_AUDIT_FILE + GATEKEEPER_AUDIT_HMAC_KEY) で 改ざん検知付きの local trail を残す
  2. Webhook 連携: 外部 SIEM / log aggregator にリアルタイム転送し、ホスト障害時の保証を持たせる
  3. Slack 通知: GATEKEEPER_SLACK_WEBHOOK_URL で重要イベントを人間に即時通知

将来のバージョンでは、SQLite / PostgreSQL 連携による監査ログの直接永続化を予定しています。

audit_retention_days limit(entitlements.md §4)が 実際に enforce されます。retention 窓より古い audit entry / closed session が JSONL ファイルから prune されます。

⚠️ Pro デプロイへの behavior change: Pro の license limit は 30 日です。retention enforcement に対応したバージョンに上げると、永続 audit file (GATEKEEPER_AUDIT_FILE) / session file (GATEKEEPER_SESSION_FILE) の 30 日より古いレコードは初回起動時に prune されます。長期保持が 必要な場合は upgrade 前にファイルを退避するか、retention 窓を契約で 設定できる Enterprise(FeatureAuditRetentionControls)を検討して ください。

環境変数デフォルト説明
GATEKEEPER_AUDIT_RETENTION_DAYS(なし = license limit に従う)Retention 窓の override (FeatureAuditRetentionControls, Enterprise)。0 = prune しない(Enterprise の opt-out)。非 Enterprise では無視され license limit (Pro 30 日) が適用される (起動時に INFO ログ)

動作:

  • 実行タイミング: 初回 prune は proxy がトラフィックを受け付ける前 に同期実行(アップグレード直後の大きな backlog prune がクエリを 停止させない)。以降は 24 時間ごとに background 実行。
  • Fail-safe: パース不能な行・timestamp が zero の entry・ended_at が無い session は 削除しない(曖昧なものは残す)。書き込みは temp file + atomic rename で、エラー時は元ファイル無傷。
  • 自己監査: prune 実行のたびに retention_prune event が audit log に記録される(何件削除・cutoff・HMAC chain mode では削除セグメント 最終 entry の hash を forensic anchor として含む)。コンプライアンス 証跡の削除自体が証跡として残ります。
  • HMAC chain との関係: prune 後、生存 entry は genesis から re-chain され、retention_prune event が chain 末尾に連結されます。 VerifyChain は prune 後のファイルでも pass します。chain の脅威 モデルは「鍵を持たない者による改ざんの検知」であり、鍵保持者 (Querycop 自身) による prune は in-chain の prune event で可視化 されます — 黙って消えるのではなく、消したことが記録されます。
  • Runtime re-check: retention 窓は実行のたびに live license から 再解決されます。Enterprise → Pro の heartbeat downgrade で GATEKEEPER_AUDIT_RETENTION_DAYS の override は失効し、次回実行から Pro の 30 日 cap が適用されます。

11. ライセンス(Wowza 流アクティベーション)

Section titled “11. ライセンス(Wowza 流アクティベーション)”

Querycop は Apache 2.0 OSS の上に closed-source 寄りの Pro/Enterprise tier を載せるモデル。 license token (Ed25519 署名) で機能 gating + 30 日 trial + online activation (heartbeat) を提供。

querycop 起動時、license token は以下の順で解決されます:

  1. QUERYGUARD_LICENSE_KEY (env、最優先・後方互換のため env 名は維持)
  2. GATEKEEPER_LICENSE_FILE が指すパス (例: /etc/querycop/license.token)
  3. <UserConfigDir>/querycop/license.token
    • Windows: %AppData%\querycop\license.token
    • macOS: ~/Library/Application Support/querycop/license.token
    • Linux: ~/.config/querycop/license.token
  4. $HOME/.querycop/license.token (UserConfigDir 解決失敗時の fallback)

これにより querycop-cli trial start で取得した token は、追加設定なしで querycop 起動時に自動 pickup されます。

  1. QUERYGUARD_LICENSE_PUBLIC_KEY (env)
  2. GATEKEEPER_LICENSE_PUBLIC_KEY_FILE ファイル
  3. ビルド時 embedded な公式公開鍵 (GoReleaser が ldflags で注入。dev build では空)
Terminal window
querycop-cli trial start --email=ops@your-company.com --company="Your Co."
# → 30 日 Pro trial token を ~/.config/querycop/license.token に保存
querycop # ↑が自動 pickup されて Pro 起動

11.4 オンライン activation (heartbeat)

Section titled “11.4 オンライン activation (heartbeat)”

GATEKEEPER_LICENSE_HEARTBEAT_URL を設定すると、24 時間ごとに license server に ping を打ち、revocation があれば即降格 (Pro 機能 disable)、network 不通時は GATEKEEPER_LICENSE_OFFLINE_GRACE_SECONDS (default 7 日) 以内なら継続、超過で降格。

default の挙動: paid Pro license(is_trial=false の Pro) では未設定でも https://api.querycop.com/v1/license/heartbeat に default-on になりました。paid Pro は phone-home tier で、返金・支払い停止の revocation は heartbeat 経由でのみ届くためです。trial / Community / Enterprise は従来どおり 未設定 = OFF。ネットワーク制限環境で heartbeat を切る場合は GATEKEEPER_LICENSE_HEARTBEAT_URL=offdisabled / none も可)を明示して ください — 設定せず不通のままだと offline grace(7 日)超過で Community に 降格します。offline / air-gapped 運用の正式経路は Enterprise の Offline License 機能です。

EnvDefault
GATEKEEPER_LICENSE_HEARTBEAT_URLpaid Pro: 公式 server に default-on / それ以外: 空 = OFF。off で明示無効化
GATEKEEPER_LICENSE_HEARTBEAT_INTERVAL_SECONDS86400 (24h)
GATEKEEPER_LICENSE_HEARTBEAT_TIMEOUT_SECONDS30
GATEKEEPER_LICENSE_OFFLINE_GRACE_SECONDS604800 (7 days)

11.4.1 Paid license の取得(license claim

Section titled “11.4.1 Paid license の取得(license claim)”

Lemon Squeezy で Pro を購入すると、レシート記載の注文番号と購入時メールで token を引き換えられます:

Terminal window
querycop-cli license claim --order=<注文番号> --email=<購入時メール>
# → token を ~/.config/querycop/license.token に保存(--no-save で表示のみ)
EnvDefault説明
GATEKEEPER_LICENSE_CLAIM_URLhttps://api.querycop.com/v1/license/claimclaim エンドポイントの上書き

paid token は machine 非束縛(per-team)で、有効期間は発行から 365 日。 月次の支払い状態は heartbeat の revocation で enforcement されます(§11.4)。

MachineID binding: querycop-cli trial start で発行される token は 当該マシンの fingerprint (sha256 of hostname + sorted MACs + GOOS + GOARCH) に bind されています。別ホストにコピーしても起動時 validation で失敗します。

GET /license で license status (tier / valid / is_trial / days_until_expiry / features) を返す。Dashboard は header に tier badge + Trial countdown + Upgrade CTA を表示する。

license-disabled な Pro / Enterprise タブ (JIT, Metrics 等) は 🔒 lock card に置き換わり、“Upgrade to Pro” / “Contact sales” の CTA を表示する (locked タブはバックエンド API を呼ばないので console / audit に余計な 403 が出ない)。Heartbeat downgrade は 60 秒以内に UI に 反映され、リロード不要。/license fetch が失敗した場合は fail-closed で “License check failed (retrying…)” の badge を表示し、すべての gated タブを locked 表示にする (isFeatureEnabled が null safe で false を返すため)。

Pro / Community 共通で ai_requests_per_day の cap がある (Community 100 / Pro 5,000 / Enterprise unlimited)。cap を超えても proxy traffic は止めない: pkg/ai/tracked.go が外部 AI 呼び出しを止めて static rule-based scorer (pkg/ai/static.go) に degrade する設計。詳細は docs/entitlements.md §7.4 (License Over-Limit Policy) を参照。env 変数の追加は無し (cap は license claim の Limits.AIRequestsPerDay で配信)。