Skip to content

[WIP] Extend infrastructure roles handling #1064

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Aug 5, 2020

Conversation

erthalion
Copy link
Contributor

Postgres Operator uses infrastructure roles to provide access to a
database for external users e.g. for monitoring purposes. Such
infrastructure roles are expected to be present in the form of k8s
secrets with the following content:

inrole1: some_encrypted_role
password1: some_encrypted_password
user1: some_entrypted_name

inrole2: some_encrypted_role
password2: some_encrypted_password
user2: some_entrypted_name

The format of this content is implied implicitely and not flexible
enough. In case if we do not have possibility to change the format of a
secret we want to use in the Operator, we need to recreate it in this
format.

To address this lets make the format of secret content explicitely. The
idea is to introduce a new configuration option for the Operator.

infrastructure_roles_secrets:
- secret: k8s_secret_name
  name: some_encrypted_name
  password: some_encrypted_password
  role: some_encrypted_role

- secret: k8s_secret_name
  name: some_encrypted_name
  password: some_encrypted_password
  role: some_encrypted_role

This would allow Operator to use any avalable secrets to prepare
infrastructure roles. To make it backward compatible simulate the old
behaviour if the new option is not present.

The new configuration option is intended be used mainly from CRD, but
it's also available via Operator ConfigMap in a limited fashion. For
ConfigMap one can put there only a string with one secret definition in
the following format (as a string):

infrastructure_roles_secret_name: |
    secret: k8s_secret_name,
    name: some_encrypted_name,
    password: some_encrypted_password,
    role: some_encrypted_role

@erthalion erthalion force-pushed the feature/infrastructure-roles-extension branch 3 times, most recently from 6c962e9 to bd57694 Compare July 22, 2020 10:34
erthalion and others added 2 commits July 22, 2020 12:36
Postgres Operator uses infrastructure roles to provide access to a
database for external users e.g. for monitoring purposes. Such
infrastructure roles are expected to be present in the form of k8s
secrets with the following content:

    inrole1: some_encrypted_role
    password1: some_encrypted_password
    user1: some_entrypted_name

    inrole2: some_encrypted_role
    password2: some_encrypted_password
    user2: some_entrypted_name

The format of this content is implied implicitely and not flexible
enough. In case if we do not have possibility to change the format of a
secret we want to use in the Operator, we need to recreate it in this
format.

To address this lets make the format of secret content explicitely. The
idea is to introduce a new configuration option for the Operator.

    infrastructure_roles_secrets:
    - secret: k8s_secret_name
      name: some_encrypted_name
      password: some_encrypted_password
      role: some_encrypted_role

    - secret: k8s_secret_name
      name: some_encrypted_name
      password: some_encrypted_password
      role: some_encrypted_role

This would allow Operator to use any avalable secrets to prepare
infrastructure roles. To make it backward compatible simulate the old
behaviour if the new option is not present.

The new configuration option is intended be used mainly from CRD, but
it's also available via Operator ConfigMap in a limited fashion. For
ConfigMap one can put there only a string with one secret definition in
the following format (as a string):

    infrastructure_roles_secret_name: |
        secret: k8s_secret_name,
        name: some_encrypted_name,
        password: some_encrypted_password,
        role: some_encrypted_role
type InfrastructureRole struct {
// Name of a secret which describes the role, and optionally name of a
// configmap with an extra information
Secret spec.NamespacedName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this should also be called SecretName to be clear it's just a reference. What is the common way in K8s to name reference to other resources?

// To be compatible with the legacy implementation we need to return nil if
// the provided secret name is empty. The equivalent situation in the
// current implementation is an empty rolesSecrets slice or all its items
// are empty.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm overlooking something, but doesn't getInfrastructureRoleDefinitions set the secret name when the old format is used? Can it be empty then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it sets if from the old field, which apparently could be empty (judging from the previous tests implementation).

}
delete(secretData, key)

roles = append(roles, t)
Copy link
Member

@FxKu FxKu Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this part here is gone? Only checked in the else part.

if t.Name != "" {
	if t.Password == "" {
		c.logger.Warningf("infrastructure role %q has no password defined and is ignored", t.Name)
		continue
	}
	result[t.Name] = t
}

