diff --git a/docs/README.md b/docs/README.md index 85a93461a8ce0e024cb8afce4b4c8744a936c67c..fdabec555014b1bc8c45eda9ebaa7958a06e49a9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -53,6 +53,7 @@ Metabase's reference documentation. - [Databases overview](./databases/start.md) - [Adding and managing databases](./databases/connecting.md) +- [Database users, roles, and privileges](./databases/users-roles-privileges.md) - [Syncing and scanning databases](./databases/sync-scan.md) - [Encrypting your database connection](./databases/encrypting-details-at-rest.md) - [SSH tunneling](./databases/ssh-tunnel.md) diff --git a/docs/actions/introduction.md b/docs/actions/introduction.md index 9094d2be5dc6256e13fa596cde67a41318cc65a1..9396f5491ab810bf2449139c833a342f68b65b61 100644 --- a/docs/actions/introduction.md +++ b/docs/actions/introduction.md @@ -26,7 +26,7 @@ Actions must be added to a [model](../data-modeling/models.md), but actions only For actions to work, you'll first need to do the following two things: -1. **Enable model actions for the database connection**. To enable actions for a database connection, admins should click on the **gear** icon in the upper right and navigate to **Admin settings** > **Databases**, then click on the database you want to create actions for. On the right side of the connection settings form, toggle the **Model actions** option. For actions to work, the database user account (the account you're using to connect to the database) must have write permissions. And for now, actions are only supported on PostgreSQL, MySQL, and H2 databases. +1. **Enable model actions for the database connection**. To enable actions for a database connection, admins should click on the **gear** icon in the upper right and navigate to **Admin settings** > **Databases**, then click on the database you want to create actions for. On the right side of the connection settings form, toggle the **Model actions** option. For actions to work, the database user account (the account you're using to connect to the database) must have [write permissions](../databases/users-roles-privileges.md#privileges-to-enable-actions). And for now, actions are only supported on PostgreSQL, MySQL, and H2 databases. 2. **Create at least one model from that database.** Actions are associated with models, so you'll need to have created (or have access to) at least one model before you can start creating actions. ## Who can use actions diff --git a/docs/databases/connecting.md b/docs/databases/connecting.md index 1e298e7a0b1841d4a66cfa9e30cfec3c4dd9afb7..69f43505b558942ea2ca0e938977059114ff663c 100644 --- a/docs/databases/connecting.md +++ b/docs/databases/connecting.md @@ -45,6 +45,10 @@ For provider-specific connection details, like connecting to a PostgreSQL data w - [AWS's Relational Database Service (RDS)](./connections/aws-rds.md) +## Granting database privileges + +For Metabase to connect, query, or write to your database, you must give Metabase a database user account with the correct database privileges. See [Database roles, users, and privileges](./users-roles-privileges.md). + ## Syncing and scanning databases See [Syncing and scanning](./sync-scan.md). diff --git a/docs/databases/connections/mysql.md b/docs/databases/connections/mysql.md index 578e331b6f47a552f259b9b0c73c57a42934884c..b76a358e399a594a6deef1844fbf14e7b476a20b 100644 --- a/docs/databases/connections/mysql.md +++ b/docs/databases/connections/mysql.md @@ -26,7 +26,7 @@ The database port. E.g., 3306. ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/oracle.md b/docs/databases/connections/oracle.md index a580b6c3a0ba16838a29065a4fc58811f0ddad1f..c087302c05c44d1185e7e5de248443f6d3d5e69e 100644 --- a/docs/databases/connections/oracle.md +++ b/docs/databases/connections/oracle.md @@ -34,7 +34,7 @@ Optional TNS alias. ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/postgresql.md b/docs/databases/connections/postgresql.md index db7a94f23ec35ad79c9f00aaa2dea5ac79157f2a..7ade62d149dc1474b137a55980cf5160889fc33c 100644 --- a/docs/databases/connections/postgresql.md +++ b/docs/databases/connections/postgresql.md @@ -32,7 +32,7 @@ The name of the database you're connecting to. ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/presto.md b/docs/databases/connections/presto.md index ff1c7c553e3d981031668a1ad8508b09f0682a12..574c3c0b711141b1a9822d64ae4992777fc0e120 100644 --- a/docs/databases/connections/presto.md +++ b/docs/databases/connections/presto.md @@ -34,7 +34,7 @@ Only add tables to Metabase that come from a specific schema. ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/redshift.md b/docs/databases/connections/redshift.md index 5905271f11a470ab87f870290c32a79603691399..710952c76abb263df33e55693306aef53c950e13 100644 --- a/docs/databases/connections/redshift.md +++ b/docs/databases/connections/redshift.md @@ -53,7 +53,7 @@ Note that only the `*` wildcard is supported; you can't use other special charac ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/snowflake.md b/docs/databases/connections/snowflake.md index 7fc306b255b48ff9bddb74c6f3c44400163b9a6d..1fd4e78b644b0f6536749a932952d0e4ee760ea7 100644 --- a/docs/databases/connections/snowflake.md +++ b/docs/databases/connections/snowflake.md @@ -30,7 +30,7 @@ You'd enter `az12345.ca-central-1.aws` as the account name in Metabase. ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/sparksql.md b/docs/databases/connections/sparksql.md index 09a5782cc3469d908bfde4417e223a8e86381d85..3ae8b6530c6bf4fb9897b996be1b89a6413ac7b2 100644 --- a/docs/databases/connections/sparksql.md +++ b/docs/databases/connections/sparksql.md @@ -24,7 +24,7 @@ The database port. E.g., 10000 ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/connections/sql-server.md b/docs/databases/connections/sql-server.md index 17f0b78f25f18f92cdfd2c23dcc2d1e43fab9db6..19dd173da469be4d47772093c82801ac41d0d818 100644 --- a/docs/databases/connections/sql-server.md +++ b/docs/databases/connections/sql-server.md @@ -34,7 +34,7 @@ If you're running multiple databases on the same host, you can include the insta ### Username -The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of privileges. +The database username for the account that you want to use to connect to your database. You can set up multiple connections to the same database using different user accounts to connect to the same database, each with different sets of [privileges](../users-roles-privileges.md). ### Password diff --git a/docs/databases/users-roles-privileges.md b/docs/databases/users-roles-privileges.md new file mode 100644 index 0000000000000000000000000000000000000000..f8614644925d6e6683a9720f250ce2ec8925b60d --- /dev/null +++ b/docs/databases/users-roles-privileges.md @@ -0,0 +1,184 @@ +--- +title: Database users, roles, and privileges +--- + +# Database users, roles, and privileges + +We recommend creating a `metabase` database user with the following database roles: + +- [`analytics` for read access](#minimum-database-privileges) to any schemas or tables used for analysis. +- Optional [`metabase_actions` for write access](#privileges-to-enable-actions) to tables used for Metabase actions. +- Optional [`metabase_model_caching` for write access](#privileges-to-enable-model-caching) to the schema used for Metabase model caching. + +Bundling your privileges into roles based on use cases makes it easier to manage privileges in the future (especially in [multi-tenant situations](#multi-tenant-permissions)). For example, you could: + +- Use the same `analytics` role for other BI tools in your [data stack](https://www.metabase.com/learn/databases/data-landscape#data-analysis-layer) that need read-only access to the analytics tables in your database. +- Revoke the write access for `metabase_model_caching` without affecting the write access for `metabase_actions`. + +## Minimum database privileges + +In order to view and query your tables in Metabase, you'll have to give Metabase's database user: + +- `CONNECT` to your database. +- `SELECT` privileges to any schemas or tables that you want to use in Metabase. + +To organize these privileges (and make maintenance easier down the line): + +- Create a database role called `analytics`. +- Create a database user called `metabase`. +- Add `metabase` to the `analytics` role. +- Add privileges to the `analytics` role. + +For example, if you're using a Postgres database, you'd log in as an admin and run the SQL statements: + +```sql +-- Create a role named "analytics". +CREATE ROLE analytics WITH LOGIN; + +-- Add the CONNECT privilege to the role. +GRANT CONNECT ON DATABASE "your_database" TO analytics; + +-- Create a database user named "metabase". +CREATE USER metabase WITH PASSWORD "your_password"; + +-- Give the role to the metabase user. +GRANT analytics TO metabase; + +-- Add query privileges to the role (options 1-3): + +-- Option 1: Uncomment the line below to let users with the analytics role query anything in the DATABASE. +-- GRANT pg_read_all_data ON DATABASE "your_database" TO analytics; + +-- Option 2: Uncomment the line below to let users with the analytics role query anything in a specific SCHEMA. +-- GRANT USAGE ON SCHEMA "your_schema" TO analytics; +-- GRANT SELECT ON ALL TABLES IN SCHEMA "your_schema" TO analytics; + +-- Option 3: Uncomment the line below to let users with the analytics role query anything in a specific TABLE. +-- GRANT USAGE ON SCHEMA "your_schema" TO analytics; +-- GRANT SELECT ON "your_table" IN SCHEMA "your_schema" TO analytics; +``` + +Depending on how you use Metabase, you can also additonally grant: + +- `TEMPORARY` privileges to create temp tables. +- `EXECUTE` privileges to use stored procedures or user-defined functions. + +Remember that when you grant privileges to a role, all users with that role will get those privileges. + +## Grant all database privileges + +If you don't want to structure your database privileges yet: + +- Create a `metabase` database user. +- Give `metabase` all privileges to the database. + +```sql +-- Create a database user named "metabase". +CREATE USER metabase WITH PASSWORD "your_password"; + +-- Give the user read and write privileges to anything in the database. +GRANT ALL PRIVILEGES ON "database" TO metabase; +``` + +This is a good option if you're connecting to a local database for development or testing. + +## Privileges to enable actions + +[Actions](../actions/introduction.md) let Metabase write back to specific tables in your database. + +In addition to the [minimum database privileges](#minimum-database-privileges), you'll need to grant write access to any tables used with actions: + +- Create a new role called `metabase_actions`. +- Give the role `INSERT`, `UPDATE`, and `DELETE` privileges to any tables used with Metabase actions. +- Give the `metabase_actions` role to the `metabase` user. + +```sql +-- Create a role to bundle database privileges for Metabase actions. +CREATE ROLE metabase_actions WITH LOGIN; + +-- Grant write privileges to the TABLE used with Metabase actions. +GRANT INSERT, UPDATE, DELETE ON "your_table" IN SCHEMA "your_schema" TO metabase_actions; + +-- Grant role to the metabase user. +GRANT metabase_actions TO metabase; +``` + +## Privileges to enable model caching + +[Model caching](../data-modeling/models.md#model-caching) lets Metabase save query results to a specific schema in your database. Metabase's database user will need the `CREATE` privilege to set up the dedicated schema for model caching, as well as write access (`INSERT`, `UPDATE`, `DELETE`) to that schema. + +In addition to the [minimum database privileges](#minimum-database-privileges): + +- Create a new role called `metabase_model_caching`. +- Give the role `CREATE` access to the database. +- Give the role `INSERT`, `UPDATE`, and `DELETE` privileges to the schema used for model caching. +- Give the `metabase_model_caching` role to the `metabase` user. + +```sql +-- Create a role to bundle database privileges for Metabase model caching. +CREATE ROLE metabase_model_caching WITH LOGIN; + +-- If you don't want to give CREATE access to your database, +-- add the schema manually before enabling modeling caching. +GRANT CREATE ON "database" TO metabase_model_caching; + +-- Grant write privileges to the SCHEMA used for model caching. +GRANT USAGE ON "your_schema" TO metabase_model_caching; +GRANT INSERT, UPDATE, DELETE ON "your_model's_table" IN SCHEMA "your_schema" TO metabase_model_caching; + +-- Grant role to the metabase user. +GRANT metabase_model_caching TO metabase; +``` + +## Multi-tenant permissions + +If you're setting up multi-tenant permissions for customers who need SQL access, you can [create one database connection per customer](https://www.metabase.com/learn/permissions/multi-tenant-permissions#option-2-granting-customers-native-sql-access-to-their-schema). That means each customer will connect to the database using their own database user. + +Let's say you have customers named Tangerine and Lemon: + +- Create new database users `metabase_tangerine` and `metabase_lemon`. +- Create a `customer_facing_analytics` role with the `CONNECT` privilege. +- Create roles to bundle privileges specific to each customer's use case. For example: + - `tangerine_queries` to bundle read privileges for people to query and create stored procedures against the Orange schema. + - `lemon_queries` to bundle read privileges for people to query tables in the Lemon schema. + - `lemon_actions` to bundle the write privileges needed to create [actions](#privileges-to-enable-actions) on a Lemonade table in the Lemon schema. +- Add each user to their respective roles. + +```sql +-- Create one database user per customer. +CREATE USER metabase_tangerine WITH PASSWORD "orange"; +CREATE USER metabase_lemon WITH PASSWORD "yellow"; + +-- Create a role to bundle privileges for all customers. +CREATE ROLE customer_facing_analytics; +GRANT CONNECT ON DATABASE "citrus" TO customer_facing_analytics; +GRANT customer_facing_analytics TO metabase_tangerine, metabase_lemon; + +-- Create a role to bundle analytics read access for customer Tangerine. +CREATE ROLE tangerine_queries; +GRANT USAGE ON SCHEMA "tangerine" TO tangerine_queries; +GRANT SELECT, EXECUTE ON ALL TABLES IN SCHEMA "tangerine" TO tangerine_queries; +GRANT tangerine_queries TO metabase_tangerine; + +-- Create a role to bundle analytics read access for customer Lemon. +CREATE ROLE lemon_queries; +GRANT USAGE ON SCHEMA "lemon" TO lemon_queries; +GRANT SELECT ON ALL TABLES IN SCHEMA "lemon" TO lemon_queries; +GRANT lemon_queries TO metabase_lemon; + +-- Create a role to bundle privileges to Metabase actions for customer Lemon. +CREATE ROLE lemon_actions; +GRANT INSERT, UPDATE, DELETE ON TABLE "lemonade" IN SCHEMA "lemon" TO lemon_actions; +GRANT lemon_actions TO metabase_lemon; +``` + +We recommend bundling privileges into roles based on use cases per customer. That way, you can reuse common privileges across customers while still being able to grant or revoke granular privileges per customer. For example: + +- If customer Tangerine needs to query the Tangerine schema from another analytics tool, you can use the `tangerine_queries` role when setting up that tool. +- If customer Lemon decides that they don't want to use Metabase actions anymore (but they still want to ask questions), you can simply revoke or drop the `lemon_actions` role. + +## Further reading + +- [Permissions strategies](https://www.metabase.com/learn/permissions/strategy) +- [Permissions introduction](../permissions/introduction.md) +- [People overview](../people-and-groups/start.md) diff --git a/docs/troubleshooting-guide/data-permissions.md b/docs/troubleshooting-guide/data-permissions.md index ac70997667262bfe56ef0559b543a1c957fed728..5f33fc1f7414ed58d9d774a16b240fbb5a1b2b5f 100644 --- a/docs/troubleshooting-guide/data-permissions.md +++ b/docs/troubleshooting-guide/data-permissions.md @@ -79,7 +79,7 @@ If you get an error message that says something like "permission denied to \<you 2. Get the credentials that Metabase uses to connect to your database. If you're not sure what those credentials are, ask your database admin. 3. Using a different application (like your CLI or database IDE), connect to your database using the same credentials your Metabase uses to connect to that database, and run the query from step 1. 4. If you cannot access the table or schema in both step 1 and 3, ask your database admin to: - - [Grant database privileges](#granting-database-privileges) to the role that Metabase is using to connect, or + - [Grant database privileges](../databases/connecting.md#database-roles-users-and-privileges) to the role that Metabase is using to connect, or - Provide a set of database credentials with the correct permissions. 5. [Check if the access problem is fixed](#checking-someones-access-to-a-table-or-schema). @@ -97,24 +97,6 @@ This means that settings configured on the database side can prevent Metabase fr 2. Log in to Metabase as the person in question. 3. Run a question, dashboard, or native query to confirm that the person can see the data they're supposed to. -## Granting database privileges - -These sample commands use PostgreSQL syntax. If you use a different database, refer to your database's syntax guide. - -To allow Metabase to query a specific table: - -```sql -USE <database>; -GRANT ALL ON <table> IN SCHEMA <schema> TO <metabase_user>; -``` - -To allow Metabase to query all tables in a specific schema: - -```sql -USE <database>; -GRANT ALL ON <table> TO <metabase_user>; -``` - ## Do you have a different problem? - [I can't view or edit my question or dashboard][view-edit]. diff --git a/docs/troubleshooting-guide/db-connection.md b/docs/troubleshooting-guide/db-connection.md index d9b16035b72a8b4e114e7a4f601080b0dc837197..9bb3384ad8729352bcd0f2da5895764b01268d32 100644 --- a/docs/troubleshooting-guide/db-connection.md +++ b/docs/troubleshooting-guide/db-connection.md @@ -34,6 +34,8 @@ If you don't have access to the Metabase Admin panel, you'll need to ask the per - If you're running Metabase Cloud, check that you've [whitelisted our IP addresses](https://www.metabase.com/cloud/docs/ip-addresses-to-whitelist). +3. Make sure that Metabase is using a role with the necessary privileges to connect to your data warehouse. See [Granting database privileges](../databases/connecting.md#database-roles-users-and-privileges). + The steps above will help you detect whether the problem is occurring outside of Metabase. To _fix_ problems with your database server, you'll need to refer to the docs for your database or cloud service. Remember to [test your database connection](#testing-the-connection-status) after you make changes. If you don't have access to the data warehouse server, you’ll need to ask the person who manages your database or data warehouse. diff --git a/docs/troubleshooting-guide/sync-fingerprint-scan.md b/docs/troubleshooting-guide/sync-fingerprint-scan.md index ee3ec37aed3c0cee9392308e4d3415a3c2e2d10f..c0f2e56816def6afd6290b09989a68aeef983bf1 100644 --- a/docs/troubleshooting-guide/sync-fingerprint-scan.md +++ b/docs/troubleshooting-guide/sync-fingerprint-scan.md @@ -37,7 +37,7 @@ If you’ve just set up a new database in Metabase, the initial sync query needs **Explanation** -A sync query should show up like this in your database's query execution table (using the privileges for the database user in the database connection details): +A sync query should show up like this in your database's query execution table (using the [privileges](../databases/users-roles-privileges.md) for the database user in the database connection details): ```sql SELECT