Security
Security for EDB Postgres Distributed for Kubernetes is analyzed at three layers: code, container, and cluster.
Warning
In addition to security practices described here, you must perform regular InfoSec duties on your Kubernetes cluster. Familiarize yourself with Overview of Cloud Native Security in the Kubernetes documentation.
About the 4C's Security Model
See The 4C's Security Model in Kubernetes blog article for a better understanding and context of the approach EDB takes with security in EDB Postgres Distributed for Kubernetes.
Code
Source code of EDB Postgres Distributed for Kubernetes is systematically scanned for static analysis purposes, including security problems. EDB uses a popular open-source linter for Go called GolangCI-Lint directly in the CI/CD pipeline. GolangCI-Lint can run several linters on the same source code.
One of these is Golang Security Checker, or gosec
.
gosec
is a linter that scans the abstract syntactic tree of the source against a set of rules aimed at discovering well-known vulnerabilities, threats, and weaknesses hidden in
the code. These threads include hard-coded credentials, integer overflows, SQL injections, and others.
Important
A failure in the static code analysis phase of the CI/CD pipeline is a blocker for the entire delivery of EDB Postgres Distributed for Kubernetes, meaning that each commit is validated against all the linters defined by GolangCI-Lint.
Container
Every container image that's part of EDB Postgres Distributed for Kubernetes is built by way of CI/CD pipelines following every commit. Such images include not only those of the operator but also of the operands, specifically every supported PostgreSQL version. In the pipelines, images are scanned with:
- Dockle for best practices in terms of the container build process
- Clair for vulnerabilities found in both the underlying operating system and libraries and applications that they run
Important
All operand images are rebuilt once a day by our pipelines in case of security updates at the base image and package level, providing patch level updates for the container images that EDB distributes.
The following guidelines and frameworks were taken into account for container-level security:
- The Container Image Creation and Deployment Guide, developed by the Defense Information Systems Agency (DISA) of the United States Department of Defense (DoD)
- The CIS Benchmark for Docker, developed by the Center for Internet Security (CIS)
About the container-level security
See the Security and Containers in EDB Postgres Distributed for Kubernetes blog article for more information about the approach that EDB takes on security at the container level in EDB Postgres Distributed for Kubernetes.
Cluster
Security at the cluster level takes into account all Kubernetes components that form both the control plane and the nodes as well as the applications that run in the cluster, including PostgreSQL.
Role-based access control (RBAC)
The operator interacts with the Kubernetes API server with a dedicated service
account called pgd-operator-controller-manager. In Kubernetes this account is installed
by default in the pgd-operator-system
namespace. A cluster role
binds between this service account and the pgd-operator-controller-manager
cluster role that defines the set of rules, resources, and verbs granted to the operator.
RedHat OpenShift directly manages the operator RBAC entities by way of Operator Lifecycle Manager (OLM). OLM allows you to grant permissions only where they're required, implementing the principle of least privilege.
Important
These permissions are exclusively reserved for the operator's service
account to interact with the Kubernetes API server. They aren't directly
accessible by the users of the operator that interact only with PGDGroup
and PGDGroupCleanup
resources.
The following are some examples and, most importantly, the reasons why EDB Postgres Distributed for Kubernetes requires full or partial management of standard Kubernetes namespaced resources.
jobs
: The operator needs to handle jobs to manage different PGDGroup
phases.
poddisruptionbudgets
: The operator uses pod disruption budgets to make sure enough PGD nodes
are kept active during maintenance operations.
pods
: The operator needs to manage PGD nodes as a Cluster
resource.
secrets
: Unless you provide certificates and passwords to your data nodes,
the operator adopts the "convention over configuration" paradigm by
self-provisioning random-generated passwords and TLS certificates and by
storing them in secrets.
serviceaccounts
: The operator needs to create a service account to
enable the PGDGroup
recovery job to retrieve the backup objects from
the object store where they reside.
services
: The operator needs to control network access to the PGD cluster
from applications and properly manage
failover/switchover operations in an automated way.
statefulsets
: The operator needs to manage PGD proxies.
validatingwebhookconfigurations
and mutatingwebhookconfigurations
: The operator injects its self-signed webhook CA into both webhook
configurations, which are needed to validate and mutate all the resources it
manages. For more details, see the
Kubernetes documentation.
To see all the permissions required by the operator, you can run kubectl
describe clusterrole pgd-operator-manager-role
.
EDB Postgres Distributed for Kubernetes internally manages the PGD nodes using the Cluster
resource as defined by EDB Postgres
for Kubernetes. See the
EDB Postgres for Kubernetes documentation
for the list of permissions used by the EDB Postgres for Kubernetes operator service account.
Calls to the API server made by the instance manager
The instance manager, which is the entry point of the operand container, needs
to make some calls to the Kubernetes API server to ensure that the status of
some resources is correctly updated and to access the config maps and secrets
that are associated with that Postgres cluster. Such calls are performed through
a dedicated ServiceAccount
created by the operator that shares the same
PostgreSQL Cluster
resource name.
Important
The operand can access only a specific and limited subset of resources through the API server. A service account is the recommended way to access the API server from within a pod. See the Kubernetes documentation for details.
See the EDB Postgres for Kubernetes documentation for more information on the instance manager.
Pod security policies
A pod security policy is the Kubernetes way to define security rules and specifications that a pod needs to meet to run in a cluster. For InfoSec reasons, every Kubernetes platform must implement them.
EDB Postgres Distributed for Kubernetes doesn't require privileged mode for containers execution. The PostgreSQL containers run as the postgres system user. No component requires running as root.
Likewise, volumes access doesn't require privileged mode or root privileges. Proper permissions must be assigned by the Kubernetes platform or administrators. The PostgreSQL containers run with a read-only root filesystem, that is, no writable layer.
The operator explicitly sets the required security contexts.
On Red Hat OpenShift, Cloud Native PostgreSQL runs in the restricted
security context constraint,
the most restrictive one. The goal is to limit the execution of a pod to a namespace allocated UID
and SELinux context.
Security Context Constraints in OpenShift
For more information on security context constraints (SCC) in OpenShift, see the Managing SCC in OpenShift article.
Security context constraints and namespaces
As stated in the Openshift documentation,
SCCs aren't applied in the default namespaces (default
, kube-system
,
kube-public
, openshift-node
, openshift-infra
, openshift
). Don't use them
to run pods. CNP clusters deployed in those namespaces
will be unable to start due to missing SCCs.
Exposed ports
EDB Postgres Distributed for Kubernetes exposes ports at operator, instance manager, and operand levels, as shown in the table.
System | Port number | Exposing | Name | Certificates | Authentication |
---|---|---|---|---|---|
operator | 9443 | webhook server | webhook-server | TLS | Yes |
operator | 8080 | metrics | metrics | no TLS | No |
instance manager | 9187 | metrics | metrics | no TLS | No |
instance manager | 8000 | status | status | no TLS | No |
operand | 5432 | PostgreSQL instance | postgresql | optional TLS | Yes |
PGD
The current implementation of EDB Postgres Distributed for Kubernetes creates passwords for the postgres superuser and the database owner.
As far as encryption of passwords is concerned, EDB Postgres Distributed for Kubernetes follows
the default behavior of PostgreSQL: starting with PostgreSQL 14,
password_encryption
is by default set to scram-sha-256
. On earlier
versions, it's set to md5
.
Important
See Connection DSNs and SSL in the PGD documentation for details.
You can disable management of the postgres user password using secrets by setting
enableSuperuserAccess
to false
in the cnp
section of the spec.
Note
The operator supports toggling the enableSuperuserAccess
option. When you
disable it on a running cluster, the operator ignores the content of the secret.
Remove it (if previously generated by the operator) and set the password of the
postgres user to NULL
, in effect disabling remote access through password authentication.
Storage
EDB Postgres Distributed for Kubernetes delegates encryption at rest to the underlying storage class. For data protection in production environments, we highly recommend that you choose a storage class that supports encryption at rest.