newFormatConfigmap := &v1.ConfigMap{}
newFormatConfigmap.Name = "testcluster"
newFormatConfigmap.Data = map[string]string{
"new-foobar": "{}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we also test with fields like user_flags to test if a proper pgUser struct is marshalled?

@erthalion erthalion force-pushed the feature/infrastructure-roles-extension branch from 0636883 to d5b7c94 Compare July 27, 2020 08:35
Postgres Operator uses infrastructure roles to provide access to a
database for external users e.g. for monitoring purposes. Such
infrastructure roles are expected to be present in the form of k8s
secrets with the following content:

    inrole1: some_encrypted_role
    password1: some_encrypted_password
    user1: some_entrypted_name

    inrole2: some_encrypted_role
    password2: some_encrypted_password
    user2: some_entrypted_name

The format of this content is implied implicitely and not flexible
enough. In case if we do not have possibility to change the format of a
secret we want to use in the Operator, we need to recreate it in this
format.

To address this lets make the format of secret content explicitely. The
idea is to introduce a new configuration option for the Operator.

    infrastructure_roles_secrets:
    - secret: k8s_secret_name
      name: some_encrypted_name
      password: some_encrypted_password
      role: some_encrypted_role

    - secret: k8s_secret_name
      name: some_encrypted_name
      password: some_encrypted_password
      role: some_encrypted_role

This would allow Operator to use any avalable secrets to prepare
infrastructure roles. To make it backward compatible simulate the old
behaviour if the new option is not present.

The new configuration option is intended be used mainly from CRD, but
it's also available via Operator ConfigMap in a limited fashion. For
ConfigMap one can put there only a string with one secret definition in
the following format (as a string):

    infrastructure_roles_secret_name: |
        secret: k8s_secret_name,
        name: some_encrypted_name,
        password: some_encrypted_password,
        role: some_encrypted_role
// configmap with an extra information
SecretName spec.NamespacedName

Name string
Copy link
Member

@FxKu FxKu Jul 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this field better be called User? I got confused while configuring the infrastructure_roles_secret field in the config map (where I used user:<username> first, and then name:user and finally name:<username>).

name := strings.TrimSpace(values[0])
value := strings.TrimSpace(values[1])

switch name {
Copy link
Member

@FxKu FxKu Jul 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you would also extract the secretname key here, too, we could mark the infrastructure_roles_secret_name as deprecated and one could solely rely on infrastructure_roles_secrets. The surrounding conditions need to be adapted then:

if c.opConfig.InfrastructureRolesSecretName == emptyName {
  if c.opConfig.InfrastructureRolesDefs == "" {
    return rolesDefs
  } else {
    do extraction from configmap

} else {
  older format
} 

Now, it's a bit confusing that you have to use both infrastructure_roles... config options together when dealing with configmap. But if you do the same for CRD only the old format is used and the new format is ignored (see if c.opConfig.InfrastructureRolesSecretName == emptyName)

@erthalion erthalion force-pushed the feature/infrastructure-roles-extension branch 3 times, most recently from a71f571 to 1805b83 Compare August 3, 2020 12:14
@erthalion erthalion force-pushed the feature/infrastructure-roles-extension branch 5 times, most recently from b7f018b to 602f26c Compare August 3, 2020 13:42
erthalion and others added 3 commits August 3, 2020 15:45
This parameter should be a detail of internal implementation and only
facilitate compatibility with the legacy behaviour if we want to
recommend only using the new format.
and specify the keys for extract credentials from them such as user name,
password and role membership. For the configmap this has to be a string
which allows referencing only one infrastructure roles secret.
The default is empty.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am finding first part of the sentence hard to follow, array of infrastructure role definitions that references existing secrets and specify the keys to extract credentials from them such as user name, password, and role membership, does this phrasing says what you meant.
Also, when you mention for the configmap, can it be specified somewhere else also...?
Also, is it role's secret...?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's roles in this case. Did some rephrasing.

docs/user.md Outdated
parameter where you can reference multiple existing secrets. Prior to `v1.6.0`
the operator could only reference one secret with the
`infrastructure_roles_secret_name` option. However, this secret could contain
multiple roles using the same set of keys with incremented indexes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indexes? Does it refers to array indexes? Does it need to be mentioned like this...?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slightly rewritten, hopefully clearer now ... I thought the example shows it nicely what I'm referring to

@erthalion
Copy link
Contributor Author

👍

1 similar comment
@FxKu
Copy link
Member

FxKu commented Aug 5, 2020

👍

@erthalion erthalion merged commit 7cf2fae into master Aug 5, 2020
@FxKu FxKu added this to the 1.6 milestone Dec 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants