[CMCSMACD-4695] Add a function for syncing users and roles#10
[CMCSMACD-4695] Add a function for syncing users and roles#10hundt-corbalt merged 3 commits intomainfrom
Conversation
This will be used instead of migrations for making sure that a database has the right users and roles.
| return fmt.Errorf("Failed to set password for user %q: %w", user.Username, err) | ||
| } | ||
| } else { | ||
| _, err = tx.Exec( |
There was a problem hiding this comment.
I think here we will also need to grant the rds_iam role per docs.
There was a problem hiding this comment.
I think the caller will pass rds_iam as one of the GrantRoles when they want to use RDS IAM auth
There was a problem hiding this comment.
Here's how it looks on my branch. UsePasswordAuth is false if we detect the Lambda runtime
func ensureUsersAndMigrate(usePasswordAuth bool) error {
users := []migrations.PostgreSQLUser{
{
Username: "reader",
GrantRoles: []string{
postgresReadAllRole,
},
},
{
Username: "writer",
GrantRoles: []string{
postgresReadAllRole,
postgresWriteAllRole,
},
},
}
// When using RDS IAM auth instead of passwords, users also need the rds_iam role
if !usePasswordAuth {
for i := range users {
users[i].GrantRoles = append(users[i].GrantRoles, rdsIAMRole)
}
}
err := migrations.EnsureUsersWithRoles(db, users, usePasswordAuth)
if err != nil {
return fmt.Errorf("error ensuring users with roles: %w", err)
}
return migrations.Migrate(db, schema.AllMigrations())
}There was a problem hiding this comment.
Ah, okay, so that logic is in the caller — makes sense.
There was a problem hiding this comment.
Actually, on second thought, maybe we do want to include that in the function since everyone will want it and it simplifies the caller.
There was a problem hiding this comment.
Check it out now and let me know what you all think.
migrations/user.go
Outdated
| if err != nil { | ||
| return fmt.Errorf("Error starting transaction: %w", err) | ||
| } | ||
| committed := false |
There was a problem hiding this comment.
Do we need the committed flag? This example suggests doing tx.Rollback in all cases since it will be a noop if the transaction has been committed. If we want to print the error from tx.Rollback, we could check that it's not sql.ErrTxDone.
There was a problem hiding this comment.
Huh. The API docs don't really make abundantly clear that this is a good idea, but since this section of the docs suggests it I guess it's fine! Done.
| }() | ||
|
|
||
| for _, user := range users { | ||
| createUserSQL := fmt.Sprintf(` |
There was a problem hiding this comment.
Another option would be to create optimistically and catch an exception (static, less interpolation):
createUserSQL := fmt.Sprintf(`
DO $$
BEGIN
CREATE USER %s;
EXCEPTION
WHEN duplicate_object THEN
NULL;
END
$$;
`, pq.QuoteIdentifier(user.Username),
)
There was a problem hiding this comment.
I do kind of like that, but also reading the docs about exception handling makes me a little nervous. They recommend not doing it if you can avoid it (although I think just for performance reasons?), and there are some semantics regarding transactions that I don't think would matter here but I'm not 100% confident. I'm inclined to leave it as is.
hundt-corbalt
left a comment
There was a problem hiding this comment.
Thanks for the reviews!
migrations/user.go
Outdated
| if err != nil { | ||
| return fmt.Errorf("Error starting transaction: %w", err) | ||
| } | ||
| committed := false |
There was a problem hiding this comment.
Huh. The API docs don't really make abundantly clear that this is a good idea, but since this section of the docs suggests it I guess it's fine! Done.
| }() | ||
|
|
||
| for _, user := range users { | ||
| createUserSQL := fmt.Sprintf(` |
There was a problem hiding this comment.
I do kind of like that, but also reading the docs about exception handling makes me a little nervous. They recommend not doing it if you can avoid it (although I think just for performance reasons?), and there are some semantics regarding transactions that I don't think would matter here but I'm not 100% confident. I'm inclined to leave it as is.
This will be used instead of migrations for making sure that a database has the right users and roles.
Testing: pulled in to dso-metrics repo and added a call to the migrate binary. Verified that it appeared to add users and fix roles as necessary.
PR Checklist
Examples:
To provide feedback on this template, visit https://docs.google.com/document/d/1YfTv7Amyop5G_8w1c2GJ_Mu-70L0KkZHhm9f9umDi3U/edit