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:

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.

SystemPort numberExposingNameCertificatesAuthentication
operator9443webhook serverwebhook-serverTLSYes
operator8080metricsmetricsno TLSNo
instance manager9187metricsmetricsno TLSNo
instance manager8000statusstatusno TLSNo
operand5432PostgreSQL instancepostgresqloptional TLSYes

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.