Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions charts/postgres-operator/crds/postgresqls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ spec:
type: boolean
defaultRoles:
type: boolean
secretNamespace:
type: string
replicaLoadBalancer: # deprecated
type: boolean
resources:
Expand Down
47 changes: 41 additions & 6 deletions docs/reference/cluster_manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ These parameters are grouped directly under the `spec` key in the manifest.
`SUPERUSER`, `REPLICATION`, `INHERIT`, `LOGIN`, `NOLOGIN`, `CREATEROLE`,
`CREATEDB`, `BYPASSURL`. A login user is created by default unless NOLOGIN is
specified, in which case the operator creates a role. One can specify empty
flags by providing a JSON empty array '*[]*'. Optional.
flags by providing a JSON empty array '*[]*'. If the config option
`enable_cross_namespace_secrets` is enabled you can specify the namespace in
the user name in the form `{namespace}.{username}` and the operator will
create the K8s secret in that namespace. The part after the first `.` is
considered to be the user name. Optional.

* **databases**
a map of database names to database owners for the databases that should be
Expand Down Expand Up @@ -185,6 +189,35 @@ These parameters are grouped directly under the `spec` key in the manifest.
If you set the `all` special item, it will be mounted in all containers (postgres + sidecars).
Else you can set the list of target containers in which the additional volumes will be mounted (eg : postgres, telegraf)

## Prepared Databases

The operator can create databases with default owner, reader and writer roles
without the need to specifiy them under `users` or `databases` sections. Those
parameters are grouped under the `preparedDatabases` top-level key. For more
information, see [user docs](../user.md#prepared-databases-with-roles-and-default-privileges).

* **defaultUsers**
The operator will always create default `NOLOGIN` roles for defined prepared
databases, but if `defaultUsers` is set to `true` three additional `LOGIN`
roles with `_user` suffix will get created. Default is `false`.

* **extensions**
map of extensions with target database schema that the operator will install
in the database. Optional.

* **schemas**
map of schemas that the operator will create. Optional - if no schema is
listed, the operator will create a schema called `data`. Under each schema
key, it can be defined if `defaultRoles` (NOLOGIN) and `defaultUsers` (LOGIN)
roles shall be created that have schema-exclusive privileges. Both flags are
set to `false` by default.

* **secretNamespace**
for each default LOGIN role the operator will create a secret. You can
specify the namespace in which these secrets will get created, if
`enable_cross_namespace_secrets` is set to `true` in the config. Otherwise,
the cluster namespace is used.

## Postgres parameters

Those parameters are grouped under the `postgresql` top-level key, which is
Expand Down Expand Up @@ -258,31 +291,33 @@ explanation of `ttl` and `loop_wait` parameters.

Those parameters define [CPU and memory requests and limits](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/)
for the Postgres container. They are grouped under the `resources` top-level
key with subgroups `requests` and `limits`.
key with subgroups `requests` and `limits`. The whole section is optional,
however if you specify a request or limit you have to define everything
(unless you are not modifying the default CRD schema validation).

### Requests

CPU and memory requests for the Postgres container.

* **cpu**
CPU requests for the Postgres container. Optional, overrides the
`default_cpu_requests` operator configuration parameter. Optional.
`default_cpu_requests` operator configuration parameter.

* **memory**
memory requests for the Postgres container. Optional, overrides the
`default_memory_request` operator configuration parameter. Optional.
`default_memory_request` operator configuration parameter.

### Limits

CPU and memory limits for the Postgres container.

* **cpu**
CPU limits for the Postgres container. Optional, overrides the
`default_cpu_limits` operator configuration parameter. Optional.
`default_cpu_limits` operator configuration parameter.

* **memory**
memory limits for the Postgres container. Optional, overrides the
`default_memory_limits` operator configuration parameter. Optional.
`default_memory_limits` operator configuration parameter.

## Parameters defining how to clone the cluster from another one

Expand Down
4 changes: 1 addition & 3 deletions docs/reference/operator_parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,7 @@ configuration they are grouped under the `kubernetes` key.
* **enable_cross_namespace_secrets**
To allow secrets in a different namespace other than the Postgres cluster
namespace. Once enabled, specify the namespace in the user name under the
`users` section in the form `{namespace}.{username}`. The operator will then
create the user secret in that namespace. The part after the first `.` is
considered to be the user name. The default is `false`.
`users` section in the form `{namespace}.{username}`. The default is `false`.

* **enable_init_containers**
global option to allow for creating init containers in the cluster manifest to
Expand Down
24 changes: 19 additions & 5 deletions docs/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ secret, without ever sharing it outside of the cluster.
At the moment it is not possible to define membership of the manifest role in
other roles.

To define the secrets for the users in a different namespace than that of the cluster,
one can set `enable_cross_namespace_secret` and declare the namespace for the
secrets in the manifest in the following manner,
To define the secrets for the users in a different namespace than that of the
cluster, one can set `enable_cross_namespace_secret` and declare the namespace
for the secrets in the manifest in the following manner,

```yaml
spec:
Expand All @@ -150,7 +150,8 @@ spec:
appspace.db_user:
- createdb
```
Here, anything before the first dot is taken as the namespace and the text after

Here, anything before the first dot is considered the namespace and the text after
the first dot is the username. Also, the postgres roles of these usernames would
be in the form of `namespace.username`.

Expand Down Expand Up @@ -520,7 +521,7 @@ Then, the schemas are owned by the database owner, too.

The roles described in the previous paragraph can be granted to LOGIN roles from
the `users` section in the manifest. Optionally, the Postgres Operator can also
create default LOGIN roles for the database an each schema individually. These
create default LOGIN roles for the database and each schema individually. These
roles will get the `_user` suffix and they inherit all rights from their NOLOGIN
counterparts. Therefore, you cannot have `defaultRoles` set to `false` and enable
`defaultUsers` at the same time.
Expand Down Expand Up @@ -550,6 +551,19 @@ Default access privileges are also defined for LOGIN roles on database and
schema creation. This means they are currently not set when `defaultUsers`
(or `defaultRoles` for schemas) are enabled at a later point in time.

For all LOGIN roles the operator will create K8s secrets in the namespace
specified in `secretNamespace`, if `enable_cross_namespace_secret` is set to
`true` in the config. Otherwise, they are created in the same namespace like
the Postgres cluster.

```yaml
spec:
preparedDatabases:
foo:
defaultUsers: true
secretNamespace: appspace
```

### Schema `search_path` for default roles

The schema [`search_path`](https://www.postgresql.org/docs/13/ddl-schemas.html#DDL-SCHEMAS-PATH)
Expand Down
2 changes: 2 additions & 0 deletions manifests/postgresql.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ spec:
type: boolean
defaultRoles:
type: boolean
secretNamespace:
type: string
replicaLoadBalancer: # deprecated
type: boolean
resources:
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/acid.zalan.do/v1/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,9 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{
},
},
},
"secretNamespace": {
Type: "string",
},
},
},
},
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/acid.zalan.do/v1/postgresql_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type PreparedDatabase struct {
PreparedSchemas map[string]PreparedSchema `json:"schemas,omitempty"`
DefaultUsers bool `json:"defaultUsers,omitempty" defaults:"false"`
Extensions map[string]string `json:"extensions,omitempty"`
SecretNamespace string `json:"secretNamespace,omitempty"`
}

