github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.0/pkg/appsec/match_target.go (about)

     1  package appsec
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	validation "github.com/go-ozzo/ozzo-validation/v4"
    10  )
    11  
    12  type (
    13  	// The MatchTarget interface supports creating, retrieving, updating and removing match targets.
    14  	//
    15  	// https://developer.akamai.com/api/cloud_security/application_security/v1.html#matchtarget
    16  	MatchTarget interface {
    17  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargets
    18  		GetMatchTargets(ctx context.Context, params GetMatchTargetsRequest) (*GetMatchTargetsResponse, error)
    19  
    20  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargetid
    21  		GetMatchTarget(ctx context.Context, params GetMatchTargetRequest) (*GetMatchTargetResponse, error)
    22  
    23  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#getmatchtargetid
    24  		CreateMatchTarget(ctx context.Context, params CreateMatchTargetRequest) (*CreateMatchTargetResponse, error)
    25  
    26  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#putmatchtargetid
    27  		UpdateMatchTarget(ctx context.Context, params UpdateMatchTargetRequest) (*UpdateMatchTargetResponse, error)
    28  
    29  		// https://developer.akamai.com/api/cloud_security/application_security/v1.html#deletematchtargetid
    30  		RemoveMatchTarget(ctx context.Context, params RemoveMatchTargetRequest) (*RemoveMatchTargetResponse, error)
    31  	}
    32  
    33  	// GetMatchTargetsRequest is used to retrieve the match targets for a configuration.
    34  	GetMatchTargetsRequest struct {
    35  		ConfigID      int `json:"configId"`
    36  		ConfigVersion int `json:"configVersion"`
    37  		TargetID      int `json:"targetId"`
    38  	}
    39  
    40  	// GetMatchTargetsResponse is returned from a call to GetMatchTargets.
    41  	GetMatchTargetsResponse struct {
    42  		MatchTargets struct {
    43  			APITargets []struct {
    44  				Type string `json:"type,omitempty"`
    45  				Apis []struct {
    46  					ID   int    `json:"id"`
    47  					Name string `json:"name"`
    48  				} `json:"apis"`
    49  				Sequence      int `json:"sequence"`
    50  				TargetID      int `json:"targetId"`
    51  				ConfigID      int `json:"configId,omitempty"`
    52  				ConfigVersion int `json:"configVersion,omitempty"`
    53  
    54  				SecurityPolicy struct {
    55  					PolicyID string `json:"policyId,omitempty"`
    56  				} `json:"securityPolicy,omitempty"`
    57  
    58  				BypassNetworkLists []struct {
    59  					Name string `json:"name,omitempty"`
    60  					ID   string `json:"id,omitempty"`
    61  				} `json:"bypassNetworkLists,omitempty"`
    62  			} `json:"apiTargets,omitempty"`
    63  			WebsiteTargets []struct {
    64  				ConfigID                     int              `json:"configId,omitempty"`
    65  				ConfigVersion                int              `json:"configVersion,omitempty"`
    66  				DefaultFile                  string           `json:"defaultFile,omitempty"`
    67  				IsNegativeFileExtensionMatch bool             `json:"isNegativeFileExtensionMatch,omitempty"`
    68  				IsNegativePathMatch          *json.RawMessage `json:"isNegativePathMatch,omitempty"`
    69  				Sequence                     int              `json:"-"`
    70  				TargetID                     int              `json:"targetId,omitempty"`
    71  				Type                         string           `json:"type,omitempty"`
    72  				FileExtensions               []string         `json:"fileExtensions,omitempty"`
    73  				FilePaths                    []string         `json:"filePaths,omitempty"`
    74  				Hostnames                    []string         `json:"hostnames,omitempty"`
    75  				SecurityPolicy               struct {
    76  					PolicyID string `json:"policyId,omitempty"`
    77  				} `json:"securityPolicy,omitempty"`
    78  				BypassNetworkLists []struct {
    79  					Name string `json:"name,omitempty"`
    80  					ID   string `json:"id,omitempty"`
    81  				} `json:"bypassNetworkLists,omitempty"`
    82  			} `json:"websiteTargets,omitempty"`
    83  		} `json:"matchTargets,omitempty"`
    84  	}
    85  
    86  	// GetMatchTargetRequest is used to retrieve a match target.
    87  	GetMatchTargetRequest struct {
    88  		ConfigID      int `json:"configId"`
    89  		ConfigVersion int `json:"configVersion"`
    90  		TargetID      int `json:"targetId"`
    91  	}
    92  
    93  	// GetMatchTargetResponse is returned from a call to GetMatchTarget.
    94  	GetMatchTargetResponse struct {
    95  		Type string `json:"type,omitempty"`
    96  		Apis []struct {
    97  			ID   int    `json:"id"`
    98  			Name string `json:"name"`
    99  		} `json:"apis,omitempty"`
   100  		DefaultFile                  string           `json:"defaultFile,omitempty"`
   101  		Hostnames                    []string         `json:"hostnames,omitempty"`
   102  		IsNegativeFileExtensionMatch bool             `json:"isNegativeFileExtensionMatch,omitempty"`
   103  		IsNegativePathMatch          *json.RawMessage `json:"isNegativePathMatch,omitempty"`
   104  		FilePaths                    []string         `json:"filePaths,omitempty"`
   105  		FileExtensions               []string         `json:"fileExtensions,omitempty"`
   106  		SecurityPolicy               struct {
   107  			PolicyID string `json:"policyId,omitempty"`
   108  		} `json:"securityPolicy,omitempty"`
   109  		Sequence           int `json:"-"`
   110  		TargetID           int `json:"targetId"`
   111  		BypassNetworkLists []struct {
   112  			Name string `json:"name,omitempty"`
   113  			ID   string `json:"id,omitempty"`
   114  		} `json:"bypassNetworkLists,omitempty"`
   115  	}
   116  
   117  	// CreateMatchTargetRequest is used to create a match target.
   118  	CreateMatchTargetRequest struct {
   119  		Type           string          `json:"type"`
   120  		ConfigID       int             `json:"configId"`
   121  		ConfigVersion  int             `json:"configVersion"`
   122  		JsonPayloadRaw json.RawMessage `json:"-"`
   123  	}
   124  
   125  	// CreateMatchTargetResponse is returned from a call to CreateMatchTarget.
   126  	CreateMatchTargetResponse struct {
   127  		MType string `json:"type"`
   128  		Apis  []struct {
   129  			ID   int    `json:"id"`
   130  			Name string `json:"name"`
   131  		} `json:"apis,omitempty"`
   132  		DefaultFile                  string           `json:"defaultFile"`
   133  		Hostnames                    []string         `json:"hostnames"`
   134  		IsNegativeFileExtensionMatch bool             `json:"isNegativeFileExtensionMatch"`
   135  		IsNegativePathMatch          *json.RawMessage `json:"isNegativePathMatch,omitempty"`
   136  		FilePaths                    []string         `json:"filePaths"`
   137  		FileExtensions               []string         `json:"fileExtensions"`
   138  		SecurityPolicy               struct {
   139  			PolicyID string `json:"policyId"`
   140  		} `json:"securityPolicy"`
   141  		Sequence           int `json:"-"`
   142  		TargetID           int `json:"targetId"`
   143  		BypassNetworkLists []struct {
   144  			Name string `json:"name"`
   145  			ID   string `json:"id"`
   146  		} `json:"bypassNetworkLists"`
   147  	}
   148  
   149  	// UpdateMatchTargetRequest is used to modify an existing match target.
   150  	UpdateMatchTargetRequest struct {
   151  		ConfigID       int             `json:"configId"`
   152  		ConfigVersion  int             `json:"configVersion"`
   153  		JsonPayloadRaw json.RawMessage `json:"-"`
   154  		TargetID       int             `json:"targetId"`
   155  	}
   156  
   157  	// UpdateMatchTargetResponse is returned from a call to UpdateMatchTarget.
   158  	UpdateMatchTargetResponse struct {
   159  		Type                         string           `json:"type"`
   160  		ConfigID                     int              `json:"configId"`
   161  		ConfigVersion                int              `json:"configVersion"`
   162  		DefaultFile                  string           `json:"defaultFile"`
   163  		Hostnames                    []string         `json:"hostnames"`
   164  		IsNegativeFileExtensionMatch bool             `json:"isNegativeFileExtensionMatch"`
   165  		IsNegativePathMatch          *json.RawMessage `json:"isNegativePathMatch,omitempty"`
   166  		FilePaths                    []string         `json:"filePaths"`
   167  		FileExtensions               []string         `json:"fileExtensions"`
   168  		SecurityPolicy               struct {
   169  			PolicyID string `json:"policyId"`
   170  		} `json:"securityPolicy"`
   171  		Sequence           int `json:"-"`
   172  		TargetID           int `json:"targetId"`
   173  		BypassNetworkLists []struct {
   174  			Name string `json:"name"`
   175  			ID   string `json:"id"`
   176  		} `json:"bypassNetworkLists"`
   177  	}
   178  
   179  	// RemoveMatchTargetRequest is used to remove a match target.
   180  	RemoveMatchTargetRequest struct {
   181  		ConfigID      int `json:"configId"`
   182  		ConfigVersion int `json:"configVersion"`
   183  		TargetID      int `json:"targetId"`
   184  	}
   185  
   186  	// RemoveMatchTargetResponse is returned from a call to RemoveMatchTarget.
   187  	RemoveMatchTargetResponse struct {
   188  		Type                         string   `json:"type"`
   189  		ConfigID                     int      `json:"configId"`
   190  		ConfigVersion                int      `json:"configVersion"`
   191  		DefaultFile                  string   `json:"defaultFile"`
   192  		Hostnames                    []string `json:"hostnames"`
   193  		IsNegativeFileExtensionMatch bool     `json:"isNegativeFileExtensionMatch"`
   194  		IsNegativePathMatch          bool     `json:"isNegativePathMatch"`
   195  		FilePaths                    []string `json:"filePaths"`
   196  		FileExtensions               []string `json:"fileExtensions"`
   197  		SecurityPolicy               struct {
   198  			PolicyID string `json:"policyId"`
   199  		} `json:"securityPolicy"`
   200  		Sequence           int `json:"sequence"`
   201  		TargetID           int `json:"targetId"`
   202  		BypassNetworkLists []struct {
   203  			Name string `json:"name"`
   204  			ID   string `json:"id"`
   205  		} `json:"bypassNetworkLists"`
   206  	}
   207  
   208  	// BypassNetworkList describes a network list used in the bypass network lists for the specified configuration.
   209  	BypassNetworkList struct {
   210  		Name string `json:"name"`
   211  		ID   string `json:"id"`
   212  	}
   213  
   214  	// Hostnames contains one or more hostnames.
   215  	Hostnames struct {
   216  		Hostnames string `json:"hostnames"`
   217  	}
   218  
   219  	// AutoGenerated is currently unused.
   220  	AutoGenerated struct {
   221  		Type string `json:"type"`
   222  		Apis []struct {
   223  			ID   int    `json:"id"`
   224  			Name string `json:"name"`
   225  		} `json:"apis"`
   226  		BypassNetworkLists []struct {
   227  			ID   string `json:"id"`
   228  			Name string `json:"name"`
   229  		} `json:"bypassNetworkLists"`
   230  		ConfigID       int `json:"configId"`
   231  		ConfigVersion  int `json:"configVersion"`
   232  		SecurityPolicy struct {
   233  			PolicyID string `json:"policyId"`
   234  		} `json:"securityPolicy"`
   235  		Sequence int `json:"-"`
   236  		TargetID int `json:"targetId"`
   237  	}
   238  )
   239  
   240  // Validate validates a GetMatchTargetRequest.
   241  func (v GetMatchTargetRequest) Validate() error {
   242  	return validation.Errors{
   243  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   244  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   245  		"TargetID":      validation.Validate(v.TargetID, validation.Required),
   246  	}.Filter()
   247  }
   248  
   249  // Validate validates a GetMatchTargetsRequest.
   250  func (v GetMatchTargetsRequest) Validate() error {
   251  	return validation.Errors{
   252  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   253  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   254  	}.Filter()
   255  }
   256  
   257  // Validate validates a CreateMatchTargetRequest.
   258  func (v CreateMatchTargetRequest) Validate() error {
   259  	return validation.Errors{
   260  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   261  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   262  	}.Filter()
   263  }
   264  
   265  // Validate validates an UpdateMatchTargetRequest.
   266  func (v UpdateMatchTargetRequest) Validate() error {
   267  	return validation.Errors{
   268  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   269  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   270  		"TargetID":      validation.Validate(v.TargetID, validation.Required),
   271  	}.Filter()
   272  }
   273  
   274  // Validate validates a RemoveMatchTargetRequest.
   275  func (v RemoveMatchTargetRequest) Validate() error {
   276  	return validation.Errors{
   277  		"ConfigID":      validation.Validate(v.ConfigID, validation.Required),
   278  		"ConfigVersion": validation.Validate(v.ConfigVersion, validation.Required),
   279  		"TargetID":      validation.Validate(v.TargetID, validation.Required),
   280  	}.Filter()
   281  }
   282  
   283  func (p *appsec) GetMatchTarget(ctx context.Context, params GetMatchTargetRequest) (*GetMatchTargetResponse, error) {
   284  	logger := p.Log(ctx)
   285  	logger.Debug("GetMatchTarget")
   286  
   287  	if err := params.Validate(); err != nil {
   288  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   289  	}
   290  
   291  	uri := fmt.Sprintf(
   292  		"/appsec/v1/configs/%d/versions/%d/match-targets/%d?includeChildObjectName=true",
   293  		params.ConfigID,
   294  		params.ConfigVersion,
   295  		params.TargetID,
   296  	)
   297  
   298  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   299  	if err != nil {
   300  		return nil, fmt.Errorf("failed to create GetMatchTarget request: %w", err)
   301  	}
   302  
   303  	var result GetMatchTargetResponse
   304  	resp, err := p.Exec(req, &result)
   305  	if err != nil {
   306  		return nil, fmt.Errorf("get match target request failed: %w", err)
   307  	}
   308  	if resp.StatusCode != http.StatusOK {
   309  		return nil, p.Error(resp)
   310  	}
   311  
   312  	return &result, nil
   313  }
   314  
   315  func (p *appsec) GetMatchTargets(ctx context.Context, params GetMatchTargetsRequest) (*GetMatchTargetsResponse, error) {
   316  	logger := p.Log(ctx)
   317  	logger.Debug("GetMatchTargets")
   318  
   319  	if err := params.Validate(); err != nil {
   320  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   321  	}
   322  
   323  	uri := fmt.Sprintf(
   324  		"/appsec/v1/configs/%d/versions/%d/match-targets",
   325  		params.ConfigID,
   326  		params.ConfigVersion,
   327  	)
   328  
   329  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
   330  	if err != nil {
   331  		return nil, fmt.Errorf("failed to create GetMatchTargets request: %w", err)
   332  	}
   333  
   334  	var result GetMatchTargetsResponse
   335  	resp, err := p.Exec(req, &result)
   336  	if err != nil {
   337  		return nil, fmt.Errorf("get match targets request failed: %w", err)
   338  	}
   339  	if resp.StatusCode != http.StatusOK {
   340  		return nil, p.Error(resp)
   341  	}
   342  
   343  	if params.TargetID != 0 {
   344  		var filteredResult GetMatchTargetsResponse
   345  		for _, val := range result.MatchTargets.WebsiteTargets {
   346  			if val.TargetID == params.TargetID {
   347  				filteredResult.MatchTargets.WebsiteTargets = append(filteredResult.MatchTargets.WebsiteTargets, val)
   348  			}
   349  		}
   350  		for _, val := range result.MatchTargets.APITargets {
   351  			if val.TargetID == params.TargetID {
   352  				filteredResult.MatchTargets.APITargets = append(filteredResult.MatchTargets.APITargets, val)
   353  			}
   354  		}
   355  		return &filteredResult, nil
   356  	}
   357  
   358  	return &result, nil
   359  }
   360  
   361  func (p *appsec) UpdateMatchTarget(ctx context.Context, params UpdateMatchTargetRequest) (*UpdateMatchTargetResponse, error) {
   362  	logger := p.Log(ctx)
   363  	logger.Debug("UpdateMatchTarget")
   364  
   365  	if err := params.Validate(); err != nil {
   366  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   367  	}
   368  
   369  	uri := fmt.Sprintf(
   370  		"/appsec/v1/configs/%d/versions/%d/match-targets/%d",
   371  		params.ConfigID,
   372  		params.ConfigVersion,
   373  		params.TargetID,
   374  	)
   375  
   376  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil)
   377  	if err != nil {
   378  		return nil, fmt.Errorf("failed to create UpdateMatchTarget request: %w", err)
   379  	}
   380  
   381  	var result UpdateMatchTargetResponse
   382  	req.Header.Set("Content-Type", "application/json")
   383  	resp, err := p.Exec(req, &result, params.JsonPayloadRaw)
   384  	if err != nil {
   385  		return nil, fmt.Errorf("update match target request failed: %w", err)
   386  	}
   387  	if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
   388  		return nil, p.Error(resp)
   389  	}
   390  
   391  	return &result, nil
   392  }
   393  
   394  func (p *appsec) CreateMatchTarget(ctx context.Context, params CreateMatchTargetRequest) (*CreateMatchTargetResponse, error) {
   395  	logger := p.Log(ctx)
   396  	logger.Debug("CreateMatchTarget")
   397  
   398  	if err := params.Validate(); err != nil {
   399  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   400  	}
   401  
   402  	uri := fmt.Sprintf(
   403  		"/appsec/v1/configs/%d/versions/%d/match-targets",
   404  		params.ConfigID,
   405  		params.ConfigVersion,
   406  	)
   407  
   408  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
   409  	if err != nil {
   410  		return nil, fmt.Errorf("failed to create CreateMatchTarget request: %w", err)
   411  	}
   412  
   413  	var result CreateMatchTargetResponse
   414  	req.Header.Set("Content-Type", "application/json")
   415  	resp, err := p.Exec(req, &result, params.JsonPayloadRaw)
   416  	if err != nil {
   417  		return nil, fmt.Errorf("create match target request failed: %w", err)
   418  	}
   419  	if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
   420  		return nil, p.Error(resp)
   421  	}
   422  
   423  	return &result, nil
   424  }
   425  
   426  func (p *appsec) RemoveMatchTarget(ctx context.Context, params RemoveMatchTargetRequest) (*RemoveMatchTargetResponse, error) {
   427  	logger := p.Log(ctx)
   428  	logger.Debug("RemoveMatchTarget")
   429  
   430  	if err := params.Validate(); err != nil {
   431  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   432  	}
   433  
   434  	uri := fmt.Sprintf("/appsec/v1/configs/%d/versions/%d/match-targets/%d", params.ConfigID, params.ConfigVersion, params.TargetID)
   435  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil)
   436  	if err != nil {
   437  		return nil, fmt.Errorf("failed to create RemoveMatchTarget request: %w", err)
   438  	}
   439  
   440  	var result RemoveMatchTargetResponse
   441  	resp, errd := p.Exec(req, nil)
   442  	if errd != nil {
   443  		return nil, fmt.Errorf("remove match target request failed: %w", err)
   444  	}
   445  
   446  	if resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusOK {
   447  		return nil, p.Error(resp)
   448  	}
   449  
   450  	return &result, nil
   451  }