Skip to content

Policies

A policy is one YAML object. Sluice denies every query that no policy allows.

Example

This policy lets the analysts group read two tables.

apiVersion: sluice.bino.bi/v1alpha1
kind: SqlAccessPolicy
metadata:
  name: allow-analysts
  priority: 100
spec:
  effect: allow
  match:
    any:
      - subjects:
          groups: ["analysts"]
        resources:
          catalogs: ["shop"]
          schemas: ["main"]
          tables: ["orders", "customers"]

Check the policy directory:

sluice policy validate policies.d
policies OK: policies.d (2 objects, digest <digest>)

The file in invalid has effect: Allow, with a capital letter:

sluice policy validate invalid
invalid/allow-analysts.yaml: SqlAccessPolicy/allow-analysts: spec.effect: must be "allow" or "deny"
1 validation error(s)
[exit status 3]

Exit status 3 means an invalid policy. Without --strict, Sluice ignores unknown fields.

Policy kinds

Kind Purpose
SqlAccessPolicy Allows or denies access to tables.
RowFilterPolicy Limits the rows a subject reads.
ColumnMaskPolicy Replaces the values of a column.
QueryRejectPolicy Rejects a query that matches a rule.
QueryRewritePolicy Limits rows, samples rows or sets a timeout.
ApprovalPolicy Holds a query until a person accepts it.
SubjectBinding Defines subjects from API keys or JWTs.
DataSource Attaches a database or file store.
DataClassification Puts tags on tables and columns.
RelationshipPolicy Asks OpenFGA about a table.

DataClassification and RelationshipPolicy use apiVersion: sluice.bino.bi/v1beta1, all other kinds sluice.bino.bi/v1alpha1. Another value is a load error.

Shared fields

Field Type Default Meaning
metadata.name string required Lower case letters and digits, also - between them. Unique per kind.
metadata.priority int 0 0 to 1000. The highest comes first, then the name decides.
spec.match object required Subjects and tables the policy covers. See Matching.
spec.exclude object none Subjects or tables to leave out.
spec.conditions list none CEL expressions that must all be true. See Conditions.
spec.enforcementMode string Enforce Enforce, Audit or DryRun.

SubjectBinding, DataSource and DataClassification do not have the spec fields. RelationshipPolicy has no conditions.

Enforcement mode

Audit and DryRun do the same: the policy matches but does not enforce. Example:

apiVersion: sluice.bino.bi/v1alpha1
kind: SqlAccessPolicy
metadata:
  name: deny-customers
  priority: 500
spec:
  # Audit mode: the policy matches, but it does not deny.
  enforcementMode: Audit
  effect: deny
  match:
    any:
      - resources:
          catalogs: ["shop"]
          schemas: ["main"]
          tables: ["customers"]
sluice policy explain --policies-dir policies.d \
  --user alice --groups analysts \
  --table shop.main.customers --json
{
  "subject": "alice",
  "resource": "shop.main.customers",
  "matched": [
    {
      "kind": "SqlAccessPolicy",
      "name": "allow-analysts",
      "priority": 100
    }
  ],
  "rejected": null,
  "effective": {
    "decision": "allow"
  },
  "shadow": [
    {
      "kind": "SqlAccessPolicy",
      "name": "deny-customers",
      "priority": 500,
      "would": "deny"
    }
  ]
}

The decision is allow. The deny shows under shadow, with would: deny. The audit record of each query lists it under policies_shadow, so you can see what the policy would stop before you enforce it.

Loading

  • Sluice reads all *.yaml and *.yml files under policies.directory (default ./policies.d), also in subdirectories.
  • It skips tests, testdata and directories that start with a dot.
  • One file can hold many objects, separated by ---.
  • With an empty policy directory, Sluice denies every query.
  • A query needs at least a DataSource, a SubjectBinding and an allow.

Limits

  • A failing condition still denies the query in Audit and DryRun mode: ACL_DENIED.
  • --strict does not check the keys under spec.mask.args.
  • A missing path validates as 0 objects, exit status 0.

See also