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

secrets/database: advanced TTL management for static roles #22484

Merged
merged 18 commits into from
Aug 24, 2023

Conversation

fairclothjm
Copy link
Contributor

This PR enables schedule-based auto-rotation of static roles for the Database Secrets engine. This rotation mechanism will be “embedded” in the Database Secrets engine and will not be reusable by other engines. In particular, this approach allows for exclusion windows (e.g. market hours) in which automatic rotations will not occur.

We add a new field rotation_schedule to the create static role endpoint. This field can be set with a cron-style string that will define the schedule on which rotations should occur:

// set rotations to occur on Saturday at 00:00
vault write database/static-roles/test-role \
    db_name=postgresql \
    username="vault" \
    rotation_schedule="0 0 * * SAT"

Additionally, we add a new rotation_window field on the create static role endpoint. It will be optional when rotation_schedule is set and disallowed when rotation_period is set. This field can be set with a time duration string with a minimum of 1 hour. The rotation_window will define the window of time in which rotations are allowed to occur starting from a given rotation_schedule:

// set rotations to occur on Saturday at 00:00, but allow up to Sunday at 23:59
vault write database/static-roles/test-role \
    db_name=postgresql \
    username="vault" \
    rotation_schedule="0 0 * * SAT" \
    rotation_window="24h"

@fairclothjm fairclothjm requested a review from a team as a code owner August 21, 2023 21:45
@fairclothjm fairclothjm requested review from a team and removed request for a team August 21, 2023 21:45
@github-actions github-actions bot added the hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed label Aug 21, 2023
@fairclothjm fairclothjm added this to the 1.15 milestone Aug 21, 2023
@github-actions
Copy link

Build Results:
All builds succeeded! ✅

@github-actions
Copy link

github-actions bot commented Aug 21, 2023

CI Results:
All Go tests succeeded! ✅

// TODO(JM): don't allow seconds in production, this is helpful for
// development/testing though
parser := cron.NewParser(
cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.DowOptional,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suggested change
cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.DowOptional,
cron.Second | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow,

fairclothjm and others added 18 commits August 22, 2023 12:36
* handle mutual exclusion of rotation fields

* fix import
* adv ttl mgmt: add rotation_window field

* do some rotation_window validation and add unit tests
#22341)

* general cleanup and refactor rotation type checks

* make NextRotationTime account for the rotation type

* add comments
* add unit tests to handle mutual exclusion

* revert rotation_test.go and add missing test case to path_roles_test.go
* support manual rotation for schedule based roles

* update description and naming
* consider rotation window

ensure rotations only occur within a rotation window for schedule-based
rotations

* use helper method to set priority in rotateCredential

* fix bug with priority check

* remove test for now

* add and remove comments
* update read static-creds endpoint to include correct resp data

* return rotation_window if set

* update
Copy link
Member

@austingebauer austingebauer left a comment

Choose a reason for hiding this comment

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

Looks good to me! Nice job on this @fairclothjm and @MilenaHC! 🚀

} else if rotationScheduleChanged {
next := role.StaticAccount.Schedule.Next(lvr)
b.logger.Debug("init priority for Schedule", "lvr", lvr, "next", next)
item.Priority = role.StaticAccount.Schedule.Next(lvr).Unix()
Copy link
Member

Choose a reason for hiding this comment

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

nit: any good reason to not use next.Unix()?

Comment on lines +689 to +690
_, rotationPeriodChanged := data.Raw["rotation_period"]
_, rotationScheduleChanged := data.Raw["rotation_schedule"]
Copy link
Member

Choose a reason for hiding this comment

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

Curious if there is a difference between these values from data.Raw and rotationPeriodOk / rotationScheduleOk from above?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, good catch!

Comment on lines +563 to +564
rotationSchedule := data.Get("rotation_schedule").(string)
rotationScheduleOk := rotationSchedule != ""
Copy link
Member

Choose a reason for hiding this comment

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

nit: I might be missing something but curious if there is a reason GetOk didn't work for rotation_schedule?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this line was added a bit later when we realized we needed the boolean. Will update, thanks!

Copy link
Contributor

@vinay-gopalan vinay-gopalan left a comment

Choose a reason for hiding this comment

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

LGTM! Had a couple questions :)

builtin/logical/database/path_roles.go Show resolved Hide resolved
@@ -127,6 +128,13 @@ func Backend(conf *logical.BackendConfig) *databaseBackend {
b.connections = syncmap.NewSyncMap[string, *dbPluginInstance]()
b.queueCtx, b.cancelQueueCtx = context.WithCancel(context.Background())
b.roleLocks = locksutil.CreateLocks()

// TODO(JM): don't allow seconds in production, this is helpful for
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we going to remove supporting seconds altogether or are we going to add some safeguards so they can still be run in our CI tests but users can't add them in production? From the tests set up below, I can definitely see us keeping seconds around just for our testing

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, also just saw Milena's PR to only allow seconds in testing, so this comment should be resolved when that PR is merged 😅

@fairclothjm
Copy link
Contributor Author

@austingebauer @vinay-gopalan Thanks for the reviews! I am going to address your comments in a follow up PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hashicorp-contributed-pr If the PR is HashiCorp (i.e. not-community) contributed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants