Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion connections/credential-profiles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,27 @@ A linked connection keeps no password of its own. Linking deletes the one it had
| Saved in the Keychain | Read from the Keychain, under the profile's own id |
| Ask every time | Asked for once per profile each time TablePro runs, however many connections use it |
| `~/.pgpass` | Looked up by the host, port, database and username of whichever connection is opening |
| Read from elsewhere | Resolved from a file, an environment variable, a command's output, 1Password, Vault or AWS Secrets Manager |
| Read from elsewhere | Resolved from a file, an environment variable, a command's output, 1Password, Vault, AWS Secrets Manager, or a Vault database role |

Pick **Saved in the Keychain** unless something else already owns the password. **Read from elsewhere** never leaves this Mac and never syncs.

## Vault database roles

A role on Vault's database secrets engine hands out a new database user for every lease. Set **Source** to **Read from elsewhere** and **Read From** to **HashiCorp Vault database role**, then fill in:

| Field | Holds |
|---|---|
| Mount | Where the database secrets engine is mounted, such as `database` |
| Role | The role to read, as in `<mount>/creds/<role>` |
| Vault Address | The server, such as `https://vault.example.com:8200`. Leave it empty to use `VAULT_ADDR` |
| Sign In With | **Token** reads `VAULT_TOKEN`, then `~/.vault-token` from `vault login`. **AppRole** takes a role ID and a file holding the secret ID. **OIDC** opens your browser once per launch |

The username field greys out, because Vault generates the username too. **Test Source** reads a lease, shows the username and password it got, and revokes it.

Each sign-in reads a new lease, so the main connection, a second database, and a backup each sign in as a user of their own. While connected, the lease renews before it expires. When Vault stops renewing it, at the role's maximum TTL or when renewal fails, the connection signs in again with a new lease before the old user is revoked. Disconnecting revokes the lease. The generated password stays in memory: it never reaches the Keychain, `connections.json`, or iCloud.

An OIDC role must allow the redirect URI `http://localhost:8250/oidc/callback`, the one `vault login -method=oidc` uses. A connection that needs an OIDC sign-in offers **Sign In** instead of failing.

### 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`.
Expand Down
4 changes: 4 additions & 0 deletions features/connection-sharing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ A connection in `~/Library/Application Support/TablePro/connections.json` can sa
{ "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" } }
{ "passwordSource": { "kind": "vaultDatabaseRole", "mount": "database", "role": "readonly" } }
{ "passwordSource": { "kind": "vaultDatabaseRole", "address": "https://vault.example.com:8200", "mount": "database", "role": "readonly",
"auth": { "method": "approle", "roleId": "8f1c…", "secretIdPath": "~/.vault/secret-id" } } }
```

| `kind` | Reads from | Set up first |
Expand All @@ -174,6 +177,7 @@ A connection in `~/Library/Application Support/TablePro/connections.json` can sa
| `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 | |
| `vaultDatabaseRole` | A new lease from `<mount>/creds/<role>`, which supplies the username as well. `auth.method` is `token` (the default), `approle` with `roleId` and `secretIdPath`, or `oidc` with an optional `role`; each takes an optional `mount` | `address`, or `VAULT_ADDR` in TablePro's environment. See [Vault database roles](/connections/credential-profiles#vault-database-roles) |

Every command gets 30 seconds. The three CLI kinds quote each argument, so a reference cannot break out into the shell, and they need the tool on `PATH`, in `/usr/local/bin`, or in `/opt/homebrew/bin`.

Expand Down
4 changes: 2 additions & 2 deletions security/privacy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ Every path here is under `~/Library/Application Support/TablePro/` unless it say

Secrets live in the macOS keychain, under the `com.TablePro` service and in the data protection keychain: connection passwords, SSH passwords, key passphrases, SSL client key passphrases, TOTP secrets, plugin secure fields, AI provider keys, and the license key. Google sign-in refresh tokens for BigQuery and Spanner are kept in the same keychain under `com.TablePro.GoogleOAuth`, one per OAuth client ID. MCP tokens are the exception, stored as a salted SHA-256 hash; the plaintext is shown once at creation and never written down.

A connection can name a [password source](/features/connection-sharing#password-sources) instead of using the keychain: a file, an environment variable, a shell command, 1Password, HashiCorp Vault, or AWS Secrets Manager. Those resolve at connect time, on your machine, and are never synced, since a path or a command belongs to one Mac.
A connection can name a [password source](/features/connection-sharing#password-sources) instead of using the keychain: a file, an environment variable, a shell command, 1Password, HashiCorp Vault, AWS Secrets Manager, or a Vault database role. Those resolve at connect time, on your machine, and are never synced, since a path or a command belongs to one Mac. A Vault database role sends your Vault token to the address it names, and the database password it gets back stays in memory.

<Warning>
The `command`, `onePassword`, `vault`, and `awsSecretsManager` kinds run a program on your Mac. The app keeps a signature over `connections.json` for that reason: if the file changed outside the app, password sources do not run and the connection reports why. Open the connection and save it from TablePro to accept the change.
The `command`, `onePassword`, `vault`, and `awsSecretsManager` kinds run a program on your Mac, and `vaultDatabaseRole` sends a Vault token where it says. The app keeps a signature over `connections.json` for that reason: if the file changed outside the app, password sources do not run and the connection reports why. Open the connection and save it from TablePro to accept the change.
</Warning>
Loading