Storage block
Cerbos supports multiple backends for storing policies. Which storage driver to use is defined by the driver
setting.
Disk driver
The disk driver is a way to serve the policies from a directory on the filesystem. Any .yaml
, .yml
or .json
files in the directory tree rooted at the given path will be read and parsed as policies.
storage:
driver: disk
disk:
directory: /etc/cerbos/policies
storage:
driver: disk
disk:
directory: /etc/cerbos/policies
watchForChanges: true
On some platforms the automatic change detection feature can be inefficient and resource-intensive if the watched directory contains many files or gets updated frequently. |
Blob driver
Cerbos policies can be stored in AWS S3, Google Cloud Storage, or any other S3-compatible storage systems such as Minio.
-
bucket
: Required. A URL specifying the service (e.g. S3, GCS), the storage bucket and any other configuration parameters required by the provider.-
AWS S3:
s3://my-bucket?region=us-west-1
. Must specify region in the URL. -
Google Cloud Storage:
gs://my-bucket
-
S3-compatible (e.g. Minio):
s3://my-bucket?endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true®ion=local
. Must specify region in the URL.
-
-
prefix
: Optional. Look for policies only under this key prefix. -
workDir
: Optional. Path to the local directory to download the policies to. Defaults to the system cache directory if not specified. -
updatePollInterval
: Optional. How frequently the blob store should be checked to discover new or updated policies. Defaults to 0 — which disables polling. -
requestTimeout
: Optional. HTTP request timeout. It takes an HTTP request to download a policy file. Defaults to 5s. -
downloadTimeout
: Optional. Timeout to download all policies from the the storage provider. Must be greater than therequestTimeout
. Defaults to 60s.
Cloud provider credentials are taken from the environment using default credential provider chain. |
Setting the updatePollInterval to a low value could increase resource consumption in both the client and the server systems. Some managed service providers may even impose rate limits or temporary suspensions on your account if the number of requests is too high.
|
storage:
driver: "blob"
blob:
bucket: "s3://my-bucket-name?region=us-east-2"
prefix: policies
workDir: ${HOME}/tmp/cerbos/work
updatePollInterval: 15s
downloadTimeout: 30s
requestTimeout: 10s
storage:
driver: "blob"
blob:
bucket: "gs://my-bucket-name"
workDir: ${HOME}/tmp/cerbos/work
updatePollInterval: 10s
storage:
driver: "blob"
blob:
bucket: "s3://my-bucket-name?endpoint=localhost:9000&disableSSL=true&s3ForcePathStyle=true®ion=local"
workDir: ${HOME}/tmp/cerbos/work
updatePollInterval: 10s
Git driver
Git is the preferred method of storing Cerbos policies. The server is smart enough to detect when new commits are made to the git repository and refresh its state based on the changes.
-
Git repositories can be local (
file
protocol) or remote (ssh
orhttps
). -
If no
branch
is specified, the default branch would be themaster
branch. -
If no
subDir
is specified, the entire repository would be scanned for policies (.yaml
,.yml
or.json
). -
The
checkoutDir
is the working directory of the server and must be writable by the server process. -
If
updatePollInterval
is set to 0, the source repository will not be polled to pick up any new commits. -
If
operationTimeout
is not specified, the default timeout for git operations is 60 seconds.
If the git repository is remote, setting the updatePollInterval to a low value could increase resource consumption in both the client and the server systems. Some managed service providers may even impose rate limits or temporary suspensions on your account if the number of requests is too high.
|
storage:
driver: "git"
git:
protocol: file
url: file://${HOME}/tmp/cerbos/policies
checkoutDir: ${HOME}/tmp/cerbos/work
updatePollInterval: 10s
storage:
driver: "git"
git:
protocol: https
url: https://github.com/cerbos/policy-test.git
branch: main
subDir: policies
checkoutDir: ${HOME}/tmp/work/policies
updatePollInterval: 60s
operationTimeout: 30s
https:
username: cerbos
password: ${GITHUB_TOKEN}
storage:
driver: "git"
git:
protocol: ssh
url: ssh://github.com:cerbos/policy-test.git
branch: main
subDir: policies
checkoutDir: ${HOME}/tmp/cerbos/work
updatePollInterval: 60s
ssh:
user: git
privateKeyFile: ${HOME}/.ssh/id_rsa
SQLite3 Driver
The SQLite3 storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the Admin API.
storage:
driver: "sqlite3"
sqlite3:
dsn: ":memory:"
storage:
driver: "sqlite3"
sqlite3:
dsn: "file:/tmp/cerbos.sqlite?mode=rwc&cache=shared&_fk=true"
Postgres Driver
The Postgres storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the Admin API.
Unlike the SQLite3 driver, the tables and other database objects are not created automatically by the Cerbos Postgres driver. This is to minimize the privileges the Cerbos instance has on the Postgres installation. You must create the required tables using the provided script before configuring Cerbos to connect to the database. |
The driver configuration expects the connection details to be provided as connection URL. See Postgres connstring documentation for more information. Use the search_path
parameter to point to the schema containing the Cerbos tables.
You can use environment variable references in the URL to avoid storing credentials as part of the Cerbos configuration file.
storage:
driver: "postgres"
postgres:
url: "postgres://${PG_USER}:${PG_PASSWORD}@localhost:5432/postgres?sslmode=disable&search_path=cerbos"
Connection pool
Cerbos uses a connection pool when connecting to a database. You can configure the connection pool settings by adding a connPool
section to the driver configuration.
Available options are:
maxLifeTime
-
The maximum length of time a connection can be reused for. This is useful when your database enforces a maximum lifetime on connections or if you have a load balancer in front of your database to spread the load.
maxIdleTime
-
How long a connection should be idle for before it is closed. Useful if you want to cleanup idle connections quickly.
maxOpen
-
Maximum number of connections that can be open at any given time (including idle connections).
maxIdle
-
Maximum number of idle connections that can be open at any given time.
Connection pool settings can have a significant impact on the performance of Cerbos and your database server. Make sure you fully understand the implications of updating these settings before making any changes. |
storage:
driver: "postgres"
postgres:
url: "postgres://${PG_USER}:${PG_PASSWORD}@localhost:5432/postgres?sslmode=disable&search_path=cerbos"
connPool:
maxLifeTime: 5m
maxIdleTime: 3m
maxOpen: 10
maxIdle: 5
Database object definitions
You can customise the script below to suit your environment. Make sure to specify a strong password for the cerbos_user
user.
CREATE SCHEMA IF NOT EXISTS cerbos;
SET search_path TO cerbos;
CREATE TABLE IF NOT EXISTS policy (
id bigint NOT NULL PRIMARY KEY,
kind VARCHAR(128) NOT NULL,
name VARCHAR(1024) NOT NULL,
version VARCHAR(128) NOT NULL,
scope VARCHAR(512),
description TEXT,
disabled BOOLEAN default false,
definition BYTEA
);
CREATE TABLE IF NOT EXISTS policy_dependency (
policy_id BIGINT,
dependency_id BIGINT,
PRIMARY KEY (policy_id, dependency_id),
FOREIGN KEY (policy_id) REFERENCES cerbos.policy(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS policy_ancestor (
policy_id BIGINT,
ancestor_id BIGINT,
PRIMARY KEY (policy_id, ancestor_id),
FOREIGN KEY (policy_id) REFERENCES cerbos.policy(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS policy_revision (
revision_id SERIAL PRIMARY KEY,
action VARCHAR(64),
id BIGINT,
kind VARCHAR(128),
name VARCHAR(1024),
version VARCHAR(128),
scope VARCHAR(512),
description TEXT,
disabled BOOLEAN,
definition BYTEA,
update_timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS attr_schema_defs (
id VARCHAR(255) PRIMARY KEY,
definition JSON
);
CREATE OR REPLACE FUNCTION process_policy_audit() RETURNS TRIGGER AS $policy_audit$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('DELETE', OLD.id, OLD.kind, OLD.name, OLD.version, OLD.scope, OLD.description, OLD.disabled, OLD.definition);
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('UPDATE', NEW.id, NEW.kind, NEW.name, NEW.version, NEW.scope, NEW.description, NEW.disabled, NEW.definition);
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('INSERT', NEW.id, NEW.kind, NEW.name, NEW.version, NEW.scope, NEW.description, NEW.disabled, NEW.definition);
END IF;
RETURN NULL;
END;
$policy_audit$ LANGUAGE plpgsql;
CREATE TRIGGER policy_audit
AFTER INSERT OR UPDATE OR DELETE ON policy
FOR EACH ROW EXECUTE PROCEDURE process_policy_audit();
CREATE USER cerbos_user WITH PASSWORD 'changeme';
GRANT CONNECT ON DATABASE postgres TO cerbos_user;
GRANT USAGE ON SCHEMA cerbos TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON cerbos.policy, cerbos.policy_dependency, cerbos.policy_ancestor, cerbos.attr_schema_defs TO cerbos_user;
GRANT SELECT,INSERT ON cerbos.policy_revision TO cerbos_user;
GRANT USAGE,SELECT ON cerbos.policy_revision_revision_id_seq TO cerbos_user;
MySQL Driver
The MySQL storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the Admin API.
Unlike the SQLite3 driver, the tables and other database objects are not created automatically by the Cerbos MySQL driver. This is to minimize the privileges the Cerbos instance has on the MySQL installation. You must create the required tables using the provided script before configuring Cerbos to connect to the database. |
The driver configuration expects the connection details to be provided as a DSN in the following form:
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
See https://github.com/go-sql-driver/mysql#dsn-data-source-name for the list of supported parameters.
You can use environment variable references in the URL to avoid storing credentials as part of the Cerbos configuration file.
storage:
driver: "mysql"
mysql:
dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos"
Secure connections
If your MySQL server requires TLS or if you want to use RSA key pair-based password exchange, you can configure those settings as follows:
storage:
driver: "mysql"
mysql:
dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos?tls=mysecuretls"
tls:
mysecuretls:
caCert: /path/to/ca_certificate.crt
cert: /path/to/certificate.crt
key: /path/to/private.key
storage:
driver: "mysql"
mysql:
dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos?serverPubKey=mypubkey"
serverPubKey:
mypubkey: /path/to/server_public_key.pem
Connection pool
Cerbos uses a connection pool when connecting to a database. You can configure the connection pool settings by adding a connPool
section to the driver configuration.
Available options are:
maxLifeTime
-
The maximum length of time a connection can be reused for. This is useful when your database enforces a maximum lifetime on connections or if you have a load balancer in front of your database to spread the load.
maxIdleTime
-
How long a connection should be idle for before it is closed. Useful if you want to cleanup idle connections quickly.
maxOpen
-
Maximum number of connections that can be open at any given time (including idle connections).
maxIdle
-
Maximum number of idle connections that can be open at any given time.
Connection pool settings can have a significant impact on the performance of Cerbos and your database server. Make sure you fully understand the implications of updating these settings before making any changes. |
storage:
driver: "mysql"
mysql:
dsn: "${MYSQL_USER}:${MYSQL_PASSWORD}@tcp(localhost:3306)/cerbos"
connPool:
maxLifeTime: 5m
maxIdleTime: 3m
maxOpen: 10
maxIdle: 5
Database object definitions
You can customise the script below to suit your environment. Make sure to specify a strong password for the cerbos_user
user.
CREATE DATABASE IF NOT EXISTS cerbos CHARACTER SET utf8mb4;
USE cerbos;
CREATE TABLE IF NOT EXISTS policy (
id BIGINT PRIMARY KEY,
kind VARCHAR(128) NOT NULL,
name VARCHAR(1024) NOT NULL,
version VARCHAR(128) NOT NULL,
scope VARCHAR(512),
description TEXT,
disabled BOOLEAN default false,
definition BLOB);
CREATE TABLE IF NOT EXISTS policy_dependency (
policy_id BIGINT NOT NULL,
dependency_id BIGINT NOT NULL,
PRIMARY KEY (policy_id, dependency_id),
FOREIGN KEY (policy_id) REFERENCES policy(id) ON DELETE CASCADE);
CREATE TABLE IF NOT EXISTS policy_ancestor (
policy_id BIGINT NOT NULL,
ancestor_id BIGINT NOT NULL,
PRIMARY KEY (policy_id, ancestor_id),
FOREIGN KEY (policy_id) REFERENCES policy(id) ON DELETE CASCADE);
CREATE TABLE IF NOT EXISTS policy_revision (
revision_id INTEGER AUTO_INCREMENT PRIMARY KEY,
action ENUM('INSERT', 'UPDATE', 'DELETE'),
id BIGINT NOT NULL,
kind VARCHAR(128),
name VARCHAR(1024),
version VARCHAR(128),
scope VARCHAR(512),
description TEXT,
disabled BOOLEAN,
definition BLOB,
update_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
CREATE TABLE IF NOT EXISTS attr_schema_defs (
id VARCHAR(255) PRIMARY KEY,
definition JSON);
DROP TRIGGER IF EXISTS policy_on_insert;
CREATE TRIGGER policy_on_insert AFTER INSERT ON policy
FOR EACH ROW
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('INSERT', NEW.id, NEW.kind, NEW.name, NEW.version, NEW.scope, NEW.description, NEW.disabled, NEW.definition);
DROP TRIGGER IF EXISTS policy_on_update;
CREATE TRIGGER policy_on_update AFTER UPDATE ON policy
FOR EACH ROW
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('UPDATE', NEW.id, NEW.kind, NEW.name, NEW.version, NEW.scope, NEW.description, NEW.disabled, NEW.definition);
DROP TRIGGER IF EXISTS policy_on_delete;
CREATE TRIGGER policy_on_delete AFTER DELETE ON policy
FOR EACH ROW
INSERT INTO policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
VALUES('DELETE', OLD.id, OLD.kind, OLD.name, OLD.version, OLD.scope, OLD.description, OLD.disabled, OLD.definition);
CREATE USER IF NOT EXISTS cerbos_user IDENTIFIED WITH mysql_native_password BY 'changeme';
GRANT SELECT,INSERT,UPDATE,DELETE ON cerbos.policy TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON cerbos.attr_schema_defs TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON cerbos.policy_dependency TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON cerbos.policy_ancestor TO cerbos_user;
GRANT SELECT,INSERT ON cerbos.policy_revision TO cerbos_user;
Microsoft SQL Server Driver
The SQL Server storage backend is one of the dynamic stores that supports adding or updating policies at runtime through the Admin API.
Unlike the SQLite3 driver, the tables and other database objects are not created automatically by the Cerbos SQL Server driver. This is to minimize the privileges the Cerbos instance has on the SQL Server installation. You must create the required tables using the provided script before configuring Cerbos to connect to the database. |
The driver configuration expects the connection details to be provided as connection URL. See SQL Server connstring documentation for more information. Use the database
parameter to point to the database containing the Cerbos tables.
You can use environment variable references in the URL to avoid storing credentials as part of the Cerbos configuration file.
storage:
driver: "sqlserver"
sqlserver:
url: "sqlserver://${SQL_SERVER_USERNAME}:${SQL_SERVER_PASSWORD}@host/instance?database=cerbos¶m1=value¶m2=value"
Connection pool
Cerbos uses a connection pool when connecting to a database. You can configure the connection pool settings by adding a connPool
section to the driver configuration.
Available options are:
maxLifeTime
-
The maximum length of time a connection can be reused for. This is useful when your database enforces a maximum lifetime on connections or if you have a load balancer in front of your database to spread the load.
maxIdleTime
-
How long a connection should be idle for before it is closed. Useful if you want to cleanup idle connections quickly.
maxOpen
-
Maximum number of connections that can be open at any given time (including idle connections).
maxIdle
-
Maximum number of idle connections that can be open at any given time.
Connection pool settings can have a significant impact on the performance of Cerbos and your database server. Make sure you fully understand the implications of updating these settings before making any changes. |
storage:
driver: "sqlserver"
sqlserver:
url: "sqlserver://${SQL_SERVER_USERNAME}:${SQL_SERVER_PASSWORD}@host/instance?database=cerbos¶m1=value¶m2=value"
connPool:
maxLifeTime: 5m
maxIdleTime: 3m
maxOpen: 10
maxIdle: 5
Database object definitions
You can customise the script below to suit your environment. Make sure to specify a strong password for the cerbos_user
user.
IF SUSER_ID('cerbos_user') IS NULL
CREATE LOGIN cerbos_user WITH PASSWORD = 'ChangeMe(1!!)';
GO
IF NOT EXISTS (
SELECT [name]
FROM sys.databases
WHERE [name] = N'cerbos'
)
CREATE DATABASE cerbos;
GO
USE cerbos;
IF OBJECT_ID('[dbo].[policy]', 'U') IS NULL
CREATE TABLE [dbo].[policy] (
id BIGINT PRIMARY KEY,
kind VARCHAR(128) NOT NULL,
name VARCHAR(1024) NOT NULL,
version VARCHAR(128) NOT NULL,
scope VARCHAR(512),
description NVARCHAR(MAX),
disabled BIT default 'FALSE',
definition VARBINARY(MAX));
IF OBJECT_ID('[dbo].[policy_dependency]', 'U') IS NULL
CREATE TABLE [dbo].[policy_dependency] (
policy_id BIGINT NOT NULL,
dependency_id BIGINT NOT NULL,
PRIMARY KEY (policy_id, dependency_id),
FOREIGN KEY (policy_id) REFERENCES [policy](id) ON DELETE CASCADE);
IF OBJECT_ID('[dbo].[policy_ancestor]', 'U') IS NULL
CREATE TABLE [dbo].[policy_ancestor] (
policy_id BIGINT NOT NULL,
ancestor_id BIGINT NOT NULL,
PRIMARY KEY (policy_id, ancestor_id),
FOREIGN KEY (policy_id) REFERENCES [policy](id) ON DELETE CASCADE);
IF OBJECT_ID('[dbo].[policy_revision]', 'U') IS NULL
CREATE TABLE [dbo].[policy_revision] (
revision_id INT NOT NULL IDENTITY PRIMARY KEY,
action VARCHAR(255) NOT NULL CHECK ([action] IN('INSERT', 'UPDATE', 'DELETE')),
id BIGINT NOT NULL,
kind VARCHAR(128),
name VARCHAR(1024),
version VARCHAR(128),
scope VARCHAR(512),
description NVARCHAR(MAX),
disabled BIT,
definition VARBINARY(MAX),
update_timestamp DATETIME DEFAULT CURRENT_TIMESTAMP);
IF OBJECT_ID('[dbo].[attr_schema_defs]', 'U') IS NULL
CREATE TABLE [dbo].[attr_schema_defs] (
id VARCHAR(255) NOT NULL PRIMARY KEY,
definition VARBINARY(MAX));
DROP TRIGGER IF EXISTS dbo.policy_on_insert;
DROP TRIGGER IF EXISTS dbo.policy_on_update;
DROP TRIGGER IF EXISTS dbo.policy_on_delete;
GO
USE cerbos;
IF USER_ID('cerbos_user') IS NULL
CREATE USER cerbos_user for LOGIN cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON [dbo].[policy] TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON dbo.attr_schema_defs TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON dbo.policy_dependency TO cerbos_user;
GRANT SELECT,INSERT,UPDATE,DELETE ON dbo.policy_ancestor TO cerbos_user;
GRANT SELECT,INSERT ON dbo.policy_revision TO cerbos_user;
GO
CREATE TRIGGER dbo.policy_on_insert ON dbo.[policy] AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
SELECT
'INSERT', i.id, i.kind, i.name, i.version, i.scope, i.description, i.disabled, i.definition
FROM inserted i
END;
GO
CREATE TRIGGER dbo.policy_on_update ON dbo.[policy] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
SELECT
'UPDATE', i.id, i.kind, i.name, i.version, i.scope, i.description, i.disabled, i.definition
FROM inserted i
END;
GO
CREATE TRIGGER dbo.policy_on_delete ON dbo.[policy] AFTER DELETE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.policy_revision(action, id, kind, name, version, scope, description, disabled, definition)
SELECT
'DELETE', d.id, d.kind, d.name, d.version, d.scope, d.description, d.disabled, d.definition
FROM deleted d
END;