mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-22 23:21:08 +02:00
* add ce side code and stubs * add changelog * style refactor * try to use APIPath as mount point instead of request field * fix linter * return a response struct instead of a pure timestamp * add issue time to response * add ttl to GetRotationInformation response * rename field for clarity * update ttl to just seconds * rename next and last rotation time field; describe what they are * rename function * catch up to ent PR * fix patch merge mistake
153 lines
4.1 KiB
Go
153 lines
4.1 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package mock
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
|
"github.com/hashicorp/vault/sdk/helper/automatedrotationutil"
|
|
"github.com/hashicorp/vault/sdk/logical"
|
|
"github.com/hashicorp/vault/sdk/rotation"
|
|
)
|
|
|
|
// pathConfig is used to test auto rotation.
|
|
func pathConfig(b *backend) *framework.Path {
|
|
p := &framework.Path{
|
|
Pattern: "config",
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"fail_rotate": {
|
|
Type: framework.TypeBool,
|
|
},
|
|
},
|
|
Callbacks: map[logical.Operation]framework.OperationFunc{
|
|
logical.CreateOperation: b.pathConfigUpdate,
|
|
logical.UpdateOperation: b.pathConfigUpdate,
|
|
logical.ReadOperation: b.pathConfigRead,
|
|
},
|
|
ExistenceCheck: b.pathConfigExistenceCheck,
|
|
}
|
|
automatedrotationutil.AddAutomatedRotationFields(p.Fields)
|
|
return p
|
|
}
|
|
|
|
func (b *backend) pathConfigUpdate(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
conf, err := b.configEntry(ctx, req.Storage)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if conf == nil {
|
|
conf = &config{}
|
|
}
|
|
|
|
if failRotateRaw, ok := data.GetOk("fail_rotate"); ok {
|
|
conf.FailRotate = failRotateRaw.(bool)
|
|
}
|
|
|
|
if err := conf.ParseAutomatedRotationFields(data); err != nil {
|
|
return logical.ErrorResponse(err.Error()), nil
|
|
}
|
|
|
|
if conf.ShouldDeregisterRotationJob() {
|
|
deregisterReq := &rotation.RotationJobDeregisterRequest{
|
|
MountPoint: req.MountPoint,
|
|
ReqPath: req.Path,
|
|
}
|
|
|
|
b.Logger().Debug("Deregistering rotation job", "mount", req.MountPoint+req.Path)
|
|
if err := b.System().DeregisterRotationJob(ctx, deregisterReq); err != nil {
|
|
return logical.ErrorResponse("error deregistering rotation job: %s", err), nil
|
|
}
|
|
} else if conf.ShouldRegisterRotationJob() {
|
|
cfgReq := &rotation.RotationJobConfigureRequest{
|
|
MountPoint: req.MountPoint,
|
|
ReqPath: req.Path,
|
|
RotationSchedule: conf.RotationSchedule,
|
|
RotationWindow: conf.RotationWindow,
|
|
RotationPeriod: conf.RotationPeriod,
|
|
}
|
|
|
|
b.Logger().Debug("Registering rotation job", "mount", req.MountPoint+req.Path)
|
|
if _, err = b.System().RegisterRotationJob(ctx, cfgReq); err != nil {
|
|
return logical.ErrorResponse("error registering rotation job: %s", err), nil
|
|
}
|
|
}
|
|
|
|
entry, err := logical.StorageEntryJSON("config", conf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := req.Storage.Put(ctx, entry); err != nil {
|
|
return nil, err
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
conf, err := b.configEntry(ctx, req.Storage)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if conf == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
configData := map[string]interface{}{}
|
|
conf.PopulateAutomatedRotationData(configData)
|
|
|
|
if conf.HasNonzeroRotationValues() {
|
|
resp, err := b.System().GetRotationInformation(ctx, &rotation.RotationInfoRequest{ReqPath: req.Path})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp != nil {
|
|
configData["expire_time"] = resp.NextVaultRotation.Unix()
|
|
configData["creation_time"] = resp.LastVaultRotation.Unix()
|
|
configData["ttl"] = int64(resp.TTL)
|
|
}
|
|
}
|
|
|
|
return &logical.Response{
|
|
Data: configData,
|
|
}, nil
|
|
}
|
|
|
|
func (b *backend) pathConfigDelete(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
|
if err := req.Storage.Delete(ctx, "config"); err != nil {
|
|
return nil, err
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (b *backend) pathConfigExistenceCheck(ctx context.Context, req *logical.Request, data *framework.FieldData) (bool, error) {
|
|
entry, err := b.configEntry(ctx, req.Storage)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return entry != nil, nil
|
|
}
|
|
|
|
// Fetch the client configuration required to access the AWS API.
|
|
func (b *backend) configEntry(ctx context.Context, s logical.Storage) (*config, error) {
|
|
entry, err := s.Get(ctx, "config")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if entry == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var result config
|
|
if err := entry.DecodeJSON(&result); err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, nil
|
|
}
|
|
|
|
type config struct {
|
|
FailRotate bool
|
|
automatedrotationutil.AutomatedRotationParams
|
|
}
|