2023-03-15 19:00:52 +03:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2015-05-28 04:05:23 +03:00
|
|
|
package api
|
|
|
|
|
2018-07-25 01:49:55 +03:00
|
|
|
import (
|
|
|
|
"context"
|
2018-08-14 22:29:22 +03:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2022-03-24 20:58:03 +03:00
|
|
|
"net/http"
|
2018-07-25 01:49:55 +03:00
|
|
|
"time"
|
|
|
|
)
|
2015-05-28 04:05:23 +03:00
|
|
|
|
|
|
|
func (c *Sys) Rotate() error {
|
2022-03-24 00:47:43 +03:00
|
|
|
return c.RotateWithContext(context.Background())
|
|
|
|
}
|
2018-07-25 01:49:55 +03:00
|
|
|
|
2022-03-24 00:47:43 +03:00
|
|
|
func (c *Sys) RotateWithContext(ctx context.Context) error {
|
|
|
|
ctx, cancelFunc := c.c.withConfiguredTimeout(ctx)
|
2018-07-25 01:49:55 +03:00
|
|
|
defer cancelFunc()
|
2022-03-24 00:47:43 +03:00
|
|
|
|
2022-03-24 20:58:03 +03:00
|
|
|
r := c.c.NewRequest(http.MethodPost, "/v1/sys/rotate")
|
2022-03-24 00:47:43 +03:00
|
|
|
|
|
|
|
resp, err := c.c.rawRequestWithContext(ctx, r)
|
2015-05-28 04:05:23 +03:00
|
|
|
if err == nil {
|
|
|
|
defer resp.Body.Close()
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Sys) KeyStatus() (*KeyStatus, error) {
|
2022-03-24 00:47:43 +03:00
|
|
|
return c.KeyStatusWithContext(context.Background())
|
|
|
|
}
|
2018-07-25 01:49:55 +03:00
|
|
|
|
2022-03-24 00:47:43 +03:00
|
|
|
func (c *Sys) KeyStatusWithContext(ctx context.Context) (*KeyStatus, error) {
|
|
|
|
ctx, cancelFunc := c.c.withConfiguredTimeout(ctx)
|
2018-07-25 01:49:55 +03:00
|
|
|
defer cancelFunc()
|
2022-03-24 00:47:43 +03:00
|
|
|
|
2022-03-24 20:58:03 +03:00
|
|
|
r := c.c.NewRequest(http.MethodGet, "/v1/sys/key-status")
|
2022-03-24 00:47:43 +03:00
|
|
|
|
|
|
|
resp, err := c.c.rawRequestWithContext(ctx, r)
|
2015-05-28 04:05:23 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
2018-08-14 22:29:22 +03:00
|
|
|
secret, err := ParseSecret(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if secret == nil || secret.Data == nil {
|
|
|
|
return nil, errors.New("data from server response is empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
var result KeyStatus
|
|
|
|
|
|
|
|
termRaw, ok := secret.Data["term"]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("term not found in response")
|
|
|
|
}
|
|
|
|
term, ok := termRaw.(json.Number)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("could not convert term to a number")
|
|
|
|
}
|
|
|
|
term64, err := term.Int64()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
result.Term = int(term64)
|
|
|
|
|
|
|
|
installTimeRaw, ok := secret.Data["install_time"]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("install_time not found in response")
|
|
|
|
}
|
|
|
|
installTimeStr, ok := installTimeRaw.(string)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("could not convert install_time to a string")
|
|
|
|
}
|
|
|
|
installTime, err := time.Parse(time.RFC3339Nano, installTimeStr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
result.InstallTime = installTime
|
|
|
|
|
2021-02-25 23:27:25 +03:00
|
|
|
encryptionsRaw, ok := secret.Data["encryptions"]
|
|
|
|
if ok {
|
|
|
|
encryptions, ok := encryptionsRaw.(json.Number)
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("could not convert encryptions to a number")
|
|
|
|
}
|
|
|
|
encryptions64, err := encryptions.Int64()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
result.Encryptions = int(encryptions64)
|
|
|
|
}
|
|
|
|
|
2018-08-14 22:29:22 +03:00
|
|
|
return &result, err
|
2015-05-28 04:05:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type KeyStatus struct {
|
2016-08-14 21:52:45 +03:00
|
|
|
Term int `json:"term"`
|
2015-05-28 04:05:23 +03:00
|
|
|
InstallTime time.Time `json:"install_time"`
|
2021-02-25 23:27:25 +03:00
|
|
|
Encryptions int `json:"encryptions"`
|
2015-05-28 04:05:23 +03:00
|
|
|
}
|