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
81 changes: 79 additions & 2 deletions documentation/query/sql/acl/grant.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,20 @@ GRANT permission [, permission ...] TO entityName
```questdb-sql title="Table or column scope"
GRANT permission [, permission ...]
ON { ALL TABLES
| tableName [(columnName [, columnName ...])]
[, tableName [(columnName [, columnName ...])] ...] }
| tableName [(columns)] [, tableName [(columns)] ...] }
TO entityName
[WITH GRANT OPTION]
[WITH VERIFICATION];
```

Where `columns` is either an explicit list of columns, or `*` for all of the
table's current columns with an optional `EXCLUDE` list:

```questdb-sql title="Column specification"
{ columnName [, columnName ...]
| * [EXCLUDE (columnName [, columnName ...])] }
```

## Description

- `GRANT [permissions] TO entity` - grant database level permissions on database
Expand All @@ -47,6 +54,8 @@ GRANT permission [, permission ...]
permissions on table level to an entity
- `GRANT [permissions] ON [table(columns)] TO entity` - grant column level
permissions on column level to an entity
- `GRANT [permissions] ON [table(*)] TO entity` - grant column level permissions
on all of the table's current columns, with an optional `EXCLUDE` list

### Grant database level permissions

Expand Down Expand Up @@ -116,6 +125,74 @@ GRANT SELECT ON orders(id, name), trades(id, quantity) TO john;
| SELECT | orders | id | f | G |
| SELECT | orders | name | f | G |

### Grant on all columns of a table

Use the `*` wildcard to grant a column level permission on every column the table
currently has, without naming each one:

```questdb-sql
CREATE TABLE trades (
symbol SYMBOL, price DOUBLE, quantity DOUBLE,
counterparty SYMBOL, ts TIMESTAMP
) TIMESTAMP(ts);
GRANT SELECT ON trades(*) TO john;
```

| permission | table_name | column_name | grant_option | origin |
| ---------- | ---------- | ------------ | ------------ | ------ |
| SELECT | trades | symbol | f | G |
| SELECT | trades | price | f | G |
| SELECT | trades | quantity | f | G |
| SELECT | trades | counterparty | f | G |
| SELECT | trades | ts | f | G |

The `*` is expanded to the table's columns at the time the statement runs, so the
result is a set of individual column level grants.

:::note

`GRANT SELECT ON trades(*)` is not the same as `GRANT SELECT ON trades`. The
wildcard grants only on the columns that exist at that moment and does not extend
to columns added later. A table level grant (without parentheses) covers all
current and future columns. Use the table level form when new columns should be
included automatically.

:::

#### Exclude columns from the wildcard

Add an `EXCLUDE` list to grant on all columns except the ones you name. This is
useful when you want to expose most of a table but keep a few sensitive columns
private:

```questdb-sql
GRANT SELECT ON trades(* EXCLUDE (counterparty)) TO john;
```

| permission | table_name | column_name | grant_option | origin |
| ---------- | ---------- | ----------- | ------------ | ------ |
| SELECT | trades | symbol | f | G |
| SELECT | trades | price | f | G |
| SELECT | trades | quantity | f | G |
| SELECT | trades | ts | f | G |

`EXCLUDE` can only be used together with `*`. The following rules apply:

- Every excluded column must exist, otherwise the statement fails. This catches
typos that would otherwise silently grant a column you meant to keep private.
- The `EXCLUDE` list cannot be empty and cannot cover every column of the table.
- The target table must exist. Unlike other grants, a wildcard grant cannot be
issued ahead of table creation.

:::note

Excluding the designated timestamp column does not necessarily hide it. If the
entity still holds `SELECT` or `UPDATE` on another column of the same table, the
timestamp keeps that permission as an
[implicit permission](#implicit-permissions) shown with origin `I`.

:::

### Grant option

If the `WITH GRANT OPTION` clause is present, then the target entity is allowed
Expand Down
41 changes: 39 additions & 2 deletions documentation/query/sql/acl/revoke.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,18 @@ REVOKE permission [, permission ...] FROM entityName;
```questdb-sql title="Table or column scope"
REVOKE permission [, permission ...]
ON { ALL TABLES
| tableName [(columnName [, columnName ...])]
[, tableName [(columnName [, columnName ...])] ...] }
| tableName [(columns)] [, tableName [(columns)] ...] }
FROM entityName;
```

Where `columns` is either an explicit list of columns, or `*` for all of the
table's current columns with an optional `EXCLUDE` list:

```questdb-sql title="Column specification"
{ columnName [, columnName ...]
| * [EXCLUDE (columnName [, columnName ...])] }
```

## Description

- `REVOKE [permissions] FROM entity` - revoke database level permissions from an
Expand All @@ -43,6 +50,9 @@ REVOKE permission [, permission ...]
permissions on table level from an entity
- `REVOKE [permissions] ON [table(columns)] FROM entity` - revoke column level
permissions on column level from an entity
- `REVOKE [permissions] ON [table(*)] FROM entity` - revoke column level
permissions on all of the table's current columns, with an optional `EXCLUDE`
list

### Revoke database level permissions

Expand Down Expand Up @@ -80,6 +90,33 @@ REVOKE SELECT ON orders, trades FROM john;
REVOKE SELECT ON orders(id, name) FROM john;
```

### Revoke from all columns of a table

Use the `*` wildcard to revoke a column level permission from every column the
table currently has:

```questdb-sql
REVOKE SELECT ON trades(*) FROM john;
```

As with [`GRANT`](/docs/query/sql/acl/grant/#grant-on-all-columns-of-a-table),
the `*` is expanded to the table's columns at the time the statement runs, and
the target table must exist.

Add an `EXCLUDE` list to revoke from all columns except the ones you name. For
example, to take away `SELECT` on every column of `trades` except `symbol` and
`ts`:

```questdb-sql
REVOKE SELECT ON trades(* EXCLUDE (symbol, ts)) FROM john;
```

`EXCLUDE` can only be used together with `*`. Every excluded column must exist,
and the list can neither be empty nor cover every column of the table. When the
permission was originally granted at table level, revoking it from a subset of
columns this way triggers
[permission level readjustment](#permission-level-readjustment).

### Implicit permissions

If the target table has implicit timestamp permissions, then revoking `SELECT`
Expand Down
12 changes: 12 additions & 0 deletions documentation/security/rbac.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ Restrict users to see only certain columns:
GRANT SELECT ON trades(ts, price) TO analyst;
```

To grant on every column except a few, use the `*` wildcard with an `EXCLUDE`
list:

```questdb-sql
-- User can see all columns except trader_id
GRANT SELECT ON trades(* EXCLUDE (trader_id)) TO analyst;
```

The wildcard covers the columns that exist when the statement runs, not columns
added later. See
[GRANT](/docs/query/sql/acl/grant/#grant-on-all-columns-of-a-table) for details.

### Row-level access with views

For row-level security, create a [view](/docs/concepts/views/) that filters rows,
Expand Down
Loading