-
Notifications
You must be signed in to change notification settings - Fork 1
/
secret_apikey.go
136 lines (116 loc) · 3.77 KB
/
secret_apikey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package exoscale
import (
"context"
"errors"
"fmt"
"strings"
"time"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
const SecretTypeAPIKey = "apikey"
func (b *exoscaleBackend) secretAPIKey() *framework.Secret {
return &framework.Secret{
Type: SecretTypeAPIKey,
Fields: map[string]*framework.FieldSchema{
"name": {
Type: framework.TypeString,
Description: "API key name",
},
"api_key": {
Type: framework.TypeString,
Description: "API key",
},
"api_secret": {
Type: framework.TypeString,
Description: "API secret",
},
},
Renew: b.secretAPIKeyRenew,
Revoke: b.secretAPIKeyRevoke,
}
}
func (b *exoscaleBackend) secretAPIKeyRenew(
ctx context.Context,
req *logical.Request,
_ *framework.FieldData,
) (*logical.Response, error) {
iamKey, ok := req.Secret.InternalData["api_key"]
if !ok {
return nil, errors.New("'api_key' is missing from the secret's internal data")
}
iamName, ok := req.Secret.InternalData["name"]
if !ok {
return nil, errors.New("'name' is missing from the secret's internal data")
}
res := &logical.Response{Secret: req.Secret}
ttl, _, err := framework.CalculateTTL(b.System(), 0, req.Secret.TTL, 0, 0, req.Secret.MaxTTL, req.Secret.IssueTime)
if err != nil {
return nil, err
}
// Vault agent calculates a grace period of 10 to 20% of the lease TTL,
// once we enter the grace period, the agent stops renewing the lease
// and fetches a new one. This gives the workload time to complete
// ongoing operations before loading the new secret.
// After each renew, if the lease was extended, vault agent will recalculate
// the grace period based on the new TTL. If the new TTL is above the Max TTL,
// the value is capped, reducing the grace period to an unpredictable amount
// of time.
// To make sure it will calculate the refresh grace period based
// on a full TTL value, we extend the lease only if the TTL is
// not capped by max_ttl
if ttl == req.Secret.TTL {
res.Secret.TTL = ttl
res.Secret.InternalData["expireTime"] = time.Now().Add(res.Secret.TTL)
b.Logger().Info("Renewing",
"ttl", fmt.Sprint(res.Secret.TTL),
"role", req.Secret.InternalData["role"],
"iam_key", iamKey,
"iam_name", iamName)
} else {
rawExpireTime, ok := req.Secret.InternalData["expireTime"]
if !ok {
return nil, fmt.Errorf("expireTime missing from secret's InternalData")
}
expireTime, err := time.Parse(time.RFC3339, rawExpireTime.(string))
if err != nil {
return nil, fmt.Errorf("can't parse expireTime from secret's InternalData")
}
res.Secret.TTL = time.Until(expireTime)
b.Logger().Info("Not renewing because ttl would be capped by max_ttl ",
"ttl", fmt.Sprint(res.Secret.TTL),
"capped_ttl", fmt.Sprint(ttl),
"role", req.Secret.InternalData["role"],
"iam_key", iamKey,
"iam_name", iamName)
}
return res, nil
}
func (b *exoscaleBackend) secretAPIKeyRevoke(
ctx context.Context,
req *logical.Request,
_ *framework.FieldData,
) (*logical.Response, error) {
key, ok := req.Secret.InternalData["api_key"]
if !ok {
return nil, errors.New("API key is missing from the secret")
}
version := "v2"
if v, ok := req.Secret.InternalData["version"]; ok {
version = v.(string)
}
var err error
if version == "v2" {
err = b.exo.V2RevokeAccessKey(ctx, key.(string))
} else {
err = b.exo.V3DeleteAPIKey(ctx, key.(string))
}
if err != nil && strings.HasSuffix(err.Error(), ": resource not found") {
b.Logger().Warn("IAM key deosn't exist anymore, cleaning up secret", "key", key, "lease_id", req.Secret.LeaseID)
return nil, nil
} else if err != nil {
return nil, fmt.Errorf("unable to revoke the API key: %w", err)
}
b.Logger().Info("IAM key revoked", "key", key.(string), "lease_id", req.Secret.LeaseID)
return nil, nil
}