Lesson 3 of 7 · 50 min · Lab included

Privileges and the reader and contributor pattern

In this lesson you will

  • Name the privileges you use daily and their prerequisites
  • Explain inheritance and why the schema is the right level
  • Apply the reader and contributor group per schema pattern
  • Handle sensitive tables with separate schemas or table-level groups
Skip to the knowledge check

Grant to the schema, through two groups

You now have a namespace and identities. This lesson connects them. The pattern we use on every platform is short: for every schema, one reader group and one contributor group, and a group as owner. People get access by joining a group, and nobody gets a grant of their own.

We cover the privileges you need, how inheritance works, and why the schema is the right level. We do not cover metastore-level privileges in depth.

The privileges that matter

The Unity Catalog documentation defines each privilege. These are the ones you use daily.

PrivilegeAllowsAlso needs
USE CATALOGInteract with objects in a catalog. It gives no data access by itselfGranted by the catalog owner or a holder of MANAGE
USE SCHEMAThe schema-level equivalentUSE CATALOG on the parent
SELECTQuery a table, view or materialised viewUSE CATALOG and USE SCHEMA
MODIFYInsert, update and delete data in a tableSELECT on the table, plus the usage privileges
CREATE TABLECreate tables or views in a schemaThe documentation recommends granting it at schema level, with the usage privileges
READ VOLUMERead files in a volumeUSE CATALOG and USE SCHEMA
WRITE VOLUMEAdd, remove or change files in a volumeThe same
EXECUTECall a function or load a registered model for inferenceGrant it on individual functions and models
MANAGEManage privileges, transfer ownership, rename and drop without being the ownerNot included in ALL PRIVILEGES

Two points trip up most teams. First, usage privileges are required in addition to the data privilege. A group with SELECT on a table but no USE SCHEMA sees nothing. Second, MODIFY requires SELECT, so a contributor must also be a reader.

Inheritance: why the schema is the level

Privileges granted on a catalog or schema apply to its current and future child objects. The documentation gives the example that granting SELECT on a schema covers every existing and new table and view in it. The same applies to MODIFY, READ VOLUME, WRITE VOLUME and EXECUTE. MANAGE on a container also gives MANAGE on its children. The documentation also notes that inheritance requires privilege model version 1.0, so older metastores may need an upgrade first.

That behaviour makes the schema the natural level for grants:

  • A grant on a table needs repeating for every new table, and people forget.
  • A grant on a catalog is wide: it reaches every schema, including the ones you add next year.
  • A grant on a schema matches a layer or a subject area. A new table in gold is covered the moment it exists.

Grant on a table or volume only when one object has a different audience from the rest of its schema, such as a table with salary data. Our standard adds a table-level group for those cases.

The reader and contributor pattern

For every schema, create two groups.

GroupPrivileges on the schemaWho belongs to it
...-readerUSE CATALOG on the catalog, USE SCHEMA, SELECT, READ VOLUMEAnalysts, dashboards, downstream pipelines
...-contributorEverything the reader has, plus MODIFY, CREATE TABLE, WRITE VOLUMEThe pipeline service principal that writes this layer
...-ownerOwnership of the schemaA small platform group, never a person

Pipelines that write silver are members of the silver contributor group and the bronze reader group. Analysts are members of the gold reader group. Nobody except the ingestion principal is a member of any bronze contributor group. The layers of lesson 1 and the groups line up one to one, so the access model explains itself.

Here is the SQL for one schema. Group names follow the convention from lesson 2.

Illustration

sql
-- Reader: may see and query everything in prd_finance.gold, present and future.
GRANT USE CATALOG ON CATALOG prd_finance              TO `grp-uc-prd-finance-gold-reader`;
GRANT USE SCHEMA  ON SCHEMA  prd_finance.gold         TO `grp-uc-prd-finance-gold-reader`;
GRANT SELECT      ON SCHEMA  prd_finance.gold         TO `grp-uc-prd-finance-gold-reader`;
GRANT READ VOLUME ON SCHEMA  prd_finance.gold         TO `grp-uc-prd-finance-gold-reader`;
 
