Skip to the page
← All docs

Make a read-only role

The agent reads every database through a role that can only read. That is the first of three walls. The second is a guard on every statement: one SELECT, nothing else. The third is the session: a read-only transaction, a statement timeout, and at most 500 rows a page. Make the role once, as an administrator, and give its URL to strata connect add.

PostgreSQL. Run these as an owner of the database, the last three once for each schema the agent should read (public here):

CREATE ROLE strata_reader LOGIN PASSWORD '<a new password>';
GRANT CONNECT ON DATABASE crm TO strata_reader;
GRANT USAGE ON SCHEMA public TO strata_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO strata_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO strata_reader;

The last line gives the role SELECT on tables made later, so a migration does not leave the agent unable to read a new table. The proof asks the server what the role may do on every table, so a write it inherits through another role is seen and refused, and so are the built-in roles that reach the server's files or write every table (pg_write_all_data and its like).

MySQL and MariaDB. As an administrator:

CREATE USER 'strata_reader'@'%' IDENTIFIED BY '<a new password>';
GRANT SELECT, SHOW VIEW ON support.* TO 'strata_reader'@'%';

The proof reads SHOW GRANTS: anything but SELECT and SHOW VIEW is refused, and so is a role granted to the user or WITH GRANT OPTION. Narrow '%' to the address the agent connects from if you can.

SQL Server. As an administrator, the last line once for each schema the agent should read:

CREATE LOGIN strata_reader WITH PASSWORD = '<a new password>';
USE [billing];
CREATE USER strata_reader FOR LOGIN strata_reader;
GRANT SHOWPLAN TO strata_reader;
GRANT SELECT ON SCHEMA::[dbo] TO strata_reader;

SHOWPLAN lets db_explain show a plan; it reads no row. The proof asks the server for the login's permissions at the server and in the database, and whether it may INSERT, UPDATE or DELETE on each table and view: sysadmin, a role that writes (db_owner, db_datawriter, db_ddladmin…), EXECUTE, or anything past reading is refused. SQL Server has no read-only transaction, so this role and the guard are the walls that matter most there: the agent also runs each statement inside a transaction it always rolls back, under a lock timeout, and stops reading at the row cap.

Oracle. As an administrator in the pluggable database (on 23ai, one grant for each schema; before it, GRANT READ ON claims.<table> TO strata_reader; for each table):

CREATE USER strata_reader IDENTIFIED BY "<a new password>";
GRANT CREATE SESSION TO strata_reader;
GRANT READ ANY TABLE ON SCHEMA claims TO strata_reader;

The proof reads the user's privileges in effect through every role it holds (SESSION_PRIVS), its grants on your schemas to it, its roles and PUBLIC, 23ai's schema privileges, and whether it owns a table: anything past CREATE SESSION and reading is refused. Oracle cannot explain a statement without writing its plan into PLAN_TABLE, which the read-only session refuses, so db_explain answers why instead of a plan there.

SQLite. Nothing to make: the agent opens the file read-only, and the guard and the session's limits apply as for the others.

Narrower still. To keep a table out of reach altogether, grant SELECT table by table instead of on the whole schema. The agent reflects and reads only what its role may see. Your workspace's policy can narrow a role to named sources and tables too (see Roles, tiers and rules), but a grant you never gave is the surest wall.

If strata connect add refuses a role, it prints these lines filled in with your database's name and schemas, with what the role could do that it should not.