Skip to content

Commit 57cc6d3

Browse files
committed
Remove duplicate database code in provider logic
Replice terminate_backend with WITH (FORCE)
1 parent 4c908b6 commit 57cc6d3

File tree

13 files changed

+721
-339
lines changed

13 files changed

+721
-339
lines changed

README.md

Lines changed: 95 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Manage external PostgreSQL databases in Kubernetes with ease—supporting AWS RD
1313
- [Features](#features)
1414
- [Supported Cloud Providers](#supported-cloud-providers)
1515
- [Configuration](#configuration)
16+
- [Dedicated Operator Role](#dedicated-operator-role)
1617
- [Installation](#installation)
1718
- [Custom Resources (CRs)](#custom-resources-crs)
1819
- [Multiple Operator Support](#multiple-operator-support)
@@ -66,27 +67,83 @@ Set `POSTGRES_CLOUD_PROVIDER` to `AWS` via environment variable, Kubernetes Secr
6667

6768
Set environment variables in [`config/manager/operator.yaml`](config/manager/operator.yaml):
6869

69-
| Name | Description | Default |
70-
| --- | --- | --- |
71-
| `WATCH_NAMESPACE` | Namespace to watch. Empty string = all namespaces. | (all namespaces) |
72-
| `POSTGRES_INSTANCE` | Operator identity for multi-instance deployments. | (empty) |
73-
| `KEEP_SECRET_NAME` | Use user-provided secret names instead of auto-generated ones. | disabled |
70+
| Name | Description | Default |
71+
| ------------------- | -------------------------------------------------------------- | ---------------- |
72+
| `WATCH_NAMESPACE` | Namespace to watch. Empty string = all namespaces. | (all namespaces) |
73+
| `POSTGRES_INSTANCE` | Operator identity for multi-instance deployments. | (empty) |
74+
| `KEEP_SECRET_NAME` | Use user-provided secret names instead of auto-generated ones. | disabled |
7475

7576
> **Note:**
7677
> If enabling `KEEP_SECRET_NAME`, ensure there are no secret name conflicts in your namespace to avoid reconcile loops.
7778
79+
## Dedicated Operator Role
80+
81+
The operator connects to PostgreSQL using the credentials configured via the `POSTGRES_*` environment variables / Secret (see below). In many setups these credentials are the _server admin_ or _master user_.
82+
83+
You can also run the operator using a **dedicated operator login role** (recommended for production), for better separation of duties and easier auditing/rotation.
84+
85+
### What privileges are required?
86+
87+
This operator manages databases and roles, and also runs some operations inside the created databases. Your operator login role must be able to:
88+
89+
- Create databases and set database owners (`CREATE DATABASE`, `ALTER DATABASE ... OWNER TO ...`)
90+
- Grant database-level privileges (the operator runs `GRANT CREATE ON DATABASE ...`)
91+
- Create roles/users and manage role membership (`CREATE ROLE`, `DROP ROLE`, `GRANT <role> TO <grantee>`, `REVOKE ...`)
92+
- Connect to managed databases and:
93+
- Create schemas (`CREATE SCHEMA ... AUTHORIZATION ...`)
94+
- Create extensions (`CREATE EXTENSION ...`)
95+
- Grant privileges / alter default privileges within schemas
96+
97+
The operator also grants each created role to itself, so it can later revoke privileges, reassign ownership, and drop roles cleanly.
98+
99+
### Example: creating an operator role
100+
101+
The exact SQL depends on how your PostgreSQL instance is managed. In plain PostgreSQL (self-hosted), you can often do something like:
102+
103+
```sql
104+
-- Create a dedicated login for the Kubernetes operator
105+
CREATE ROLE pgoperator WITH
106+
PASSWORD 'YourSecurePassword123!'
107+
LOGIN
108+
CREATEDB
109+
CREATEROLE;
110+
```
111+
112+
For managed services, you typically create `ext_postgres_operator` while connected as the platform-provided admin and grant only the capabilities supported by that platform.
113+
114+
### Cloud provider notes
115+
116+
Because this is an _external / managed PostgreSQL_ operator, the feasibility of least-privilege depends on your provider.
117+
118+
- **AWS RDS (PostgreSQL)**
119+
- The initial “master user” is a member of the `rds_superuser` role.
120+
- A dedicated operator role is usually possible: create a login role with `CREATEDB`/`CREATEROLE`, then grant it any extra permissions you need for extensions/schemas.
121+
- Docs: <https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Roles.html>
122+
123+
- **GCP Cloud SQL (PostgreSQL)**
124+
- Cloud SQL does not expose true `SUPERUSER`. The default `postgres` user is a member of `cloudsqlsuperuser` and has `CREATEROLE` and `CREATEDB`.
125+
- You can create other users/roles with reduced privileges (for example, an operator role with `CREATEROLE`/`CREATEDB`), but some operations (notably certain extensions) may require `cloudsqlsuperuser`.
126+
- Docs: <https://cloud.google.com/sql/docs/postgres/users>
127+
128+
- **Azure Database for PostgreSQL  Flexible Server**
129+
- The server admin user is a member of `azure_pg_admin` and has `CREATEDB` and `CREATEROLE`; the `azuresu` superuser role is reserved for Microsoft.
130+
- A dedicated operator role is supported: create a user with `CREATEDB`/`CREATEROLE`, optionally add it to `azure_pg_admin` if you need additional capabilities.
131+
- Docs: <https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/security-manage-database-users>
132+
78133
## Installation
79134

80135
### Install Using Helm (Recommended)
81136

82137
The Helm chart for this operator is located in the `charts/ext-postgres-operator` subdirectory. Follow these steps to install:
83138

84139
1. Add the Helm repository:
140+
85141
```bash
86142
helm repo add ext-postgres-operator https://movetokube.github.io/postgres-operator/
87143
```
88144

89145
2. Install the operator:
146+
90147
```bash
91148
helm install -n operators ext-postgres-operator ext-postgres-operator/ext-postgres-operator
92149
```
@@ -121,11 +178,13 @@ To install the operator using Kustomize, follow these steps:
121178
1. Configure Postgres credentials for the operator in `config/default/secret.yaml`.
122179

123180
2. Deploy the operator:
181+
124182
```bash
125183
kubectl kustomize config/default/ | kubectl apply -f -
126184
```
127185

128186
Alternatively, use [Kustomize](https://github.com/kubernetes-sigs/kustomize) directly:
187+
129188
```bash
130189
kustomize build config/default/ | kubectl apply -f -
131190
```
@@ -149,11 +208,11 @@ spec:
149208
dropOnDelete: false # Set to true if you want the operator to drop the database and role when this CR is deleted (optional)
150209
masterRole: test-db-group (optional)
151210
schemas: # List of schemas the operator should create in database (optional)
152-
- stores
153-
- customers
211+
- stores
212+
- customers
154213
extensions: # List of extensions that should be created in the database (optional)
155-
- fuzzystrmatch
156-
- pgcrypto
214+
- fuzzystrmatch
215+
- pgcrypto
157216
```
158217

159218
This creates a database called `test-db` and a role `test-db-group` that is set as the owner of the database.
@@ -173,14 +232,14 @@ metadata:
173232
postgres.db.movetokube.com/instance: POSTGRES_INSTANCE
174233
spec:
175234
role: username
176-
database: my-db # This references the Postgres CR
235+
database: my-db # This references the Postgres CR
177236
secretName: my-secret
178-
privileges: OWNER # Can be OWNER/READ/WRITE
179-
annotations: # Annotations to be propagated to the secrets metadata section (optional)
237+
privileges: OWNER # Can be OWNER/READ/WRITE
238+
annotations: # Annotations to be propagated to the secrets metadata section (optional)
180239
foo: "bar"
181240
labels:
182-
foo: "bar" # Labels to be propagated to the secrets metadata section (optional)
183-
secretTemplate: # Output secrets can be customized using standard Go templates
241+
foo: "bar" # Labels to be propagated to the secrets metadata section (optional)
242+
secretTemplate: # Output secrets can be customized using standard Go templates
184243
PQ_URL: "host={{.Host}} user={{.Role}} password={{.Password}} dbname={{.Database}}"
185244
```
186245

@@ -191,22 +250,22 @@ This creates a user role `username-<hash>` and grants role `test-db-group`, `tes
191250
Two `Postgres` referencing the same database can exist in more than one namespace. The last CR referencing a database will drop the group role and transfer database ownership to the role used by the operator.
192251
Every PostgresUser has a generated Kubernetes secret attached to it, which contains the following data (i.e.):
193252

194-
| Key | Comment |
195-
|----------------------|---------------------|
196-
| `DATABASE_NAME` | Name of the database, same as in `Postgres` CR, copied for convenience |
197-
| `HOST` | PostgreSQL server host (including port number) |
198-
| `URI_ARGS` | URI Args, same as in `Postgres` CR, copied for convenience |
199-
| `PASSWORD` | Autogenerated password for user |
200-
| `ROLE` | Autogenerated role with login enabled (user) |
201-
| `LOGIN` | Same as `ROLE`. In case `POSTGRES_CLOUD_PROVIDER` is set to "Azure", `LOGIN` it will be set to `{role}@{serverName}`, serverName is extracted from `POSTGRES_USER` from operator's config. |
202-
| `POSTGRES_URL` | Connection string for Posgres, could be used for Go applications |
203-
| `POSTGRES_JDBC_URL` | JDBC compatible Postgres URI, formatter as `jdbc:postgresql://{POSTGRES_HOST}/{DATABASE_NAME}` |
204-
| `HOSTNAME` | The PostgreSQL server hostname (without port) |
205-
| `PORT` | The PostgreSQL server port |
206-
207-
| Functions | Meaning |
208-
|----------------|-------------------------------------------------------------------|
209-
| `mergeUriArgs` | Merge any provided uri args with any set in the `Postgres` CR |
253+
| Key | Comment |
254+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
255+
| `DATABASE_NAME` | Name of the database, same as in `Postgres` CR, copied for convenience |
256+
| `HOST` | PostgreSQL server host (including port number) |
257+
| `URI_ARGS` | URI Args, same as in `Postgres` CR, copied for convenience |
258+
| `PASSWORD` | Autogenerated password for user |
259+
| `ROLE` | Autogenerated role with login enabled (user) |
260+
| `LOGIN` | Same as `ROLE`. In case `POSTGRES_CLOUD_PROVIDER` is set to "Azure", `LOGIN` it will be set to `{role}@{serverName}`, serverName is extracted from `POSTGRES_USER` from operator's config. |
261+
| `POSTGRES_URL` | Connection string for Posgres, could be used for Go applications |
262+
| `POSTGRES_JDBC_URL` | JDBC compatible Postgres URI, formatter as `jdbc:postgresql://{POSTGRES_HOST}/{DATABASE_NAME}` |
263+
| `HOSTNAME` | The PostgreSQL server hostname (without port) |
264+
| `PORT` | The PostgreSQL server port |
265+
266+
| Functions | Meaning |
267+
| -------------- | ------------------------------------------------------------- |
268+
| `mergeUriArgs` | Merge any provided uri args with any set in the `Postgres` CR |
210269

211270
### Multiple operator support
212271

@@ -227,7 +286,7 @@ meeting the specific needs of different applications.
227286
Available context:
228287

229288
| Variable | Meaning |
230-
|-------------|------------------------------|
289+
| ----------- | ---------------------------- |
231290
| `.Host` | Database host |
232291
| `.Role` | Generated user/role name |
233292
| `.Database` | Referenced database name |
@@ -243,12 +302,11 @@ can be found [here](https://github.com/kubernetes/client-go/blob/master/README.m
243302
Postgres operator compatibility with Operator SDK version is in the table below
244303

245304
| | Operator SDK version | apiextensions.k8s.io |
246-
|---------------------------|----------------------|----------------------|
247-
| `postgres-operator 0.4.x` | v0.17 | v1beta1 |
248-
| `postgres-operator 1.x.x` | v0.18 | v1 |
249-
| `postgres-operator 2.x.x` | v1.39 | v1 |
250-
| `HEAD` | v1.39 | v1 |
251-
305+
| ------------------------- | -------------------- | -------------------- |
306+
| `postgres-operator 0.4.x` | v0.17 | v1beta1 |
307+
| `postgres-operator 1.x.x` | v0.18 | v1 |
308+
| `postgres-operator 2.x.x` | v1.39 | v1 |
309+
| `HEAD` | v1.39 | v1 |
252310

253311
## Contributing
254312

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616

1717
require (
1818
cel.dev/expr v0.24.0 // indirect
19+
github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
1920
github.com/Masterminds/semver/v3 v3.4.0 // indirect
2021
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
2122
github.com/beorn7/perks v1.0.1 // indirect

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
22
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
3+
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
4+
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
35
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
46
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
57
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
@@ -86,6 +88,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
8688
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
8789
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
8890
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
91+
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
8992
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
9093
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
9194
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=

pkg/postgres/aws.go

Lines changed: 0 additions & 80 deletions
This file was deleted.

pkg/postgres/azure.go

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)