diff --git a/connections/aws-iam.mdx b/connections/aws-iam.mdx index feb0651a..51c65715 100644 --- a/connections/aws-iam.mdx +++ b/connections/aws-iam.mdx @@ -105,6 +105,10 @@ mydb.abc123.us-east-1.rds.amazonaws.com:5432 The port is optional, falling back to 5432 for PostgreSQL and 3306 for MySQL and MariaDB. The field also covers a CNAME or any alias AWS did not issue, and is honored only when **Host** is loopback or already the same hostname. +## Redshift + +Redshift hands out its own user and temporary password rather than a signed token. The same three options appear on a Redshift connection, and [Redshift](/databases/redshift#aws-iam-sign-in) covers what each endpoint calls. + ## On iPhone and iPad Synced connections keep their AWS IAM option. **AWS IAM (Profile)** needs an access key saved on the device, and **AWS IAM (SSO)** signs in to IAM Identity Center from the device itself. [IAM sign-in](/ios#iam-sign-in) covers the setup. diff --git a/connections/connection-form.mdx b/connections/connection-form.mdx index f36c71f0..aaa71426 100644 --- a/connections/connection-form.mdx +++ b/connections/connection-form.mdx @@ -70,7 +70,9 @@ Encryption sits below the transport. [SSL/TLS](/connections/ssl) covers the mode | **Connect timeout** | Maximum seconds for the network transport and remote database to finish connecting. Empty uses 30 seconds; valid values are 1 to 600 | | **Query timeout** | Override of **Settings > General** for this connection. Empty inherits the global value; `0` means no limit. Only drivers that support query timeouts enforce it | | **Startup Commands** | SQL to run after every connect. See [Startup commands](#startup-commands) | -| **Pre-Connect Script** | Shell script run before connecting. A non-zero exit aborts the connect | +| **Pre-Connect Script** | Shell script run before connecting. A non-zero exit aborts the connect. See [Connection scripts](#connection-scripts) | +| **Timeout** | Seconds each connection script may run. Empty uses 10; valid values are 1 to 300 | +| **Post-Disconnect Script** | Shell script run once the session ends, after a pre-connect script ran. See [Connection scripts](#connection-scripts) | | **Safe Mode** | Confirms, authenticates or refuses queries before they run. See [Safe Mode](/features/safe-mode) | | **AI Policy** | Per-connection override for the in-app AI agents. **Never** also refuses external clients. Shown while **Enable AI Features** is on | | **External Clients** | **Blocked**, **Read Only** (the default), or **Read & Write** for MCP clients such as Raycast, Cursor, and Claude Desktop, and for [AppleScript](/developers/applescript). A token's own scope cannot raise it. See the [integration security model](/developers#security-model) | @@ -88,10 +90,6 @@ session picks it up. PostgreSQL connection Options pane in dark appearance with Connect timeout and Query timeout fields using their inherited defaults -A pre-connect script never runs unprompted. A **Pre-Connect Script** alert shows the script itself and waits for **Run Script**, every time, whatever opens the connection: its window, a link, Compare, **Copy To**, the AI assistant, an MCP client or a script. With no answer in 60 seconds the alert closes as **Cancel**. - -A connect you did not start never runs the script. A restored window at launch, a table loading on its own and a reconnect after a tunnel drops all stop at a **Connect** button instead. - ## Appearance **Icon** replaces the database logo in the connection list, **Switch Connection**, the connections strip and the toolbar. Click it, type to search the symbols, then click one or press `Return`. **Default** brings the logo back. The database type stays in the row's tooltip. @@ -115,6 +113,39 @@ SET search_path TO myschema, public; A statement that fails is logged and skipped, and the connection still opens. +## Connection scripts + +Put whatever has to happen before the database answers in **Pre-Connect Script**: a VPN profile coming up, `aws sso login`, a credential refresh. The script runs in `bash`, and a non-zero exit stops the connect with the script's standard error in the message. Homebrew's `/opt/homebrew/bin` and `/usr/local/bin` are on `PATH` even when TablePro was opened from the Dock. + +Both scripts get the connection in their environment, so one script can serve every connection that needs it: + +| Variable | Value | +|---|---| +| `TABLEPRO_CONNECTION_NAME` | The connection's name | +| `TABLEPRO_HOST` | **Host**, as typed, even when an SSH tunnel or proxy carries the connection | +| `TABLEPRO_PORT` | **Port**, as typed | +| `TABLEPRO_USER` | **Username**, or the linked credential profile's | +| `TABLEPRO_DATABASE` | **Database** | + +The password is never passed. + +```bash +scutil --nc start "Office VPN" +until nc -z "$TABLEPRO_HOST" "$TABLEPRO_PORT"; do sleep 1; done +``` + +A script still running at **Timeout** is stopped and the connect fails. Raise it for a VPN that takes 15 seconds to come up or a sign-in that waits on the browser. Canceling the connect stops the script too. + +**Post-Disconnect Script** undoes what the pre-connect script started. It runs once per session, after the session ends by **Disconnect**, by closing its last window, by quitting TablePro, or by a connect that fails after the pre-connect script succeeded. A connection with no pre-connect script never runs it. It gets the same variables and the same timeout, and a failure goes to the log rather than an alert. + +```bash +scutil --nc stop "Office VPN" +``` + +Neither script runs unprompted. A **Pre-Connect Script** alert shows both scripts and waits for **Run Script**, every time, whatever opens the connection: its window, a link, Compare, **Copy To**, the AI assistant, an MCP client or a script. With no answer in 60 seconds the alert closes as **Cancel**. + +A connect you did not start never runs the script. A restored window at launch, a table loading on its own and a reconnect after a tunnel drops all stop at a **Connect** button instead. Links, exports and the Team Library carry neither script. + ## Connection health Every active connection is checked on the interval set by **Check connections** in Settings > diff --git a/connections/credential-profiles.mdx b/connections/credential-profiles.mdx index a5e08c4f..3da9a72e 100644 --- a/connections/credential-profiles.mdx +++ b/connections/credential-profiles.mdx @@ -49,6 +49,18 @@ A linked connection keeps no password of its own. Linking deletes the one it had Pick **Saved in the Keychain** unless something else already owns the password. **Read from elsewhere** never leaves this Mac and never syncs. +### A command that works for every connection + +**The output of a command** runs in `bash` for whichever connection is opening. Write `{host}`, `{port}`, `{user}` and `{database}` where the command needs them, and each becomes that connection's value as one quoted word, with or without quotes around the placeholder. The same values arrive as `TABLEPRO_HOST`, `TABLEPRO_PORT`, `TABLEPRO_USER` and `TABLEPRO_DATABASE`, plus `TABLEPRO_CONNECTION_NAME`. + +```bash +aws rds generate-db-auth-token --hostname {host} --port {port} --username {user} +``` + +`{host}` and `{port}` are the ones typed in the form, never the local port of a tunnel. `${host}` is left for `bash`. + +**Reuse Result For** keeps the output for 5 minutes, 15 minutes, an hour or 8 hours, so a reconnect inside that window skips the command. Set it below the lifetime of whatever the command prints. The output stays in memory, and a connect that fails throws it away so the next one runs the command again. + ## Additional secrets Some engines sign in with more than a password: an AWS secret access key, a Snowflake private key, a service account JSON. **Additional Secrets** in the profile editor lists them per database type. A connection reads only the secrets its own type declares, so one profile can carry several engines' keys without them colliding. diff --git a/databases/redshift.mdx b/databases/redshift.mdx index b5761593..2fbc05d2 100644 --- a/databases/redshift.mdx +++ b/databases/redshift.mdx @@ -15,9 +15,21 @@ Redshift speaks the PostgreSQL wire protocol and uses the same bundled libpq dri Fill in the form and click **Save & Connect**. New connections default to SSL mode **Preferred**, and there is no version gate: any cluster AWS still runs will connect. - -AWS IAM authentication is not available for Redshift connections, unlike MySQL and PostgreSQL. Use a database username and password. For a cluster that is not publicly reachable, put it behind an [SSH tunnel](/connections/ssh-tunneling) on a bastion in the VPC. - +For a cluster that is not publicly reachable, put it behind an [SSH tunnel](/connections/ssh-tunneling) on a bastion in the VPC. + +## AWS IAM sign-in + +Set **Authentication** to **AWS IAM (Profile)**, **AWS IAM (SSO)** or **AWS IAM (Access Key)**, and every connect asks AWS for a user and a temporary password instead of reading a saved one. Profiles resolve as described in [AWS IAM Authentication](/connections/aws-iam#profiles), IAM Identity Center sign-in included. + +| Endpoint | AWS call | Signs in as | +|---|---|---| +| Provisioned cluster, **Username** empty | `redshift:GetClusterCredentialsWithIAM` | The user mapped to your IAM identity, such as `IAMR:analyst` | +| Provisioned cluster, **Username** set | `redshift:GetClusterCredentials` for that user | `IAM:` and the user name | +| Serverless workgroup | `redshift-serverless:GetCredentials` | The user mapped to your IAM identity | + +The cluster or workgroup and its region come from **Host**, so keep it the endpoint AWS issued. A tunnel TablePro opens needs nothing more. A port forward you run yourself leaves `127.0.0.1` in **Host**: set **Redshift Endpoint** to the real one, such as `my-cluster.abc123xyz.us-east-1.redshift.amazonaws.com`. It is honored only when **Host** is a loopback address or that same endpoint. **AWS Region** overrides the region. + +The policy needs the call above on the cluster or workgroup, and access to the `dbname` when it limits databases. The password lasts 15 minutes and is fetched again for each connect, and SSL mode **Disabled** or **Preferred** is raised to **Required**. IAM sign-in to Redshift works on the Mac only. ## Connection URL diff --git a/features/connection-sharing.mdx b/features/connection-sharing.mdx index 4d08e951..0bf57cdb 100644 --- a/features/connection-sharing.mdx +++ b/features/connection-sharing.mdx @@ -83,7 +83,7 @@ Group and folder paths match by name from the top down: an existing group or fol Import preview -Anything that decides where a credential comes from is stripped on the way in, from a file and from a link alike: AWS options including IAM authentication, the region, the profile and the RDS endpoint; **Use Password File**; **Prompt for password**; the SSL client key passphrase; the pre-tunnel host and port; and the **Pre-Connect Script**. Startup SQL and tunnel commands run on every connect, so a file brings them only if you agree: importing lists each one and asks, and **Import Without Commands** is the default. A link's sheet shows its startup SQL in full before you add it. +Anything that decides where a credential comes from is stripped on the way in, from a file and from a link alike: AWS options including IAM authentication, the region, the profile and the RDS endpoint; **Use Password File**; **Prompt for password**; the SSL client key passphrase; the pre-tunnel host and port; and the **Pre-Connect Script** and **Post-Disconnect Script**. Startup SQL and tunnel commands run on every connect, so a file brings them only if you agree: importing lists each one and asks, and **Import Without Commands** is the default. A link's sheet shows its startup SQL in full before you add it. ## Share via link @@ -160,6 +160,7 @@ A connection in `~/Library/Application Support/TablePro/connections.json` can sa { "passwordSource": { "kind": "file", "path": "~/.config/tablepro/secrets/feature-x.pw" } } { "passwordSource": { "kind": "env", "variable": "STAGING_DB_PASSWORD" } } { "passwordSource": { "kind": "command", "shell": "op read op://vault/feature-x/password" } } +{ "passwordSource": { "kind": "command", "shell": "aws rds generate-db-auth-token --hostname {host} --port {port} --username {user}", "reuseSeconds": 600 } } { "passwordSource": { "kind": "onePassword", "reference": "op://vault/feature-x/password" } } { "passwordSource": { "kind": "vault", "path": "secret/data/staging/db", "field": "password" } } { "passwordSource": { "kind": "awsSecretsManager", "secretId": "prod/db", "jsonKey": "password" } } @@ -169,7 +170,7 @@ A connection in `~/Library/Application Support/TablePro/connections.json` can sa |---|---|---| | `file` | The file at `path`, minus a trailing newline | `chmod 600` the file | | `env` | The named environment variable | Same Dock caveat as environment variables | -| `command` | stdout of the command, run through `/bin/bash`. A non-zero exit fails the connect | | +| `command` | stdout of the command, run through `/bin/bash`, with `{host}`, `{port}`, `{user}` and `{database}` filled in and quoted. A non-zero exit fails the connect. `reuseSeconds`, 1 to 86400, keeps the output that long | | | `onePassword` | `op read` on the reference | `op signin` | | `vault` | `vault kv get` for one field at a path | `VAULT_ADDR` and `VAULT_TOKEN` in TablePro's environment | | `awsSecretsManager` | `aws secretsmanager get-secret-value`. `jsonKey` pulls one field out of a JSON secret; omit it for the whole value | |