Skip to main content

PostgreSQL

Otterize enables secure and efficient access to your PostgreSQL database, regardless of where it's located, from within your Kubernetes environment. By utilizing Intent-Based Access Control (IBAC), Otterize creates just-in-time username-and-password pairs for your services, delivering them as Kubernetes Secrets that can be mounted to files or mapped to environment variables, as well as GRANTing access to databases and tables based on these declarations. Additionally, Otterize can automatically generate IBAC declarations (ClientIntents) by analyzing your database access patterns, determining which services are accessing which databases, tables, and the specific operations they're performing.

How Otterize Manages Database Access

Otterize manages database access through two specialized components:

Credentials Operator: This component creates and manages Kubernetes Secrets containing username-and-password pairs for your services. It ensures these credentials are synchronized with your PostgreSQL database, even performing password rotations if configured. The Credentials Operator establishes a connection to your database using the credentials provided in the PostgreSQLServerConfig, even if password rotation is not enabled, to set up the initial user credentials.

Intents Operator: This component is responsible for applying GRANTs and REVOKEs to database objects based on your ClientIntents declarations. It ensures that your services have the precise level of access required and nothing more. The Intents Operator also connects to your PostgreSQL database using the same credentials as the Credentials Operator.

Required Database Permissions for otterize

Both the Credentials and Intents Operators require specific permissions within your PostgreSQL database to function correctly. It is recommended to provide a user with administrative privileges or a dedicated user with the following privileges on the relevant schemas:

GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA <your_schema>;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA <your_schema>;
note

The root or privileged account in your database is used exclusively by the Otterize operator during the initial setup phase. It is used to create dedicated users for your workloads and to manage their permissions. Your workloads themselves do not use or have access to the root account's credentials.

Tutorials

To learn how to use the Intents Operator and Credentials Operator to enforce access using PostgreSQL GRANTs, or map access to your PostgreSQL database, try one of these quickstart tutorials.

How does Otterize work with PostgreSQL?

The Otterize credentials operator will create a unique PostgreSQL username-password combination for each service's use, exposed via a Kubernetes Secret. The service will use these credentials to connect to the database. ClientIntents will define the access required by that service. As the intents are applied, The Otterize intents operator will keep the database's list of users and GRANTs up to date so that the service is able to access it.

  1. To get started, your cluster must have Otterize deployed.
  2. You'll need to create a PostgreSQLServerConfig in your cluster, providing a connection URL and admin-level credentials for Otterize to manage permissions in your database. Below is an example PostgreSQLServerConfig resource.
apiVersion: k8s.otterize.com/v1alpha3
kind: PostgreSQLServerConfig
metadata:
name: postgres-tutorial-db # database instance name - should match the target in ClientIntents
namespace: otterize-tutorial-postgres
spec:
address: <PGHOST:PGPORT> # Your Postgres address
credentials:
# Username Otterize will connect with & configure permissions as; optional, can be omitted if using a secretRef
username: <PGUSER>
# Password for the above username; optional, can be omitted if using a secretRef
password: <PGPASSWORD>
# Secret containing the database credentials; optional, can be omitted if using the above username & password fields
secretRef:
# Name of the secret containing the database credentials; required
name: postgres-credentials
# Namespace where the secret is stored; optional, defaults to the namespace of the PostgreSQLServerConfig
namespace: otterize-tutorial-postgres
# Key in the secret containing the username; optional, defaults to 'username'
usernameKey: username
# Key in the secret containing the password; optional, defaults to 'password'
passwordKey: password
  1. Each service can request a username-password Secret to be created, by annotating the Pod with credentials-operator.otterize.com/user-password-secret-name. Below is an example of that annotation and passing the generated credentials into a container with environmental variables.
apiVersion: apps/v1
kind: Deployment
metadata:
name: server
spec:
replicas: 1
selector:
matchLabels:
app: server
template:
metadata:
annotations:
credentials-operator.otterize.com/user-password-secret-name: server-creds
labels:
app: server
spec:
serviceAccountName: server
containers:
- name: server
imagePullPolicy: Always
image: 'supercool/my-example-container'
ports:
- containerPort: 80
env:
- name: DB_SERVER_USER
valueFrom:
secretKeyRef:
name: server-creds
key: username
- name: DB_SERVER_PASSWORD
valueFrom:
secretKeyRef:
name: server-creds
key: password
  1. Apply ClientIntents and the specified access will be GRANTed to the service in the ClientIntents.
apiVersion: k8s.otterize.com/v1alpha3
kind: ClientIntents
metadata:
name: client-intents-for-server
namespace: otterize-tutorial-postgres
spec:
service:
name: server
calls:
- name: postgres-tutorial-db # Same name as our PostgreSQLServerConfig metadata.name
type: database
databaseResources:
- databaseName: otterize-tutorial
table: public.example
operations:
- SELECT
- INSERT
  1. Done!