Database Access RBAC
Role-based access control (or RBAC, for short) allows administrators to set up granular access policies for databases connected to Teleport.
An example of a policy could be, "database administrators have access to everything, QA team and engineers have full access to staging databases, and engineers can gain temporary access to the production database in case of emergency".
For a more general description of Teleport roles and examples see RBAC, as this section focuses on configuring RBAC for database access.
Role configuration
Teleport's "role" resource provides the following instruments for restricting database access:
kind: role
version: v5
metadata:
name: developer
spec:
allow:
# Label selectors for database instances this role has access to.
#
# These will be matched against the static/dynamic labels set on the
# database service.
db_labels:
environment: ["dev", "stage"]
# Database account names this role can connect as.
db_users: ["viewer", "editor"]
# Database names this role will be able to connect to.
#
# Note, this is not the same as the "name" field in "db_service", this is
# the database names within a particular database instance.
#
# Also note, this setting has effect only for PostgreSQL. It does not
# currently have any effect on MySQL databases/schemas.
db_names: ["main", "metrics", "postgres"]
It is possible to use wildcards to match any database names/users.
For example, the following role permits access to any database/user within a production database except for the internal "postgres" database/user:
kind: role
version: v5
metadata:
name: developer
spec:
allow:
db_labels:
environment: ["prod"]
db_users: ["*"]
db_names: ["*"]
deny:
db_users: ["postgres"]
db_names: ["postgres"]
Deny rules will match greedily. In the example above, a database connection attempting to use "postgres" database account (regardless of database instance or database name) or "postgres" database name (regardless of database instance or database account) will be rejected.
Database names
There's a distinction in how different database servers handle logical databases
which leads to a difference in how db_names
role field is applied to a connection
attempt.
PostgreSQL supports multiple logical databases, and each logical database can
contain multiple schemas. In order to change to a different database, a user
disconnects from the current one and establishes a new connection. During a
PostgreSQL connection attempt, db_names
field is checked against the name
of the logical database that the user is connecting to.
In MySQL a logical "database" and a "schema" are synonyms for each other, and
the scope of permissions a user has once connected is determined by the permission
grants set on the account within the database. As such, db_names
role field
is not currently enforced on MySQL connection attempts.
Template variables
Similar to other role fields, db_*
fields support templating variables.
The external.xyz
traits are replaced with values from external single
sign-on providers. For OIDC, they will be
replaced with the value of an "xyz" claim. For SAML, they are replaced
with an "xyz" assertion value.
For full details on how traits work in Teleport roles, see the Teleport Access Controls Reference.
For example, here is what a role may look like if you want to assign allowed
database names from the user's Okta databases
assertion:
spec:
allow:
db_names: ["{{external.databases}}"]
The {{internal.db_users}}
and {{internal.db_names}}
variables permit sharing
allowed database accounts and names with remote clusters. They will be replaced
with the respective properties of a remote user connecting from a root cluster.
For example, suppose a user in the root cluster has the following role:
spec:
allow:
db_users: ["postgres"]
db_names: ["postgres"]
The role on the leaf cluster can be set up to use the user's allowed database accounts and names:
spec:
allow:
db_users: ["{{internal.db_users}}"]
db_names: ["{{internal.db_names}}"]