Skip to content
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

Add redshift database plugin #8299

Merged
merged 4 commits into from
Feb 13, 2020
Merged

Add redshift database plugin #8299

merged 4 commits into from
Feb 13, 2020

Conversation

malnick
Copy link
Contributor

@malnick malnick commented Feb 5, 2020

Adds a database secrets engine for Redshift (postgres 8 compatible).

Because there are no local mocking methods available for Redshift, this plugin leverages a live Redshift cluster and enables test methods using the VAULT_ACC pattern. See comments in header to redshift_test.go for a full disclosure of caveats and setup instructions to run these acceptance tests.

Running these tests locally:

➜  vault/plugins/database/redshift malnick/redshift ✓ VAULT_ACC=1 REDSHIFT_URL=<redacted>:5439/<redacted> REDSHIFT_USER=<redacted> REDSHIFT_PASSWORD=<redacted> TEST_ROTATE_ROOT=1 go test -v
=== RUN   TestPostgreSQL_Initialize
--- PASS: TestPostgreSQL_Initialize (1.41s)
=== RUN   TestPostgreSQL_CreateUser
--- PASS: TestPostgreSQL_CreateUser (5.78s)
=== RUN   TestPostgreSQL_RenewUser
--- PASS: TestPostgreSQL_RenewUser (10.36s)
=== RUN   TestPostgreSQL_RevokeUser
--- PASS: TestPostgreSQL_RevokeUser (8.76s)
=== RUN   TestPostgresSQL_SetCredentials
--- PASS: TestPostgresSQL_SetCredentials (4.82s)
=== RUN   TestPostgreSQL_RotateRootCredentials
rotated root credentials, new user/pass:
username: <redacted>
password: <redacted>
--- PASS: TestPostgreSQL_RotateRootCredentials (1.29s)
PASS
ok      github.com/hashicorp/vault/plugins/database/redshift    33.138s

return nil, errors.New("username and password are required to rotate")
}

rotateStatents := statements
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the var is misspelled, s/rotateStatents/rotateStatements/.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A transient artifact no less https://github.com/hashicorp/vault/blob/master/plugins/database/postgresql/postgresql.go#L452

I'll fix this and PR a fix in the original codebase too. Good catch, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@malnick malnick force-pushed the malnick/redshift branch 5 times, most recently from 4a20e27 to 00726b4 Compare February 11, 2020 22:44
@malnick malnick added this to the 1.4 milestone Feb 11, 2020
Copy link
Contributor

@tyrannosaurus-becks tyrannosaurus-becks left a comment

Choose a reason for hiding this comment

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

Looks great so far! Thanks for working on this!

