-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathpath_config.go
169 lines (147 loc) · 5.03 KB
/
path_config.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package main
import (
"context"
"fmt"
"net/url"
"time"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/logical/framework"
)
func pathConfig(b *backend) *framework.Path {
return &framework.Path{
Pattern: "config",
Fields: map[string]*framework.FieldSchema{
"circleci_token": &framework.FieldSchema{
Type: framework.TypeString,
Description: "The CircleCI access token that allows this plugin to make CircleCI API calls to verify the authentication information.",
},
"base_url": &framework.FieldSchema{
Type: framework.TypeString,
Description: "The base URL used to construct all endpoint URLs for this plugin.",
Default: "https://circleci.com/api/v1.1",
},
"ttl": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Duration of the token's lifetime, unless renewed.",
},
"max_ttl": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Maximum duration of the token's lifetime.",
},
"vcs_type": &framework.FieldSchema{
Type: framework.TypeString,
Description: "The version control system type where the project is hosted. Supported values are github and bitbucket.",
},
"owner": &framework.FieldSchema{
Type: framework.TypeString,
Description: "The user or organization that owns the project in the VCS.",
},
"attempt_cache_expiry": &framework.FieldSchema{
Type: framework.TypeString,
Description: "The duration that login attempts are cached in order to prevent further attempts.",
Default: "18000s",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.pathConfigRead,
logical.UpdateOperation: b.pathConfigWrite,
},
}
}
func (b *backend) pathConfigRead(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
config, err := b.Config(ctx, req.Storage)
if err != nil {
return nil, err
}
config.TTL /= time.Second
config.MaxTTL /= time.Second
config.AttemptCacheExpiry /= time.Second
return &logical.Response{
Data: map[string]interface{}{
"circleci_token": config.CircleCIToken,
"base_url": config.BaseURL,
"ttl": config.TTL,
"max_ttl": config.MaxTTL,
"vcs_type": config.VCSType,
"owner": config.Owner,
"attempt_cache_expiry": config.AttemptCacheExpiry,
},
}, nil
}
func (b *backend) pathConfigWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
circleCIToken := d.Get("circleci_token").(string)
baseURL := d.Get("base_url").(string)
if len(baseURL) > 0 {
// Try parsing the URL to make sure that it's valid.
if _, err := url.Parse(baseURL); err != nil {
return logical.ErrorResponse(fmt.Sprintf("Error parsing given base_url: %s", err)), nil
}
}
ttl, err := parseDurationField("ttl", d)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf("Invalid 'ttl': %s", err)), nil
}
maxTTL, err := parseDurationField("max_ttl", d)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf("Invalid 'max_ttl': %s", err)), nil
}
attemptCacheExpiry, err := parseDurationField("attempt_cache_expiry", d)
if err != nil {
return logical.ErrorResponse(fmt.Sprintf("Invalid 'attempt_cache_time': %s", err)), nil
}
vcsType := d.Get("vcs_type").(string)
owner := d.Get("owner").(string)
entry, err := logical.StorageEntryJSON("config", config{
CircleCIToken: circleCIToken,
BaseURL: baseURL,
TTL: ttl,
MaxTTL: maxTTL,
VCSType: vcsType,
Owner: owner,
AttemptCacheExpiry: attemptCacheExpiry,
})
if err != nil {
return nil, err
}
if err := req.Storage.Put(ctx, entry); err != nil {
return nil, err
}
// Clear out the client so that it gets reconstructed using the new vcs_type and owner values.
b.client = nil
b.CacheExpiry = attemptCacheExpiry
return nil, nil
}
func parseDurationField(fieldName string, d *framework.FieldData) (time.Duration, error) {
var value time.Duration
var err error
raw, ok := d.GetOk(fieldName)
if !ok || len(raw.(string)) == 0 {
value = 0
} else {
value, err = time.ParseDuration(raw.(string))
}
return value, err
}
// Config reads the config object out of the provided Storage.
func (b *backend) Config(ctx context.Context, s logical.Storage) (*config, error) {
entry, err := s.Get(ctx, "config")
if err != nil {
return nil, err
}
var result config
if entry != nil {
if err := entry.DecodeJSON(&result); err != nil {
return nil, fmt.Errorf("error reading configuration: %s", err)
}
}
return &result, nil
}
type config struct {
CircleCIToken string `json:"circleci_token"`
BaseURL string `json:"base_url"`
TTL time.Duration `json:"ttl"`
MaxTTL time.Duration `json:"max_ttl"`
VCSType string `json:"vcs_type"`
Owner string `json:"owner"`
AttemptCacheExpiry time.Duration `json:"attempt_cache_expiry"`
}