-- Contributor: reads like the reader, and may also create and change tables and files.
GRANT USE CATALOG  ON CATALOG prd_finance             TO `grp-uc-prd-finance-gold-contributor`;
GRANT USE SCHEMA   ON SCHEMA  prd_finance.gold        TO `grp-uc-prd-finance-gold-contributor`;
GRANT SELECT       ON SCHEMA  prd_finance.gold        TO `grp-uc-prd-finance-gold-contributor`;
GRANT MODIFY       ON SCHEMA  prd_finance.gold        TO `grp-uc-prd-finance-gold-contributor`;
GRANT CREATE TABLE ON SCHEMA  prd_finance.gold        TO `grp-uc-prd-finance-gold-contributor`;
GRANT WRITE VOLUME ON SCHEMA  prd_finance.gold        TO `grp-uc-prd-finance-gold-contributor`;
 
-- Ownership belongs to a group.
ALTER SCHEMA prd_finance.gold OWNER TO `grp-uc-prd-finance-gold-owner`;

Run grants like this through your pipeline, from code. In lesson 7 the same pattern becomes a Terraform module, so nobody types a GRANT by hand in production.

Inspect and revoke

sql
SHOW GRANTS ON SCHEMA prd_finance.gold;                    -- everything granted on this schema
SHOW GRANTS `grp-uc-prd-finance-gold-reader` ON SCHEMA prd_finance.gold;
 
REVOKE CREATE TABLE ON SCHEMA prd_finance.gold FROM `grp-uc-prd-finance-gold-contributor`;

The documentation notes that REVOKE succeeds even if the privilege was never granted, so it is safe to run in cleanup scripts, and equally safe to mistype. Read the output of SHOW GRANTS afterwards.

Sensitive tables need their own audience

Suppose gold.payroll must be visible to HR only. Keep the schema reader grant for general tables, and either place payroll in its own schema, such as gold_hr, or give it a table-level group. A separate schema is cleaner: the grants stay at schema level, and the inheritance works for you. If you must keep payroll in gold, the reader grant on the schema would expose it. That is why we design the schema boundaries around audiences, not only around layers.

Review access every quarter

Remove permissions nobody uses. Once a quarter, list the members of each group and the grants of each schema, and ask the owner to confirm both. Because access flows through groups, the review is a list of group members, not thousands of individual grants. System tables help (lesson 5), since they show what a group actually used.

Common mistakes

  • Missing USE SCHEMA. The classic "I cannot see my table".
  • Granting to a person "just for today". It stays for years.
  • Grants on the catalog when a schema was meant.
  • ALL PRIVILEGES as a shortcut. It grants more than the job needs and hides intent.
  • Owner is the engineer who created the object. Change ownership to the group.

Summary

Grant on the schema, to two groups per schema, and let inheritance cover future tables. Remember the usage privileges. Give ownership to a group. Handle exceptions with separate schemas or table-level groups, and review quarterly.

Next lesson: finer control inside a table with row filters and column masks.

The idea in one picture

Reader and contributor per schema

  1. Entra ID groups
  2. Reader groupUSE, SELECT, READ VOLUME
  3. Contributor groupPlus MODIFY, CREATE TABLE
  4. SchemaFuture tables covered
  5. Owner group

Knowledge check

Answer each question. You see the reason behind every answer at once.

0 of 4 answered

  1. Question 1 of 4A group has SELECT on a table but cannot see it. What is the most likely cause?
  2. Question 2 of 4Why grant at schema level and not on each table?
  3. Question 3 of 4What does MODIFY require?
  4. Question 4 of 4How do you give payroll data a different audience from the rest of a schema?

Hands-on lab

Goal. Generate the GRANT script for a list of schemas and check it against the pattern.

Where to run it

Local Python Run this lab on your own machine with Python 3.10 or newer in a virtual environment.

Python setup guide

Steps

  1. Write schemas.json with four schemas: bronze, silver, gold and gold_hr in two catalogs.
  2. Write generate_grants.py that prints, per schema, the reader and contributor statements from the lesson and ALTER statements for ownership by a group.
  3. Write a checker that reads the output and fails when a statement lacks USE CATALOG or USE SCHEMA, grants to a person, or gives MODIFY without SELECT.
  4. Break one generated statement by hand and confirm that the checker fails.

Expected result

A generated script for all schemas, a checker that passes it and a checker that fails the broken version with a clear message.

Go deeper

Official documentation and recommended courses from the providers.

Read at NexOps

Articles from our own projects on the same topic.

Sources

Last verified 2026-11-11

We check every source against the official documentation. Products change, so confirm details there before you build.