- update regular expression for usernames
- add test to allow check for valid usernames
- create pg roles with namespace (if any) appended in rolename
This commit is contained in:
Rafia Sabih 2021-05-27 13:25:54 +02:00
parent f57204721d
commit fd5edea670
4 changed files with 26 additions and 23 deletions

View File

@ -41,7 +41,7 @@ import (
var ( var (
alphaNumericRegexp = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9]*$") alphaNumericRegexp = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9]*$")
databaseNameRegexp = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$") databaseNameRegexp = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
userRegexp = regexp.MustCompile(`^[a-z0-9]([-_a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-_a-z0-9]*[a-z0-9])?)*$`) userRegexp = regexp.MustCompile(`^[a-z0-9,]+\.?[-_a-z0-9,]+[a-z0-9,]$`)
patroniObjectSuffixes = []string{"config", "failover", "sync"} patroniObjectSuffixes = []string{"config", "failover", "sync"}
) )
@ -1093,16 +1093,12 @@ func (c *Cluster) initRobotUsers() error {
if c.shouldAvoidProtectedOrSystemRole(username, "manifest robot role") { if c.shouldAvoidProtectedOrSystemRole(username, "manifest robot role") {
continue continue
} }
name := username
namespace := c.Namespace namespace := c.Namespace
//more than one dot in the username is reported invalid by regexp
if strings.Contains(username, ".") { if strings.Contains(username, ".") {
splits := strings.Split(username, ".") splits := strings.Split(username, ".")
name = splits[1] namespace = splits[0]
if len(splits[0]) > 0 {
namespace = splits[0]
}
username = name
} }
flags, err := normalizeUserFlags(userFlags) flags, err := normalizeUserFlags(userFlags)
@ -1115,18 +1111,14 @@ func (c *Cluster) initRobotUsers() error {
} }
newRole := spec.PgUser{ newRole := spec.PgUser{
Origin: spec.RoleOriginManifest, Origin: spec.RoleOriginManifest,
Name: name, Name: username,
Namespace: namespace, Namespace: namespace,
Password: util.RandomPassword(constants.PasswordLength), Password: util.RandomPassword(constants.PasswordLength),
Flags: flags, Flags: flags,
AdminRole: adminRole, AdminRole: adminRole,
} }
if currentRole, present := c.pgUsers[username]; present { if currentRole, present := c.pgUsers[username]; present {
if namespace == c.pgUsers[username].Namespace { c.pgUsers[username] = c.resolveNameConflict(&currentRole, &newRole)
c.pgUsers[username] = c.resolveNameConflict(&currentRole, &newRole)
} else {
c.pgUsers[username+"."+namespace] = newRole
}
} else { } else {
c.pgUsers[username] = newRole c.pgUsers[username] = newRole
} }

View File

@ -902,7 +902,7 @@ func TestCrossNamespacedSecrets(t *testing.T) {
userNamespaceMap := map[string]string{ userNamespaceMap := map[string]string{
cluster.Namespace: "db_user", cluster.Namespace: "db_user",
"appspace": "db_user", "appspace": "appspace.db_user",
} }
err := cluster.initRobotUsers() err := cluster.initRobotUsers()
@ -912,7 +912,19 @@ func TestCrossNamespacedSecrets(t *testing.T) {
for _, u := range cluster.pgUsers { for _, u := range cluster.pgUsers {
if u.Name != userNamespaceMap[u.Namespace] { if u.Name != userNamespaceMap[u.Namespace] {
t.Errorf("%s: Could not create namespaced user in its correct namespaces", testName) t.Errorf("%s: Could not create namespaced user in its correct namespaces for user %s in namespace %s", testName, u.Name, u.Namespace)
}
}
}
func TestValidUsernames(t *testing.T) {
testName := "test username validity"
invalidUsernames := []string{"_", ".", ".user", "appspace.", "appspace.user.extra", "user_", "_user", "-user", "user-"}
for _, username := range invalidUsernames {
if isValidUsername(username) {
t.Errorf("%s Invalid username is allowed: %s", testName, username)
} }
} }
} }

View File

@ -1581,13 +1581,10 @@ func (c *Cluster) generateSingleUserSecret(namespace string, pgUser spec.PgUser)
if username == constants.ConnectionPoolerUserName { if username == constants.ConnectionPoolerUserName {
lbls = c.connectionPoolerLabels("", false).MatchLabels lbls = c.connectionPoolerLabels("", false).MatchLabels
} }
secret_name := username
if pgUser.Namespace != c.Namespace {
secret_name = username + "." + pgUser.Namespace
}
secret := v1.Secret{ secret := v1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: c.credentialSecretName(secret_name), Name: c.credentialSecretName(username),
Namespace: pgUser.Namespace, Namespace: pgUser.Namespace,
Labels: lbls, Labels: lbls,
Annotations: c.annotationsSet(nil), Annotations: c.annotationsSet(nil),

View File

@ -552,11 +552,13 @@ func (c *Cluster) syncRoles() (err error) {
}() }()
for _, u := range c.pgUsers { for _, u := range c.pgUsers {
pg_role := u.Name
if u.Namespace != c.Namespace { if u.Namespace != c.Namespace {
userNames = append(userNames, u.Name+"."+"u.Namespace") // to avoid the conflict of having multiple users of same name
} else { // but each in different namespace.
userNames = append(userNames, u.Name) pg_role = fmt.Sprintf("%s.%s", u.Name, u.Namespace)
} }
userNames = append(userNames, pg_role)
} }
if needMasterConnectionPooler(&c.Spec) || needReplicaConnectionPooler(&c.Spec) { if needMasterConnectionPooler(&c.Spec) || needReplicaConnectionPooler(&c.Spec) {