Back to changelog
New
2 minute read

Redshift: Roles, Groups, Users, and Permissions as Code

Atlas now inspects, diffs, and migrates Amazon Redshift roles, groups, users, and the grants they hold, so a role hierarchy and every schema-, table-, and column-level GRANT live alongside your schema and are reconciled with the exact GRANT and REVOKE statements.

Enabling roles and permissions

Roles and permissions are excluded from inspection and schema management by default. Turn them on per environment with a schema.mode block:

atlas.hcl
env "redshift" {  url = getenv("REDSHIFT_URL")  dev = getenv("REDSHIFT_DEV_URL")
  schema {    src = "file://schema.rs.hcl"    mode {      roles       = true   // Inspect and manage roles, groups, and users      permissions = true   // Inspect and manage GRANT / REVOKE    }  }}

Roles, groups, and users are cluster-wide rather than scoped to a database, so give the dev environment its own provisioned cluster or Serverless workgroup, and declare the accounts Atlas must never touch, such as the cluster admin, with external = true.

Defining roles, groups, and users

Redshift keeps these three apart, and Atlas manages all of them: a role block is an RBAC role, the same block with group = true is a group, and a user block is a login user. member_of builds the hierarchy across all three.

schema.rs.hcl
role "app_readonly" {}
role "app_writer" {  member_of = [role.app_readonly]}
// A group is a role carrying the group marker: Redshift keeps// CREATE GROUP apart from CREATE ROLE.role "app_analysts" {  group = true}
user "app_api" {  conn_limit = 5  member_of  = [role.app_writer, role.app_analysts]}

Granting privileges

A permission block grants privileges on a schema, table, view, materialized view, or a single column, to a role, a group, a user, or PUBLIC. A group is referenced as role.<name>, and Atlas writes it as the GROUP grantee Redshift expects:

schema.rs.hcl
permission {  to         = role.app_readonly  for        = schema.reporting  privileges = [USAGE]}
permission {  to         = role.app_readonly  for        = table.orders  privileges = [SELECT]}
// Grants can go down to a single column.permission {  to         = role.app_analysts  for        = table.orders.column.total  privileges = [SELECT]}

Applying the change

Both workflows are supported, and the statements are the same either way:

# Declarative: reconcile the cluster with the desired state.atlas schema apply --env redshift
# Versioned: capture the change as a migration file.atlas migrate diff add_security --env redshift

Whether they land in a plan or in a migration file, Atlas orders them around the constraints the cluster enforces: revokes before grants, memberships dropped before new ones are added, and privileges revoked before the role or user holding them is dropped.

migration.sql
-- Create group "app_analysts"CREATE GROUP "app_analysts";-- Create role "app_readonly"CREATE ROLE "app_readonly";-- Create role "app_writer"CREATE ROLE "app_writer";-- Add "app_writer" to "app_readonly"GRANT ROLE "app_readonly" TO ROLE "app_writer";-- Create user "app_api"CREATE USER "app_api" PASSWORD DISABLE CONNECTION LIMIT 5;-- Add "app_api" to "app_analysts"ALTER GROUP "app_analysts" ADD USER "app_api";-- Add "app_api" to "app_writer"GRANT ROLE "app_writer" TO "app_api";-- Grant on schema "reporting" to "app_readonly"GRANT USAGE ON SCHEMA "reporting" TO ROLE "app_readonly";-- Grant on table "orders" to "app_readonly"GRANT SELECT ON TABLE "reporting"."orders" TO ROLE "app_readonly";-- Grant on column "total" on table "orders" to "app_analysts"GRANT SELECT ("total") ON TABLE "reporting"."orders" TO GROUP "app_analysts";

Going the other way works too: point Atlas at an existing cluster and atlas schema inspect writes the roles, groups, users, and grants it finds back out as HCL or SQL.

Getting Started

Redshift roles and permissions are part of Atlas Pro:

$ atlas login

See the declarative and versioned security guides for the full walkthrough, the HCL reference for every attribute, and the Security Graph to see how the resulting grants connect across your repository.

featureredshiftrolespermissionssecurityatlas pro