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  }