allow secrets of default users in a different namespace (#1581)
* allow secrets of default users in a different namespace * add warning in case secretNamespace is ignored
This commit is contained in:
parent
47dc0a9aee
commit
282b6d2863
|
|
@ -394,6 +394,8 @@ spec:
|
|||
type: boolean
|
||||
defaultRoles:
|
||||
type: boolean
|
||||
secretNamespace:
|
||||
type: string
|
||||
replicaLoadBalancer: # deprecated
|
||||
type: boolean
|
||||
resources:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -258,7 +291,9 @@ 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
|
||||
|
||||
|
|
@ -266,11 +301,11 @@ 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
|
||||
|
||||
|
|
@ -278,11 +313,11 @@ 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
24
docs/user.md
24
docs/user.md
|
|
@ -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:
|
||||
|
|
@ -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`.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -390,6 +390,8 @@ spec:
|
|||
type: boolean
|
||||
defaultRoles:
|
||||
type: boolean
|
||||
secretNamespace:
|
||||
type: string
|
||||
replicaLoadBalancer: # deprecated
|
||||
type: boolean
|
||||
resources:
|
||||
|
|
|
|||
|
|
@ -573,6 +573,9 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{
|
|||
},
|
||||
},
|
||||
},
|
||||
"secretNamespace": {
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue