Skip to content

Commit 8719ac7

Browse files
tjmoore4Jonathan S. Katz
authored andcommitted
Use autogenerated pgouser password if not set
Currently, the PostgreSQL Operator requires a pgouser's password to be set during the installation process. This update allows for the password to be unset during installation, and, during Operator initialization, any pgouser that currently has an empty password will be given an autogenerated password, stored in the relevant pgouser secret. Issue: [ch9510]
1 parent 12a62ce commit 8719ac7

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

docs/content/installation/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Operator.
5353
| `namespace_mode` | dynamic | | Determines which namespace permissions are assigned to the PostgreSQL Operator using a ClusterRole. Options: `dynamic`, `readonly`, and `disabled` |
5454
| `pgbadgerport` | 10000 | **Required** | Set to configure the default port used to connect to pgbadger. |
5555
| `pgo_add_os_ca_store` | false | **Required** | When true, includes system default certificate authorities. |
56-
| `pgo_admin_password` | examplepassword | **Required** | Configures the pgo administrator password. |
56+
| `pgo_admin_password` | examplepassword | | Configures the pgo administrator password. When blank, a random password is generated. |
5757
| `pgo_admin_perms` | * | **Required** | Sets the access control rules provided by the PostgreSQL Operator RBAC resources for the PostgreSQL Operator administrative account that is created by this installer. Defaults to allowing all of the permissions, which is represented with the * |
5858
| `pgo_admin_role_name` | pgoadmin | **Required** | Sets the name of the PostgreSQL Operator role that is utilized for administrative operations performed by the PostgreSQL Operator. |
5959
| `pgo_admin_username` | admin | **Required** | Configures the pgo administrator username. |

installers/ansible/roles/pgo-operator/templates/pgouser-admin.yaml.j2

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ metadata:
1010
namespace: {{ pgo_operator_namespace }}
1111
type: Opaque
1212
data:
13-
password: {{ pgo_admin_password | b64encode }}
14-
username: {{ pgo_admin_username | b64encode }}
15-
roles: {{ pgo_admin_role_name | b64encode }}
13+
password: '{{ pgo_admin_password | b64encode }}'
14+
username: '{{ pgo_admin_username | b64encode }}'
15+
roles: '{{ pgo_admin_role_name | b64encode }}'

installers/ansible/roles/pgo-preflight/tasks/check_vars.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
- pgo_operator_namespace
99
- pgo_installation_name
1010
- pgo_admin_username
11-
- pgo_admin_password
1211
- pgo_admin_role_name
1312
- pgo_admin_perms
1413
- ccp_image_prefix

internal/apiserver/root.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ import (
3131
"github.com/crunchydata/postgres-operator/internal/kubeapi"
3232
"github.com/crunchydata/postgres-operator/internal/ns"
3333
"github.com/crunchydata/postgres-operator/internal/tlsutil"
34+
"github.com/crunchydata/postgres-operator/internal/util"
3435
log "github.com/sirupsen/logrus"
3536
corev1 "k8s.io/api/core/v1"
3637
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
38+
"k8s.io/apimachinery/pkg/types"
3739
"k8s.io/client-go/kubernetes"
3840
"k8s.io/client-go/rest"
3941
)
@@ -133,6 +135,11 @@ func Initialize() {
133135

134136
initConfig()
135137

138+
// look through all the pgouser secrets in the Operator's
139+
// namespace and set a generated password for any that currently
140+
// have an empty password set
141+
setRandomPgouserPasswords()
142+
136143
if err := setNamespaceOperatingMode(); err != nil {
137144
log.Error(err)
138145
os.Exit(2)
@@ -160,7 +167,6 @@ func connectToKube() {
160167
}
161168

162169
func initConfig() {
163-
164170
AuditFlag = Pgo.Pgo.Audit
165171
if AuditFlag {
166172
log.Info("audit flag is set to true")
@@ -305,6 +311,7 @@ func Authn(perm string, w http.ResponseWriter, r *http.Request) (string, error)
305311
// this function currently encapsulates authorization as well, and this is
306312
// the call where we get the username to check the RBAC settings
307313
username, password, authOK := r.BasicAuth()
314+
308315
if AuditFlag {
309316
log.Infof("[audit] %s username=[%s] method=[%s] ip=[%s] ok=[%t] ", perm, username, r.Method, r.RemoteAddr, authOK)
310317
}
@@ -500,6 +507,56 @@ func setNamespaceOperatingMode() error {
500507
return nil
501508
}
502509

510+
// setRandomPgouserPasswords looks through the pgouser secrets in the Operator's
511+
// namespace. If any have an empty password, it generates a random password,
512+
// Base64 encodes it, then stores it in the relevant PGO user's secret
513+
func setRandomPgouserPasswords() {
514+
ctx := context.TODO()
515+
516+
selector := "pgo-pgouser=true,vendor=crunchydata"
517+
secrets, err := Clientset.CoreV1().Secrets(PgoNamespace).
518+
List(ctx, metav1.ListOptions{LabelSelector: selector})
519+
if err != nil {
520+
log.Warnf("Could not get pgouser secrets in namespace: %s", PgoNamespace)
521+
return
522+
}
523+
524+
for _, secret := range secrets.Items {
525+
// check if password is set. if it is, continue.
526+
if len(secret.Data["password"]) > 0 {
527+
continue
528+
}
529+
530+
log.Infof("Password in pgouser secret %s for operator installation %s in namespace %s is empty. "+
531+
"Setting a generated password.", secret.Name, InstallationName, PgoNamespace)
532+
533+
// generate the password using the default password length
534+
generatedPassword, err := util.GeneratePassword(util.DefaultGeneratedPasswordLength)
535+
536+
if err != nil {
537+
log.Errorf("Could not generate password for pgouser secret %s for operator installation %s in "+
538+
"namespace %s", secret.Name, InstallationName, PgoNamespace)
539+
continue
540+
}
541+
542+
// create the password patch
543+
patch, err := kubeapi.NewMergePatch().Add("stringData", "password")(generatedPassword).Bytes()
544+
545+
if err != nil {
546+
log.Errorf("Could not generate password patch for pgouser secret %s for operator installation "+
547+
"%s in namespace %s", secret.Name, InstallationName, PgoNamespace)
548+
continue
549+
}
550+
551+
// patch the pgouser secret with the new password
552+
if _, err := Clientset.CoreV1().Secrets(PgoNamespace).Patch(ctx, secret.Name, types.MergePatchType,
553+
patch, metav1.PatchOptions{}); err != nil {
554+
log.Errorf("Could not patch pgouser secret %s with generated password for operator installation "+
555+
"%s in namespace %s", secret.Name, InstallationName, PgoNamespace)
556+
}
557+
}
558+
}
559+
503560
// NamespaceOperatingMode returns the namespace operating mode for the current Operator
504561
// installation, which is stored in the "namespaceOperatingMode" variable
505562
func NamespaceOperatingMode() ns.NamespaceOperatingMode {

0 commit comments

Comments
 (0)