Skip to content

Commit

Permalink
Merge pull request #1413 from djhworld/dharper/APISHI-2365
Browse files Browse the repository at this point in the history
Add support for Get/Patch API Shield API Discovery Operations
  • Loading branch information
jacobbednarz committed Oct 5, 2023
2 parents 217beeb + 80d9650 commit 69ddaca
Show file tree
Hide file tree
Showing 3 changed files with 576 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/1413.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
api_shield_discovery: Add support for Get/Patch API Shield API Discovery Operations
```
190 changes: 190 additions & 0 deletions api_shield_api_discovery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package cloudflare

import (
"context"
"fmt"
"net/http"
"time"

"github.com/goccy/go-json"
)

// APIShieldDiscoveryOrigin is an enumeration on what discovery engine an operation was discovered by.
type APIShieldDiscoveryOrigin string

const (

// APIShieldDiscoveryOriginML discovered operations that were sourced using ML API Discovery.
APIShieldDiscoveryOriginML APIShieldDiscoveryOrigin = "ML"
// APIShieldDiscoveryOriginSessionIdentifier discovered operations that were sourced using Session Identifier
// API Discovery.
APIShieldDiscoveryOriginSessionIdentifier APIShieldDiscoveryOrigin = "SessionIdentifier"
)

// APIShieldDiscoveryState is an enumeration on states a discovery operation can be in.
type APIShieldDiscoveryState string

const (
// APIShieldDiscoveryStateReview discovered operations that are not saved into API Shield Endpoint Management.
APIShieldDiscoveryStateReview APIShieldDiscoveryState = "review"
// APIShieldDiscoveryStateSaved discovered operations that are already saved into API Shield Endpoint Management.
APIShieldDiscoveryStateSaved APIShieldDiscoveryState = "saved"
// APIShieldDiscoveryStateIgnored discovered operations that have been marked as ignored.
APIShieldDiscoveryStateIgnored APIShieldDiscoveryState = "ignored"
)

// APIShieldDiscoveryOperation is an operation that was discovered by API Discovery.
type APIShieldDiscoveryOperation struct {
// ID represents the ID of the operation, formatted as UUID
ID string `json:"id"`
// Origin represents the API discovery engine(s) that discovered this operation
Origin []APIShieldDiscoveryOrigin `json:"origin"`
// State represents the state of operation in API Discovery
State APIShieldDiscoveryState `json:"state"`
// LastUpdated timestamp of when this operation was last updated
LastUpdated *time.Time `json:"last_updated"`
// Features are additional data about the operation
Features map[string]any `json:"features,omitempty"`

Method string `json:"method"`
Host string `json:"host"`
Endpoint string `json:"endpoint"`
}

// ListAPIShieldDiscoveryOperationsParams represents the parameters to pass when retrieving discovered operations.
//
// API documentation: https://developers.cloudflare.com/api/operations/api-shield-api-discovery-retrieve-discovered-operations-on-a-zone
type ListAPIShieldDiscoveryOperationsParams struct {
// Direction to order results.
Direction string `url:"direction,omitempty"`
// OrderBy when requesting a feature, the feature keys are available for ordering as well, e.g., thresholds.suggested_threshold.
OrderBy string `url:"order,omitempty"`
// Hosts filters results to only include the specified hosts.
Hosts []string `url:"host,omitempty"`
// Methods filters results to only include the specified methods.
Methods []string `url:"method,omitempty"`
// Endpoint filters results to only include endpoints containing this pattern.
Endpoint string `url:"endpoint,omitempty"`
// Diff when true, only return API Discovery results that are not saved into API Shield Endpoint Management
Diff bool `url:"diff,omitempty"`
// Origin filters results to only include discovery results sourced from a particular discovery engine
// See APIShieldDiscoveryOrigin for valid values.
Origin APIShieldDiscoveryOrigin `url:"origin,omitempty"`
// State filters results to only include discovery results in a particular state
// See APIShieldDiscoveryState for valid values.
State APIShieldDiscoveryState `url:"state,omitempty"`

// Pagination options to apply to the request.
PaginationOptions
}

// UpdateAPIShieldDiscoveryOperationParams represents the parameters to pass to patch a discovery operation
//
// API documentation: https://developers.cloudflare.com/api/operations/api-shield-api-patch-discovered-operation
type UpdateAPIShieldDiscoveryOperationParams struct {
// OperationID is the ID, formatted as UUID, of the operation to be updated
OperationID string `json:"-" url:"-"`
State APIShieldDiscoveryState `json:"state" url:"-"`
}

// UpdateAPIShieldDiscoveryOperationsParams maps discovery operation IDs to PatchAPIShieldDiscoveryOperation structs
//
// Example:
//
// UpdateAPIShieldDiscoveryOperations{
// "99522293-a505-45e5-bbad-bbc339f5dc40": PatchAPIShieldDiscoveryOperation{ State: "review" },
// }
//
// API documentation: https://developers.cloudflare.com/api/operations/api-shield-api-patch-discovered-operations
type UpdateAPIShieldDiscoveryOperationsParams map[string]UpdateAPIShieldDiscoveryOperation

// UpdateAPIShieldDiscoveryOperation represents the state to set on a discovery operation.
type UpdateAPIShieldDiscoveryOperation struct {
// State is the state to set on the operation
State APIShieldDiscoveryState `json:"state" url:"-"`
}

// APIShieldListDiscoveryOperationsResponse represents the response from the api_gateway/discovery/operations endpoint.
type APIShieldListDiscoveryOperationsResponse struct {
Result []APIShieldDiscoveryOperation `json:"result"`
ResultInfo `json:"result_info"`
Response
}

// APIShieldPatchDiscoveryOperationResponse represents the response from the PATCH api_gateway/discovery/operations/{id} endpoint.
type APIShieldPatchDiscoveryOperationResponse struct {
Result UpdateAPIShieldDiscoveryOperation `json:"result"`
Response
}

// APIShieldPatchDiscoveryOperationsResponse represents the response from the PATCH api_gateway/discovery/operations endpoint.
type APIShieldPatchDiscoveryOperationsResponse struct {
Result UpdateAPIShieldDiscoveryOperationsParams `json:"result"`
Response
}

// ListAPIShieldDiscoveryOperations retrieve the most up to date view of discovered operations.
//
// API documentation: https://developers.cloudflare.com/api/operations/api-shield-api-discovery-retrieve-discovered-operations-on-a-zone
func (api *API) ListAPIShieldDiscoveryOperations(ctx context.Context, rc *ResourceContainer, params ListAPIShieldDiscoveryOperationsParams) ([]APIShieldDiscoveryOperation, ResultInfo, error) {
uri := buildURI(fmt.Sprintf("/zones/%s/api_gateway/discovery/operations", rc.Identifier), params)

res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, ResultInfo{}, err
}

var asResponse APIShieldListDiscoveryOperationsResponse
err = json.Unmarshal(res, &asResponse)
if err != nil {
return nil, ResultInfo{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return asResponse.Result, asResponse.ResultInfo, nil
}

// UpdateAPIShieldDiscoveryOperation updates certain fields on a discovered operation.
//
// API Documentation: https://developers.cloudflare.com/api/operations/api-shield-api-patch-discovered-operation
func (api *API) UpdateAPIShieldDiscoveryOperation(ctx context.Context, rc *ResourceContainer, params UpdateAPIShieldDiscoveryOperationParams) (*UpdateAPIShieldDiscoveryOperation, error) {
if params.OperationID == "" {
return nil, fmt.Errorf("operation ID must be provided")
}

uri := fmt.Sprintf("/zones/%s/api_gateway/discovery/operations/%s", rc.Identifier, params.OperationID)

res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params)
if err != nil {
return nil, err
}

// Result should be the updated schema that was patched
var asResponse APIShieldPatchDiscoveryOperationResponse
err = json.Unmarshal(res, &asResponse)
if err != nil {
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return &asResponse.Result, nil
}

// UpdateAPIShieldDiscoveryOperations bulk updates certain fields on multiple discovered operations
//
// API documentation: https://developers.cloudflare.com/api/operations/api-shield-api-patch-discovered-operations
func (api *API) UpdateAPIShieldDiscoveryOperations(ctx context.Context, rc *ResourceContainer, params UpdateAPIShieldDiscoveryOperationsParams) (*UpdateAPIShieldDiscoveryOperationsParams, error) {
uri := fmt.Sprintf("/zones/%s/api_gateway/discovery/operations", rc.Identifier)

res, err := api.makeRequestContext(ctx, http.MethodPatch, uri, params)
if err != nil {
return nil, err
}

// Result should be the updated schema that was patched
var asResponse APIShieldPatchDiscoveryOperationsResponse
err = json.Unmarshal(res, &asResponse)
if err != nil {
return nil, fmt.Errorf("%s: %w", errUnmarshalError, err)
}

return &asResponse.Result, nil
}

0 comments on commit 69ddaca

Please sign in to comment.