github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/edgeworkers/edgekv_access_tokens.go (about) 1 package edgeworkers 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/url" 9 "strconv" 10 11 validation "github.com/go-ozzo/ozzo-validation/v4" 12 ) 13 14 type ( 15 // EdgeKVAccessTokens is EdgeKV access token API interface 16 EdgeKVAccessTokens interface { 17 // CreateEdgeKVAccessToken generates EdgeKV specific access token 18 // 19 // See: https://techdocs.akamai.com/edgekv/reference/post-tokens 20 CreateEdgeKVAccessToken(context.Context, CreateEdgeKVAccessTokenRequest) (*CreateEdgeKVAccessTokenResponse, error) 21 22 // GetEdgeKVAccessToken retrieves an EdgeKV access token 23 // 24 // See: https://techdocs.akamai.com/edgekv/reference/get-token 25 GetEdgeKVAccessToken(context.Context, GetEdgeKVAccessTokenRequest) (*GetEdgeKVAccessTokenResponse, error) 26 27 // ListEdgeKVAccessTokens lists EdgeKV access tokens 28 // 29 // See: https://techdocs.akamai.com/edgekv/reference/get-tokens 30 ListEdgeKVAccessTokens(context.Context, ListEdgeKVAccessTokensRequest) (*ListEdgeKVAccessTokensResponse, error) 31 32 // DeleteEdgeKVAccessToken revokes an EdgeKV access token 33 // 34 // See: https://techdocs.akamai.com/edgekv/reference/delete-token 35 DeleteEdgeKVAccessToken(context.Context, DeleteEdgeKVAccessTokenRequest) (*DeleteEdgeKVAccessTokenResponse, error) 36 } 37 38 // CreateEdgeKVAccessTokenRequest contains parameters used to create EdgeKV access token 39 CreateEdgeKVAccessTokenRequest struct { 40 // Whether to allow this token access to the Akamai production network 41 AllowOnProduction bool `json:"allowOnProduction"` 42 // Whether to allow this token access to the Akamai staging network 43 AllowOnStaging bool `json:"allowOnStaging"` 44 // Desired token expiry date in ISO format. Expiry can be up to 6 months from creation. 45 Expiry string `json:"expiry"` 46 // Friendly name of the token. Used when retrieving tokens by name. 47 Name string `json:"name"` 48 // A list of namespace identifiers the token should have access to, plus the associated read, write, delete permissions 49 NamespacePermissions NamespacePermissions `json:"namespacePermissions"` 50 } 51 52 // NamespacePermissions represents mapping between namespaces and permissions 53 NamespacePermissions map[string][]Permission 54 55 // Permissions represents set of permissions for namespace 56 Permissions []Permission 57 58 // Permission has possible values: `r` for read access, `w` for write access, `d` for delete access 59 Permission string 60 61 // EdgeKVAccessToken contains response from EdgeKV access token creation 62 EdgeKVAccessToken struct { 63 // The expiry date 64 Expiry string `json:"expiry"` 65 // The name assigned to the access token. You can't modify an access token name. 66 Name string `json:"name"` 67 // Internally generated unique identifier for the access token 68 UUID string `json:"uuid"` 69 } 70 71 // CreateEdgeKVAccessTokenResponse contains response from EdgeKV access token creation 72 CreateEdgeKVAccessTokenResponse struct { 73 // The expiry date 74 Expiry string `json:"expiry"` 75 // The name assigned to the access token. You can't modify an access token name. 76 Name string `json:"name"` 77 // Internally generated unique identifier for the access token 78 UUID string `json:"uuid"` 79 // The access token details 80 Value string `json:"value"` 81 } 82 83 // GetEdgeKVAccessTokenRequest represents an TokenName object 84 GetEdgeKVAccessTokenRequest struct { 85 TokenName string 86 } 87 88 // GetEdgeKVAccessTokenResponse contains response from EdgeKV access token retrieval 89 GetEdgeKVAccessTokenResponse CreateEdgeKVAccessTokenResponse 90 91 // ListEdgeKVAccessTokensRequest contains request parameters for ListEdgeKVAccessTokens 92 ListEdgeKVAccessTokensRequest struct { 93 IncludeExpired bool 94 } 95 96 // ListEdgeKVAccessTokensResponse contains list of EdgeKV access tokens 97 ListEdgeKVAccessTokensResponse struct { 98 Tokens []EdgeKVAccessToken `json:"tokens"` 99 } 100 101 // DeleteEdgeKVAccessTokenRequest contains name of the EdgeKV access token to remove 102 DeleteEdgeKVAccessTokenRequest struct { 103 TokenName string 104 } 105 106 // DeleteEdgeKVAccessTokenResponse contains response after removal of EdgeKV access token 107 DeleteEdgeKVAccessTokenResponse struct { 108 Name string `json:"name"` 109 UUID string `json:"uuid"` 110 } 111 ) 112 113 const ( 114 // PermissionRead represents read permission 115 PermissionRead Permission = "r" 116 // PermissionWrite represents write permission 117 PermissionWrite Permission = "w" 118 // PermissionDelete represents delete permission 119 PermissionDelete Permission = "d" 120 ) 121 122 // Validate validates CreateEdgeKVAccessTokenRequest 123 func (c CreateEdgeKVAccessTokenRequest) Validate() error { 124 namespaces := make([]string, 0) 125 for name := range c.NamespacePermissions { 126 namespaces = append(namespaces, name) 127 } 128 129 return validation.Errors{ 130 "AllowOnProduction": validation.Validate(c.AllowOnProduction, validation.Required.When(c.AllowOnStaging == false).Error("at least one of AllowOnProduction or AllowOnStaging has to be provided")), 131 "AllowOnStaging": validation.Validate(c.AllowOnStaging, validation.Required.When(c.AllowOnProduction == false).Error("at least one of AllowOnProduction or AllowOnStaging has to be provided")), 132 "Expiry": validation.Validate(c.Expiry, validation.Required, validation.Date("2006-01-02").Error("the time format should be provided as per ISO-8601")), 133 "Name": validation.Validate(c.Name, validation.Required, validation.Length(1, 32)), 134 "NamespacePermissions.Names": validation.Validate(namespaces, validation.Required, validation.Each(validation.Required)), 135 "NamespacePermissions": validation.Validate(c.NamespacePermissions, 136 validation.Required, validation.Each( // map value 137 validation.Required, 138 validation.Each( // array 139 validation.Required, 140 validation.In(PermissionRead, PermissionWrite, PermissionDelete)))), 141 }.Filter() 142 } 143 144 // Validate validates GetEdgeKVAccessTokenRequest 145 func (g GetEdgeKVAccessTokenRequest) Validate() error { 146 return validation.Errors{ 147 "TokenName": validation.Validate(g.TokenName, validation.Required, validation.Length(1, 32)), 148 }.Filter() 149 } 150 151 // Validate validates DeleteEdgeKVAccessTokenRequest 152 func (d DeleteEdgeKVAccessTokenRequest) Validate() error { 153 return validation.Errors{ 154 "TokenName": validation.Validate(d.TokenName, validation.Required, validation.Length(1, 32)), 155 }.Filter() 156 } 157 158 var ( 159 // ErrCreateEdgeKVAccessToken is returned in case an error occurs on CreateEdgeKVAccessToken operation 160 ErrCreateEdgeKVAccessToken = errors.New("create an EdgeKV access token") 161 // ErrGetEdgeKVAccessToken is returned in case an error occurs on GetEdgeKVAccessToken operation 162 ErrGetEdgeKVAccessToken = errors.New("get an EdgeKV access token") 163 // ErrListEdgeKVAccessToken is returned in case an error occurs on ListEdgeKVAccessToken operation 164 ErrListEdgeKVAccessToken = errors.New("list EdgeKV access tokens") 165 // ErrDeleteEdgeKVAccessToken is returned in case an error occurs on DeleteEdgeKVAccessToken operation 166 ErrDeleteEdgeKVAccessToken = errors.New("delete an EdgeKV access token") 167 ) 168 169 func (e *edgeworkers) CreateEdgeKVAccessToken(ctx context.Context, params CreateEdgeKVAccessTokenRequest) (*CreateEdgeKVAccessTokenResponse, error) { 170 logger := e.Log(ctx) 171 logger.Debug("CreateEdgeKVAccessToken") 172 173 if err := params.Validate(); err != nil { 174 return nil, fmt.Errorf("%s: %w: %s", ErrCreateEdgeKVAccessToken, ErrStructValidation, err) 175 } 176 177 uri := "/edgekv/v1/tokens" 178 179 req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil) 180 if err != nil { 181 return nil, fmt.Errorf("%w: failed to create request: %s", ErrCreateEdgeKVAccessToken, err) 182 } 183 184 var result CreateEdgeKVAccessTokenResponse 185 resp, err := e.Exec(req, &result, params) 186 if err != nil { 187 return nil, fmt.Errorf("%w: request failed: %s", ErrCreateEdgeKVAccessToken, err) 188 } 189 190 if resp.StatusCode != http.StatusOK { 191 return nil, fmt.Errorf("%s: %w", ErrCreateEdgeKVAccessToken, e.Error(resp)) 192 } 193 194 return &result, nil 195 } 196 197 func (e *edgeworkers) GetEdgeKVAccessToken(ctx context.Context, params GetEdgeKVAccessTokenRequest) (*GetEdgeKVAccessTokenResponse, error) { 198 logger := e.Log(ctx) 199 logger.Debug("GetEdgeKVAccessToken") 200 201 if err := params.Validate(); err != nil { 202 return nil, fmt.Errorf("%s: %w: %s", ErrGetEdgeKVAccessToken, ErrStructValidation, err) 203 } 204 205 uri, err := url.Parse(fmt.Sprintf("/edgekv/v1/tokens/%s", params.TokenName)) 206 if err != nil { 207 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrGetEdgeKVAccessToken, err) 208 } 209 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil) 210 if err != nil { 211 return nil, fmt.Errorf("%w: failed to create request: %s", ErrGetEdgeKVAccessToken, err) 212 } 213 214 var result GetEdgeKVAccessTokenResponse 215 resp, err := e.Exec(req, &result) 216 if err != nil { 217 return nil, fmt.Errorf("%w: request failed: %s", ErrGetEdgeKVAccessToken, err) 218 } 219 220 if resp.StatusCode != http.StatusOK { 221 return nil, fmt.Errorf("%s: %w", ErrGetEdgeKVAccessToken, e.Error(resp)) 222 } 223 224 return &result, nil 225 } 226 227 func (e *edgeworkers) ListEdgeKVAccessTokens(ctx context.Context, params ListEdgeKVAccessTokensRequest) (*ListEdgeKVAccessTokensResponse, error) { 228 logger := e.Log(ctx) 229 logger.Debug("ListEdgeKVAccessToken") 230 231 uri, err := url.Parse("/edgekv/v1/tokens") 232 if err != nil { 233 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrListEdgeKVAccessToken, err) 234 } 235 236 q := uri.Query() 237 if params.IncludeExpired { 238 q.Add("includeExpired", strconv.FormatBool(params.IncludeExpired)) 239 } 240 uri.RawQuery = q.Encode() 241 242 req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil) 243 if err != nil { 244 return nil, fmt.Errorf("%w: failed to create request: %s", ErrListEdgeKVAccessToken, err) 245 } 246 247 var result ListEdgeKVAccessTokensResponse 248 resp, err := e.Exec(req, &result) 249 if err != nil { 250 return nil, fmt.Errorf("%w: request failed: %s", ErrListEdgeKVAccessToken, err) 251 } 252 253 if resp.StatusCode != http.StatusOK { 254 return nil, fmt.Errorf("%s: %w", ErrListEdgeKVAccessToken, e.Error(resp)) 255 } 256 257 return &result, nil 258 } 259 260 func (e *edgeworkers) DeleteEdgeKVAccessToken(ctx context.Context, params DeleteEdgeKVAccessTokenRequest) (*DeleteEdgeKVAccessTokenResponse, error) { 261 e.Log(ctx).Debug("DeleteEdgeKVAccessToken") 262 263 if err := params.Validate(); err != nil { 264 return nil, fmt.Errorf("%s: %w:\n%s", ErrDeleteEdgeKVAccessToken, ErrStructValidation, err) 265 } 266 267 uri, err := url.Parse(fmt.Sprintf("/edgekv/v1/tokens/%s", params.TokenName)) 268 if err != nil { 269 return nil, fmt.Errorf("%w: failed to parse url: %s", ErrDeleteEdgeKVAccessToken, err) 270 } 271 272 req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri.String(), nil) 273 if err != nil { 274 return nil, fmt.Errorf("%w: failed to create request: %s", ErrDeleteEdgeKVAccessToken, err) 275 } 276 277 var result DeleteEdgeKVAccessTokenResponse 278 resp, err := e.Exec(req, &result) 279 if err != nil { 280 return nil, fmt.Errorf("%w: request failed: %s", ErrDeleteEdgeKVAccessToken, err) 281 } 282 283 if resp.StatusCode != http.StatusOK { 284 return nil, fmt.Errorf("%s: %w", ErrDeleteEdgeKVAccessToken, e.Error(resp)) 285 } 286 287 return &result, nil 288 }