// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package rotation import ( "fmt" "time" "github.com/robfig/cron/v3" ) // RotationOptions is an embeddable struct to capture common rotation // settings between a Secret and Auth type RotationOptions struct { // Schedule holds the info for the framework.Schedule Schedule *RotationSchedule } // RotationJob represents the secret part of a response. type RotationJob struct { RotationOptions // RotationID is the ID returned to the user to manage this secret. // This is generated by Vault core. Any set value will be ignored. // For requests, this will always be blank. RotationID string `sentinel:""` Path string Name string } type RotationJobConfigureRequest struct { Name string MountPoint string ReqPath string RotationSchedule string RotationWindow int RotationPeriod int } func (s *RotationJob) Validate() error { // TODO: validation? return nil } func newRotationJob(rotationSchedule, path, rotationJobName string, rotationWindow, ttl int) (*RotationJob, error) { var cronSc *cron.SpecSchedule if rotationSchedule != "" { var err error cronSc, err = DefaultScheduler.Parse(rotationSchedule) if err != nil { return nil, err } } rs := &RotationSchedule{ Schedule: cronSc, RotationSchedule: rotationSchedule, RotationWindow: time.Duration(rotationWindow) * time.Second, RotationPeriod: time.Duration(ttl) * time.Second, // TODO // decide if next rotation should be set here // or when we actually push item into queue NextVaultRotation: time.Time{}, LastVaultRotation: time.Time{}, } return &RotationJob{ RotationOptions: RotationOptions{ Schedule: rs, }, // Figure out how to get mount info Path: path, Name: rotationJobName, }, nil } // ConfigureRotationJob builds and returns a configured RotationJob for the mount and request with the given schedule. func ConfigureRotationJob(configRequest *RotationJobConfigureRequest) (*RotationJob, error) { mount := configRequest.MountPoint + configRequest.ReqPath var rotationJob *RotationJob if configRequest.RotationSchedule != "" && configRequest.RotationWindow != 0 { var err error rotationJob, err = newRotationJob(configRequest.RotationSchedule, mount, configRequest.Name, configRequest.RotationWindow, 0) if err != nil { return nil, err } } if configRequest.RotationPeriod != 0 { var err error rotationJob, err = newRotationJob("", mount, configRequest.Name, 0, configRequest.RotationPeriod) if err != nil { return nil, err } } // Expect rotation job to exist here if rotationJob == nil { return nil, fmt.Errorf("rotation credential was nil; expected non-nil value") } return rotationJob, nil }