plugins/database/redshift/redshift.go Show resolved Hide resolved
plugins/database/redshift/redshift.go Outdated Show resolved Hide resolved
plugins/database/redshift/redshift.go Outdated Show resolved Hide resolved
plugins/database/redshift/redshift.go Outdated Show resolved Hide resolved
return "", "", err
}
defer func() {
_ = tx.Rollback()
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
_ = tx.Rollback()
tx.Rollback()

Might as well just quietly drop the error, we do everywhere else. It would be super nice if we could log these, but alas, no logger!

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I have a question about these Rollback statements. I see Rollback is called this way in the mysql plugin. Is the idea basically that if we succeeded doing the transaction, then Rollback just won't work? I'm wondering if maybe we should add a guard that's like "success" that is false by default, and then it gets set to true if the whole transaction succeeded. Then inside the deferred function, it would be like "if !success, rollback" (pseudocode).

plugins/database/redshift/redshift.go Outdated Show resolved Hide resolved
plugins/database/redshift/redshift.go Outdated Show resolved Hide resolved
var lastStmtError error
for _, query := range revocationStmts {
if err := dbtxn.ExecuteDBQuery(ctx, db, nil, query); err != nil {
lastStmtError = err
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be nice to use go-multierror here to return more information about what did and didn't succeed. Commonly used in Vault.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm also wondering about an edge case here. I do believe that revocations get retried if they return an error. So, if we got part way through here, returned an error below, and then a minute later restarted the logic from the top, could we get all the way down? I'm not sure we need to do somersaults to make it work - I notice the other plugins use simplistic logic, just something to think about.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you have a good example of how this is implemented elsewhere? This plugin was largely inspired (and ripped off from) the PG secrets engine. If there's a simpler implementation you had in mind, would love to check it out.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

@tyrannosaurus-becks tyrannosaurus-becks Feb 12, 2020

Choose a reason for hiding this comment

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

You can also treat it like a regular error. So, for instance, in the example above, if right after the loop you wanted to do something like:

if result != nil {
    return
}
... do more stuff

It would totally work like normal.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

plugins/database/redshift/redshift_test.go Show resolved Hide resolved
plugins/database/redshift/redshift_test.go Show resolved Hide resolved
@malnick malnick force-pushed the malnick/redshift branch 2 times, most recently from e0faa53 to 7707d80 Compare February 12, 2020 02:48
@malnick
Copy link
Contributor Author

malnick commented Feb 12, 2020

Thanks @tyrannosaurus-becks - I got to everything but the final question you had in here. I force pushed over the existing commit, here's the results of testing with the latest changes:

=== RUN   TestPostgreSQL_Initialize
--- PASS: TestPostgreSQL_Initialize (1.53s)
=== RUN   TestPostgreSQL_CreateUser
--- PASS: TestPostgreSQL_CreateUser (6.12s)
=== RUN   TestPostgreSQL_RenewUser
--- PASS: TestPostgreSQL_RenewUser (11.38s)
=== RUN   TestPostgreSQL_RevokeUser
--- PASS: TestPostgreSQL_RevokeUser (9.11s)
=== RUN   TestPostgresSQL_SetCredentials
--- PASS: TestPostgresSQL_SetCredentials (5.28s)
=== RUN   TestPostgreSQL_RotateRootCredentials
--- SKIP: TestPostgreSQL_RotateRootCredentials (0.00s)
PASS
ok      github.com/hashicorp/vault/plugins/database/redshift    33.818s```

@tyrannosaurus-becks
Copy link
Contributor

tyrannosaurus-becks commented Feb 12, 2020

Thanks for all your work on this so far!

Would you be willing to merge in master so we can also get a clean look at the build before merging? Also, I notice there are some test failures related to TestPredict_Plugins we need to resolve. Right here, we need to add "redshift-database-plugin".

@malnick
Copy link
Contributor Author

malnick commented Feb 12, 2020

Awesome, thanks @tyrannosaurus-becks - added the plugin to the plugin predict test file and rebased on master.

@malnick malnick force-pushed the malnick/redshift branch 2 times, most recently from 43a12ad to 0497375 Compare February 12, 2020 23:55
@malnick
Copy link
Contributor Author

malnick commented Feb 12, 2020

Thanks for the second pass @tyrannosaurus-becks !

I added the missing db.Close() statements and fixed the remaining feedback. Rebased on master just now, but it'll probably need to happen one more time soon because we're merging code quickly right now.

Latest test results with fixes and rebase:

=== RUN   TestPostgreSQL_Initialize
--- PASS: TestPostgreSQL_Initialize (1.46s)
=== RUN   TestPostgreSQL_CreateUser
--- PASS: TestPostgreSQL_CreateUser (7.50s)
=== RUN   TestPostgreSQL_RenewUser
--- PASS: TestPostgreSQL_RenewUser (11.83s)
=== RUN   TestPostgreSQL_RevokeUser
--- PASS: TestPostgreSQL_RevokeUser (10.41s)
=== RUN   TestPostgresSQL_SetCredentials
--- PASS: TestPostgresSQL_SetCredentials (5.29s)
=== RUN   TestPostgreSQL_RotateRootCredentials
--- SKIP: TestPostgreSQL_RotateRootCredentials (0.00s)
PASS
ok      github.com/hashicorp/vault/plugins/database/redshift    38.058s

Copy link
Contributor

@tyrannosaurus-becks tyrannosaurus-becks left a comment

Choose a reason for hiding this comment

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

Nice! Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants