prod-db-mysql-bastion
暂无简介
- License 许可
- MIT
- 最近更新
- 2026-09-20
- Stars
- ★ 0
- Forks
- 0
02 资源文件 4
- 脚本scripts/config.example.env362 B
- 脚本scripts/query.sh3.9 KB
- 脚本scripts/runner.py7.1 KB
- 脚本scripts/test_guard.py2.0 KB
03 SKILL.md 正文
Production MySQL behind a VPC, read-only queries
Runs one read-only statement against prod and returns the rows.
scripts/query.sh 'SELECT COUNT(*) AS dealers FROM company'
scripts/query.sh --format json 'SELECT id, name FROM company LIMIT 20'
scripts/query.sh --timeout 60 'SELECT ... a slower analytical query ...'
Flags: --format table|json (default table) · --limit N (default 200) ·
--timeout SECONDS (default 30) · --start (boot the instance if it is stopped).
Configuration
Env or scripts/config.env (sourced if present, gitignored). Copy config.example.env.
| Variable | What |
|---|---|
BASTION_INSTANCE_ID |
EC2 inside the VPC whose instance role may read the DB secret |
BASTION_SSH_ALIAS |
~/.ssh/config host using ProxyCommand aws ssm start-session ... AWS-StartSSHSession |
BASTION_AWS_PROFILE / BASTION_AWS_REGION |
SSO profile and region |
BASTION_REMOTE_PYTHON |
a python on the instance with pymysql and boto3 |
DB_SECRET_ID, DB_HOST, DB_PORT, DB_NAME |
Secrets Manager id and the proxy endpoint, sent to the runner |
Hardcode DB_HOST in config.env for one environment on purpose: a skill that can be
pointed at any host by an env var an operator last set is not prod-only by construction.
Schema: look, do not guess
SHOW TABLES and DESCRIBE <table> cost a few milliseconds. Start there instead of
assuming a name, and keep a dated cheat sheet in the project's domain-knowledge.md.
Ask the user before the first query of a session
This hits a live production database. Confirm with the user before the first query,
and again for anything that is not a cheap indexed lookup: a wide scan on prod
competes with the real pipeline for proxy connections. Cheap COUNT(*) follow-ups in
an already-authorised session do not each need a fresh confirmation.
Why it cannot just connect
The RDS Proxy has no public endpoint, so the laptop cannot reach it. query.sh pipes
runner.py to the instance over SSH-via-SSM and it executes there. DB credentials are
read from Secrets Manager by the instance role, so no password ever reaches the
caller's machine or the transcript.
How read-only is enforced
The DB user may well have full privileges (many shops have no read-only role), so read-only is enforced by the skill, in three layers:
- Statement allow-list:
SELECT/WITH/SHOW/DESCRIBE/EXPLAIN, one statement per call. String literals and comments are blanked before the check, so a;inside'...'is not misread as a stacked statement. - No-file-write check: rejects
INTO OUTFILE/INTO DUMPFILE(aSELECTthat writes). START TRANSACTION READ ONLY: the server rejects any write with error 1792. This is the layer that holds; 1 and 2 exist to fail fast with a clear message.
Plus max_execution_time (default 30s) and a row cap, which is the guard that matters
day to day: on a live cluster the real hazard is an unbounded join pinning a proxy
connection, not a rogue DELETE.
scripts/test_guard.py covers the guard offline (no DB, no AWS): python3 scripts/test_guard.py.
Failure modes
| Symptom | Meaning |
|---|---|
SSO token expired. Run: aws sso login --profile X |
The user must log in; you cannot do it for them |
instance is 'stopped' |
Ask the user, then re-run with --start (a small instance costs a few dollars a month running, nothing stopped) |
SSM agent is ConnectionLost |
Box is running but saturated; the agent got starved off the network. Common right after --start following a long stop when missed cron timers fire at boot. Wait for CPU to drop, or reboot |
REFUSED: ... (exit 3) |
The statement is not read-only. Do not try to reword around the guard |
TIMEOUT: ... (exit 4) |
Query exceeded --timeout and was killed server-side. Narrow it before raising the limit |
No such file or directory: <remote python> |
Point BASTION_REMOTE_PYTHON at a venv on the instance with pymysql and boto3 |
pymysql TLS quirk: ssl={"ca": None}, not {}, is the shape that triggers the TLS
path; an RDS Proxy rejects a plaintext connection (error 3159).
04 同仓库更多 Skills
yes-no
Answer the user's question with a yes or no, optionally followed by a short explanation when the model sees fit. Use when the user types "/yes-no", asks a yes/no question and wants a decisive answer, or says "just yes or no".
sonar-workflow
Fix SonarQube code quality issues for a pull request. Auto-fixes trivial issues (formatting, unused imports) and requests approval for complex issues (security, bugs). Integrates with commit-workflow and pr-workflow skills.
short-answer
Answer the user's question as concisely as possible, a direct, to-the-point response with no preamble, filler, or unnecessary elaboration. Use when the user types "/short-answer", asks for a brief/short/concise/TL;DR answer, or says "just the answer".
redash
Query a Redash instance over its REST API , list data sources and saved queries, read a saved query's SQL, run it, or run ad-hoc read-only SQL and get the rows back. Use when the user asks about Redash, a Redash query/dashboard/link, "run that query", "what does query 1234 return", or wants numbers out of an analytics data source rather than the application DB.
prod-db-postgres
暂无简介
pr-workflow
Use this skill when asked to create or update a pull request (PR). It ensures all PRs follow the repository's established templates and standards. Handles both new PR creation and updating existing PRs with new commits, title changes, or description updates.