// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package rotation import ( "fmt" "time" "github.com/robfig/cron/v3" ) const ( PerformedRegistration = "registration" PerformedDeregistration = "deregistration" ) // 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 MountPoint string Name string } type RotationJobConfigureRequest struct { Name string MountPoint string ReqPath string RotationSchedule string RotationWindow time.Duration RotationPeriod time.Duration } type RotationJobDeregisterRequest struct { MountPoint string ReqPath string } func (s *RotationJob) Validate() error { if s.MountPoint == "" { return fmt.Errorf("MountPoint is required") } if s.Path == "" { return fmt.Errorf("ReqPath is required") } if s.Schedule.RotationSchedule == "" && s.Schedule.RotationPeriod.Seconds() == 0 { return fmt.Errorf("RotationSchedule or RotationPeriod is required to set up rotation job") } return nil } func newRotationJob(configRequest *RotationJobConfigureRequest) (*RotationJob, error) { var cronSc *cron.SpecSchedule if configRequest.RotationSchedule != "" { var err error cronSc, err = DefaultScheduler.Parse(configRequest.RotationSchedule) if err != nil { return nil, err } } rs := &RotationSchedule{ Schedule: cronSc, RotationSchedule: configRequest.RotationSchedule, RotationWindow: configRequest.RotationWindow, RotationPeriod: configRequest.RotationPeriod, NextVaultRotation: time.Time{}, LastVaultRotation: time.Time{}, } return &RotationJob{ RotationOptions: RotationOptions{ Schedule: rs, }, MountPoint: configRequest.MountPoint, Path: configRequest.ReqPath, Name: configRequest.Name, }, nil } // ConfigureRotationJob builds and returns a configured RotationJob for the mount and request with the given schedule. func ConfigureRotationJob(configRequest *RotationJobConfigureRequest) (*RotationJob, error) { rotationJob, err := newRotationJob(configRequest) if err != nil { return nil, err } if err := rotationJob.Validate(); err != nil { return nil, fmt.Errorf("error validating rotation job: %s", 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 }