-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathedgekv_access_tokens.go
284 lines (237 loc) · 11.1 KB
/
edgekv_access_tokens.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
package edgeworkers
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"github.com/akamai/AkamaiOPEN-edgegrid-golang/v9/pkg/session"
validation "github.com/go-ozzo/ozzo-validation/v4"
)
type (
// CreateEdgeKVAccessTokenRequest contains parameters used to create EdgeKV access token
CreateEdgeKVAccessTokenRequest struct {
// Whether to allow this token access to the Akamai production network
AllowOnProduction bool `json:"allowOnProduction"`
// Whether to allow this token access to the Akamai staging network
AllowOnStaging bool `json:"allowOnStaging"`
// Friendly name of the token. Used when retrieving tokens by name.
Name string `json:"name"`
// A list of namespace identifiers the token should have access to, plus the associated read, write, delete permissions
NamespacePermissions NamespacePermissions `json:"namespacePermissions"`
// A set of EdgeWorker IDs authorized to access EdgeKV via the token. By default, if you omit this array, the token authorizes access for all IDs.
RestrictToEdgeWorkerIDs []string `json:"restrictToEdgeWorkerIds"`
}
// NamespacePermissions represents mapping between namespaces and permissions
NamespacePermissions map[string][]Permission
// Permissions represents set of permissions for namespace
Permissions []Permission
// Permission has possible values: `r` for read access, `w` for write access, `d` for delete access
Permission string
// EdgeKVAccessToken contains response from EdgeKV access token creation
EdgeKVAccessToken struct {
// The expiry date
Expiry string `json:"expiry"`
// The name assigned to the access token. You can't modify an access token name.
Name string `json:"name"`
// Internally generated unique identifier for the access token
UUID string `json:"uuid"`
// The IN_PROGRESS status indicates token activation is still in progress,
// and it's not yet possible to make successful EdgeKV requests from EdgeWorkers that use the token.
// Once activation completes, status is COMPLETE.
// Otherwise, a value of ERROR indicates a problem that prevented activation.
TokenActivationStatus *string `json:"tokenActivationStatus"`
// Initial token creation date in ISO 8601 format.
IssueDate *string `json:"issueDate"`
// Most recent token refresh date in ISO 8601 format. A null value indicates the token has not yet been refreshed.
LatestRefreshDate *string `json:"latestRefreshDate"`
// Next scheduled date of the token refresh in ISO 8601 format.
NextScheduledRefreshDate *string `json:"nextScheduledRefreshDate"`
}
// CreateEdgeKVAccessTokenResponse contains response from EdgeKV access token creation
CreateEdgeKVAccessTokenResponse struct {
AllowOnProduction bool `json:"allowOnProduction"`
AllowOnStaging bool `json:"allowOnStaging"`
CPCode string `json:"cpcode"`
Expiry string `json:"expiry"`
IssueDate string `json:"issueDate"`
LatestRefreshDate *string `json:"latestRefreshDate"`
Name string `json:"name"`
NamespacePermissions NamespacePermissions `json:"namespacePermissions"`
NextScheduledRefreshDate string `json:"nextScheduledRefreshDate"`
RestrictToEdgeWorkerIDs []string `json:"restrictToEdgeWorkerIds"`
TokenActivationStatus string `json:"tokenActivationStatus"`
UUID string `json:"uuid"`
}
// GetEdgeKVAccessTokenRequest represents an TokenName object
GetEdgeKVAccessTokenRequest struct {
TokenName string
}
// GetEdgeKVAccessTokenResponse contains response from EdgeKV access token retrieval
GetEdgeKVAccessTokenResponse CreateEdgeKVAccessTokenResponse
// ListEdgeKVAccessTokensRequest contains request parameters for ListEdgeKVAccessTokens
ListEdgeKVAccessTokensRequest struct {
IncludeExpired bool
}
// ListEdgeKVAccessTokensResponse contains list of EdgeKV access tokens
ListEdgeKVAccessTokensResponse struct {
Tokens []EdgeKVAccessToken `json:"tokens"`
}
// DeleteEdgeKVAccessTokenRequest contains name of the EdgeKV access token to remove
DeleteEdgeKVAccessTokenRequest struct {
TokenName string
}
// DeleteEdgeKVAccessTokenResponse contains response after removal of EdgeKV access token
DeleteEdgeKVAccessTokenResponse struct {
Name string `json:"name"`
UUID string `json:"uuid"`
}
)
const (
// PermissionRead represents read permission
PermissionRead Permission = "r"
// PermissionWrite represents write permission
PermissionWrite Permission = "w"
// PermissionDelete represents delete permission
PermissionDelete Permission = "d"
)
// Validate validates CreateEdgeKVAccessTokenRequest
func (c CreateEdgeKVAccessTokenRequest) Validate() error {
namespaces := make([]string, 0)
for name := range c.NamespacePermissions {
namespaces = append(namespaces, name)
}
return validation.Errors{
"AllowOnProduction": validation.Validate(c.AllowOnProduction, validation.Required.When(c.AllowOnStaging == false).Error("at least one of AllowOnProduction or AllowOnStaging has to be provided")),
"AllowOnStaging": validation.Validate(c.AllowOnStaging, validation.Required.When(c.AllowOnProduction == false).Error("at least one of AllowOnProduction or AllowOnStaging has to be provided")),
"Name": validation.Validate(c.Name, validation.Required, validation.Length(1, 32)),
"NamespacePermissions.Names": validation.Validate(namespaces, validation.Required, validation.Each(validation.Required)),
"NamespacePermissions": validation.Validate(c.NamespacePermissions,
validation.Required, validation.Each( // map value
validation.Required,
validation.Each( // array
validation.Required,
validation.In(PermissionRead, PermissionWrite, PermissionDelete)))),
}.Filter()
}
// Validate validates GetEdgeKVAccessTokenRequest
func (g GetEdgeKVAccessTokenRequest) Validate() error {
return validation.Errors{
"TokenName": validation.Validate(g.TokenName, validation.Required, validation.Length(1, 32)),
}.Filter()
}
// Validate validates DeleteEdgeKVAccessTokenRequest
func (d DeleteEdgeKVAccessTokenRequest) Validate() error {
return validation.Errors{
"TokenName": validation.Validate(d.TokenName, validation.Required, validation.Length(1, 32)),
}.Filter()
}
var (
// ErrCreateEdgeKVAccessToken is returned in case an error occurs on CreateEdgeKVAccessToken operation
ErrCreateEdgeKVAccessToken = errors.New("create an EdgeKV access token")
// ErrGetEdgeKVAccessToken is returned in case an error occurs on GetEdgeKVAccessToken operation
ErrGetEdgeKVAccessToken = errors.New("get an EdgeKV access token")
// ErrListEdgeKVAccessToken is returned in case an error occurs on ListEdgeKVAccessToken operation
ErrListEdgeKVAccessToken = errors.New("list EdgeKV access tokens")
// ErrDeleteEdgeKVAccessToken is returned in case an error occurs on DeleteEdgeKVAccessToken operation
ErrDeleteEdgeKVAccessToken = errors.New("delete an EdgeKV access token")
)
func (e *edgeworkers) CreateEdgeKVAccessToken(ctx context.Context, params CreateEdgeKVAccessTokenRequest) (*CreateEdgeKVAccessTokenResponse, error) {
logger := e.Log(ctx)
logger.Debug("CreateEdgeKVAccessToken")
if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w: %s", ErrCreateEdgeKVAccessToken, ErrStructValidation, err)
}
uri := "/edgekv/v1/tokens"
req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateEdgeKVAccessToken, err)
}
var result CreateEdgeKVAccessTokenResponse
resp, err := e.Exec(req, &result, params)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrCreateEdgeKVAccessToken, err)
}
defer session.CloseResponseBody(resp)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrCreateEdgeKVAccessToken, e.Error(resp))
}
return &result, nil
}
func (e *edgeworkers) GetEdgeKVAccessToken(ctx context.Context, params GetEdgeKVAccessTokenRequest) (*GetEdgeKVAccessTokenResponse, error) {
logger := e.Log(ctx)
logger.Debug("GetEdgeKVAccessToken")
if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w: %s", ErrGetEdgeKVAccessToken, ErrStructValidation, err)
}
uri, err := url.Parse(fmt.Sprintf("/edgekv/v1/tokens/%s", params.TokenName))
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetEdgeKVAccessToken, err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetEdgeKVAccessToken, err)
}
var result GetEdgeKVAccessTokenResponse
resp, err := e.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrGetEdgeKVAccessToken, err)
}
defer session.CloseResponseBody(resp)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrGetEdgeKVAccessToken, e.Error(resp))
}
return &result, nil
}
func (e *edgeworkers) ListEdgeKVAccessTokens(ctx context.Context, params ListEdgeKVAccessTokensRequest) (*ListEdgeKVAccessTokensResponse, error) {
logger := e.Log(ctx)
logger.Debug("ListEdgeKVAccessToken")
uri, err := url.Parse("/edgekv/v1/tokens")
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListEdgeKVAccessToken, err)
}
q := uri.Query()
if params.IncludeExpired {
q.Add("includeExpired", strconv.FormatBool(params.IncludeExpired))
}
uri.RawQuery = q.Encode()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrListEdgeKVAccessToken, err)
}
var result ListEdgeKVAccessTokensResponse
resp, err := e.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrListEdgeKVAccessToken, err)
}
defer session.CloseResponseBody(resp)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrListEdgeKVAccessToken, e.Error(resp))
}
return &result, nil
}
func (e *edgeworkers) DeleteEdgeKVAccessToken(ctx context.Context, params DeleteEdgeKVAccessTokenRequest) (*DeleteEdgeKVAccessTokenResponse, error) {
e.Log(ctx).Debug("DeleteEdgeKVAccessToken")
if err := params.Validate(); err != nil {
return nil, fmt.Errorf("%s: %w:\n%s", ErrDeleteEdgeKVAccessToken, ErrStructValidation, err)
}
uri, err := url.Parse(fmt.Sprintf("/edgekv/v1/tokens/%s", params.TokenName))
if err != nil {
return nil, fmt.Errorf("%w: failed to parse url: %s", ErrDeleteEdgeKVAccessToken, err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri.String(), nil)
if err != nil {
return nil, fmt.Errorf("%w: failed to create request: %s", ErrDeleteEdgeKVAccessToken, err)
}
var result DeleteEdgeKVAccessTokenResponse
resp, err := e.Exec(req, &result)
if err != nil {
return nil, fmt.Errorf("%w: request failed: %s", ErrDeleteEdgeKVAccessToken, err)
}
defer session.CloseResponseBody(resp)
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %w", ErrDeleteEdgeKVAccessToken, e.Error(resp))
}
return &result, nil
}