// PreparedSchema describes elements to be bootstrapped per schema
Expand Down
21 changes: 15 additions & 6 deletions pkg/cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -1077,11 +1077,11 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
}

// default roles per database
if err := c.initDefaultRoles(defaultRoles, "admin", preparedDbName, searchPath.String()); err != nil {
if err := c.initDefaultRoles(defaultRoles, "admin", preparedDbName, searchPath.String(), preparedDB.SecretNamespace); err != nil {
return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err)
}
if preparedDB.DefaultUsers {
if err := c.initDefaultRoles(defaultUsers, "admin", preparedDbName, searchPath.String()); err != nil {
if err := c.initDefaultRoles(defaultUsers, "admin", preparedDbName, searchPath.String(), preparedDB.SecretNamespace); err != nil {
return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err)
}
}
Expand All @@ -1092,14 +1092,14 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
if err := c.initDefaultRoles(defaultRoles,
preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName,
constants.DefaultSearchPath+", "+preparedSchemaName); err != nil {
constants.DefaultSearchPath+", "+preparedSchemaName, preparedDB.SecretNamespace); err != nil {
return fmt.Errorf("could not initialize default roles for database schema %s: %v", preparedSchemaName, err)
}
if preparedSchema.DefaultUsers {
if err := c.initDefaultRoles(defaultUsers,
preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName,
constants.DefaultSearchPath+", "+preparedSchemaName); err != nil {
constants.DefaultSearchPath+", "+preparedSchemaName, preparedDB.SecretNamespace); err != nil {
return fmt.Errorf("could not initialize default users for database schema %s: %v", preparedSchemaName, err)
}
}
Expand All @@ -1109,10 +1109,19 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
return nil
}

func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix string, searchPath string) error {
func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix, searchPath, secretNamespace string) error {

for defaultRole, inherits := range defaultRoles {

namespace := c.Namespace
//if namespaced secrets are allowed
if secretNamespace != "" {
if c.Config.OpConfig.EnableCrossNamespaceSecret {
namespace = secretNamespace
} else {
c.logger.Warn("secretNamespace ignored because enable_cross_namespace_secret set to false. Creating secrets in cluster namespace.")
}
}
roleName := prefix + defaultRole

flags := []string{constants.RoleFlagNoLogin}
Expand All @@ -1135,7 +1144,7 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix
newRole := spec.PgUser{
Origin: spec.RoleOriginBootstrap,
Name: roleName,
Namespace: c.Namespace,
Namespace: namespace,
Password: util.RandomPassword(constants.PasswordLength),
Flags: flags,
MemberOf: memberOf,
Expand Down