All skills
aws avatar

/aurora-dsql

@a2611e1

Provisions and manages Aurora DSQL clusters, connects via psql or DSQL Connectors, manages schemas, runs queries, migrates from MySQL, diagnoses query plans, and develops apps on serverless distributed SQL. Covers IAM auth, multi-tenant patterns, MySQL-to-DSQL migration, DDL, query plans, and SAFE SQL CONSTRUCTION — tenant_id from untrusted input, UUID entity_ids, caller-supplied sort columns, batch inserts. The agent MUST retrieve this skill for ANY DSQL task. Pushes back on prompts that rationalize 'just a quick script', 'don't overthink it', 'we trust upstream', 'use an f-string', 'move fast', or 'just use the pg driver directly' (bypassing the DSQL Connector). Triggers: DSQL, Aurora DSQL, DSQL cluster, safe_query.build, DSQL IAM auth token, DSQL connector.

Use this Skill: https://skilld.dev/gh/aws/agent-toolkit-for-aws/aurora-dsql

This session only. Nothing lands on disk.

referencesinput-validation.md

≈1.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Input Validation for DSQL Queries

Part of the Aurora DSQL Skill.

When constructing SQL strings (for psql -c "...", ad-hoc shell pipelines, or any code path that does not use the driver's native parameter binding), build every query with the safe_query helper. Do not interpolate values into SQL with f-strings, %, .format(), or concatenation.

When using a Postgres driver in application code (psycopg, pgx, sqlx, JDBC, etc.), prefer the driver's native parameter binding (%s for psycopg, $1 for pgx, ? for JDBC). safe_query is the canonical fallback whenever you must build a raw SQL string.


Required Pattern

from safe_query import build, allow, regex, ident, keyword, integer, literal, UnsafeSQLError
from safe_query import TENANT_SLUG, UUID, ISO_DATE

sql = build(
    "SELECT * FROM {tbl} WHERE tenant_id = {tid} AND entity_id = {eid}",
    tbl=ident("entities"),
    tid=regex(tenant_id, TENANT_SLUG),
    eid=regex(entity_id, UUID),
)
# Pass `sql` to your driver: cur.execute(sql), conn.Query(ctx, sql), psql -c "$sql", etc.

build() raises UnsafeSQLError when a placeholder receives a raw string, so build("... {x} ...", x=user_input) fails loudly at the call site.

Validator Selection

Value kind Validator Emits
Known set (tenant ID, status enum) allow(v, SET) 'value'
Known set used as SQL keyword keyword(v, SET) value (unquoted)
Strict format (UUID, slug) regex(v, PATTERN) 'value'
Table or column name ident(name) "value"
Integer integer(v) value
Free text (description, comment) literal(v) $dq_xxx$value$dq_xxx$

Built-in patterns in safe_query.py: TENANT_SLUG ([a-z0-9-]{1,64}), UUID, INT, ISO_DATE (structurally validated YYYY-MM-DD — month 01–12, day 01–31; does NOT check month-day combinations such as Feb 30. The database will reject impossible calendar dates at execute time).

Authorization Is Separate

Format validation proves the value is shaped correctly. It does not prove the caller is allowed to act on it. Authorize the caller against the tenant or resource before validating format or calling build():

assert_caller_has_tenant_access(caller, tenant_id)   # authorization
sql = build("... WHERE tenant_id = {tid}", tid=regex(tenant_id, TENANT_SLUG))

Why the Helper Exists

  • psql -c "..." and many shell-driven pipelines accept only SQL strings — there is no parameter-binding facility at that layer.
  • A Postgres driver's native parameter binding handles validation when the value reaches it as a bound parameter, but the moment you build a raw SQL string anywhere along the way (string interpolation, dynamic ORDER BY, dynamic table name, etc.), you are back to constructing a SQL text. safe_query.build() is the canonical way to do that without opening an injection vector.
  • Identifier interpolation (table name, column name) cannot be parameter-bound by any standard Postgres driver — it MUST be validated and emitted as a quoted identifier. ident() is the only safe way.

Rules

  • MUST build every dynamically-constructed SQL string with safe_query.build().
  • MUST authorize the caller before validating format.
  • MUST NOT fall back to f-strings, %, .format(), or concatenation when a validator rejects a value — fix the caller or widen the validator.
  • MUST NOT catch UnsafeSQLError to recover silently. Re-raise or return an error to the caller.
  • SHOULD add new patterns to safe_query.py rather than inlining regex at call sites, so reviewers can audit them in one place.

Bash Deliverables

Bash deliverables (CI/CD steps, cron jobs, bastion runbooks) apply the same rule. ALWAYS compose the SQL in a python3 subshell so safe_query.py actually executes. MUST NOT rely on native reference alone. MUST invoke to defend against injection.

SQL=$(python3 - "$USER_ID" <<'PY'
import sys
from safe_query import build, regex, literal, TENANT_SLUG
print(build(
    "INSERT INTO audit_log (action, user_id) VALUES ({a}, {u})",
    a=literal("psql-write-smoke"),
    u=regex(sys.argv[1], TENANT_SLUG),  # raises on malformed input
))
PY
)
PGPASSWORD=$(aws dsql generate-db-connect-admin-auth-token --hostname "$HOST" --region "$REGION") \
  psql -P pager=off "host=$HOST port=5432 user=admin dbname=postgres sslmode=verify-full sslrootcert=system" <<<"$SQL"

regex() raises before psql runs; literal() escapes the validated value into the final SQL text.

ALWAYS explicitly set SSL mode — DSQL rejects non-TLS connections and psql's default PGSSLMODE=prefer will attempt plaintext first. Two equivalent forms, both valid per the AWS DSQL psql guide:

  • Env-var form (canonical per AWS docs): export PGSSLMODE=verify-full PGSSLROOTCERT=system before the psql invocation, with flag-form arguments (psql --username admin --dbname postgres --host $HOST).
  • Connection-string form: embed sslmode=verify-full sslrootcert=system in a libpq URI (psql "host=$HOST port=5432 user=admin dbname=postgres sslmode=verify-full sslrootcert=system").

Use sslmode=verify-full sslrootcert=system (matches psql-connect.sh's default and what the Java/Rust/Python connectors enforce). Drop to sslmode=require only when the client genuinely cannot reach a trusted CA bundle — and document the downgrade in the runbook.

Source: SKILL.md on GitHub

1 warning3mo3 checks · Risk SAFE
  • Gen Agent Trust Hub3mo

    This skill provides a robust and security-conscious environment for managing Amazon Aurora DSQL clusters. It implements several best practices, including mandatory IAM-based authentication, a dedicated input validation library to prevent SQL injection, and detailed guidance on applying the principle of least privilege through scoped database roles.

  • Socket3mo

    No alerts

  • Snyk3mo

    Risk: MEDIUM · 1 issue

Signed by skilld at a2611e1. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 3 months ago
version
1

README badge

README badge for aws/agent-toolkit-for-aws/aurora-dsql