Encrypting Postgres Data at Rest in Kubernetes
Encrypting data at rest is often an important compliance task when working on securing your database system. While there are a lot of elements that go into securing a PostgreSQL database, encrypting data at rest helps to protect your data from various offline attacks including the stealing of a disk or tampering. Disk encryption is a popular feature among public database-as-a-service providers, including Crunchy Bridge, to protect data in a multi-tenant environment.
There is ongoing work in the PostgreSQL community to natively support transparent data encryption (TDE), which lets you control encryption at rest from Postgres. While there are options such as Crunchy Hardened PostgreSQL that offer TDE solutions, you can still encrypt your PostgreSQL data at rest today by doing so at the disk level. In a Kubernetes environment, this is done by using a storage class that supports encryption.
Let's look at an example of how we can encrypt Postgres data at rest using PGO, the open source Postgres Operator from Crunchy Data
Creating Encrypted Volumes
For this example, we are going to use AWS EBS volumes to store our data on EKS. AWS EBS volumes contain a type called gp2 which provide SSD volumes as the underlying storage.
In the case of the gp2
volumes, we need to set up a Kubernetes StorageClass
that specifies for them to be encrypted. You can do this with the following
manifest:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: gp2-enc
provisioner: kubernetes.io/aws-ebs
parameters:
encrypted: 'true'
fsType: ext4
type: gp2
volumeBindingMode: WaitForFirstConsumer
Because storage classes are cluster-wide objects, you will need to ensure you
have appropriate permissions in your Kubernetes cluster to create a new
StorageClass
.
As an added bonus, let's set the encrypted storage class to be the default
storage class. You will first have to unset the current default storage class,
which is likely a gp2
StorageClass:
kubectl patch storageclass gp2 -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
You can then set the gp2-enc
StorageClass to become the default:
kubectl patch storageclass gp2-enc -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
With the ability to provision encrypted volumes in place, let's look at how to create encrypted PostgreSQL volumes with PGO!
Encrypting Postgres Data at Rest
Using the Postgres Operator, if you set the gp2-enc
StorageClass to be the
default class, creating a Postgres cluster with encrypted volumes is as simple
as using the following manifest:
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: keycloakdb
spec:
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.0-0
postgresVersion: 14
instances:
- dataVolumeClaimSpec:
accessModes:
- 'ReadWriteOnce'
resources:
requests:
storage: 1Gi
backups:
pgbackrest:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.35-0
repos:
- name: repo1
volume:
volumeClaimSpec:
accessModes:
- 'ReadWriteOnce'
resources:
requests:
storage: 1Gi
However, if you want to specify the gp2-enc
storage class, you would do the
following:
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: keycloakdb
spec:
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:centos8-14.0-0
postgresVersion: 14
instances:
- dataVolumeClaimSpec:
storageClassName: gp2-enc
accessModes:
- 'ReadWriteOnce'
resources:
requests:
storage: 1Gi
backups:
pgbackrest:
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:centos8-2.35-0
repos:
- name: repo1
volume:
volumeClaimSpec:
storageClassName: gp2-enc
accessModes:
- 'ReadWriteOnce'
resources:
requests:
storage: 1Gi
In other words, you need to add the storageClassName
to each volume claim
specification.
Notice that we encrypt both the PostgreSQL data directory and the pgBackRest volume. Why do we encrypt the backup volume as well? If you are encrypting data at rest, you need to encrypt it on each volume you store any transformation of your data on, otherwise you create a potential vector for someone to access your unencrypted data!
Next Steps
Kubernetes offers a variety of storage classes, many of which support transparent data encryption. If you are using hostpath or NFS storage, you can encrypt your volumes using a variety of disk utilities.
There are a variety of ways to encrypt data at rest. Disk level encryption is a proven and efficient method and allows you to focus on other aspects of your applications!
(Interested in seeing PGO in action? Join us for a webinar on Wednesday, Nov 17th.)
![Avatar for Jonathan S. Katz](webp/default.png-w4xgd4db.webp)