dnscontrol/pkg/cloudflare-go/lockdown.go
Tom Limoncelli 7fd6a74e0c
CLOUDFLAREAPI: CF_REDIRECT/CF_TEMP_REDIRECT should dtrt using Single Redirects (#3002)
Co-authored-by: Josh Zhang <jzhang1@stackoverflow.com>
2024-06-18 17:38:50 -04:00

192 lines
6.4 KiB
Go

package cloudflare
import (
"context"
"fmt"
"net/http"
"time"
"github.com/goccy/go-json"
)
// ZoneLockdown represents a Zone Lockdown rule. A rule only permits access to
// the provided URL pattern(s) from the given IP address(es) or subnet(s).
type ZoneLockdown struct {
ID string `json:"id"`
Description string `json:"description"`
URLs []string `json:"urls"`
Configurations []ZoneLockdownConfig `json:"configurations"`
Paused bool `json:"paused"`
Priority int `json:"priority,omitempty"`
CreatedOn *time.Time `json:"created_on,omitempty"`
ModifiedOn *time.Time `json:"modified_on,omitempty"`
}
// ZoneLockdownConfig represents a Zone Lockdown config, which comprises
// a Target ("ip" or "ip_range") and a Value (an IP address or IP+mask,
// respectively.)
type ZoneLockdownConfig struct {
Target string `json:"target"`
Value string `json:"value"`
}
// ZoneLockdownResponse represents a response from the Zone Lockdown endpoint.
type ZoneLockdownResponse struct {
Result ZoneLockdown `json:"result"`
Response
ResultInfo `json:"result_info"`
}
// ZoneLockdownListResponse represents a response from the List Zone Lockdown
// endpoint.
type ZoneLockdownListResponse struct {
Result []ZoneLockdown `json:"result"`
Response
ResultInfo `json:"result_info"`
}
// ZoneLockdownCreateParams contains required and optional params
// for creating a zone lockdown.
type ZoneLockdownCreateParams struct {
Description string `json:"description"`
URLs []string `json:"urls"`
Configurations []ZoneLockdownConfig `json:"configurations"`
Paused bool `json:"paused"`
Priority int `json:"priority,omitempty"`
}
// ZoneLockdownUpdateParams contains required and optional params
// for updating a zone lockdown.
type ZoneLockdownUpdateParams struct {
ID string `json:"id"`
Description string `json:"description"`
URLs []string `json:"urls"`
Configurations []ZoneLockdownConfig `json:"configurations"`
Paused bool `json:"paused"`
Priority int `json:"priority,omitempty"`
}
type LockdownListParams struct {
ResultInfo
}
// CreateZoneLockdown creates a Zone ZoneLockdown rule for the given zone ID.
//
// API reference: https://api.cloudflare.com/#zone-ZoneLockdown-create-a-ZoneLockdown-rule
func (api *API) CreateZoneLockdown(ctx context.Context, rc *ResourceContainer, params ZoneLockdownCreateParams) (ZoneLockdown, error) {
uri := fmt.Sprintf("/zones/%s/firewall/lockdowns", rc.Identifier)
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
if err != nil {
return ZoneLockdown{}, err
}
response := &ZoneLockdownResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return ZoneLockdown{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return response.Result, nil
}
// UpdateZoneLockdown updates a Zone ZoneLockdown rule (based on the ID) for the given zone ID.
//
// API reference: https://api.cloudflare.com/#zone-ZoneLockdown-update-ZoneLockdown-rule
func (api *API) UpdateZoneLockdown(ctx context.Context, rc *ResourceContainer, params ZoneLockdownUpdateParams) (ZoneLockdown, error) {
uri := fmt.Sprintf("/zones/%s/firewall/lockdowns/%s", rc.Identifier, params.ID)
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
if err != nil {
return ZoneLockdown{}, err
}
response := &ZoneLockdownResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return ZoneLockdown{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return response.Result, nil
}
// DeleteZoneLockdown deletes a Zone ZoneLockdown rule (based on the ID) for the given zone ID.
//
// API reference: https://api.cloudflare.com/#zone-ZoneLockdown-delete-ZoneLockdown-rule
func (api *API) DeleteZoneLockdown(ctx context.Context, rc *ResourceContainer, id string) (ZoneLockdown, error) {
uri := fmt.Sprintf("/zones/%s/firewall/lockdowns/%s", rc.Identifier, id)
res, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
if err != nil {
return ZoneLockdown{}, err
}
response := &ZoneLockdownResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return ZoneLockdown{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return response.Result, nil
}
// ZoneLockdown retrieves a Zone ZoneLockdown rule (based on the ID) for the given zone ID.
//
// API reference: https://api.cloudflare.com/#zone-ZoneLockdown-ZoneLockdown-rule-details
func (api *API) ZoneLockdown(ctx context.Context, rc *ResourceContainer, id string) (ZoneLockdown, error) {
uri := fmt.Sprintf("/zones/%s/firewall/lockdowns/%s", rc.Identifier, id)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return ZoneLockdown{}, err
}
response := &ZoneLockdownResponse{}
err = json.Unmarshal(res, &response)
if err != nil {
return ZoneLockdown{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
}
return response.Result, nil
}
// ListZoneLockdowns retrieves every Zone ZoneLockdown rules for a given zone ID.
//
// Automatically paginates all results unless `params.PerPage` and `params.Page`
// is set.
//
// API reference: https://api.cloudflare.com/#zone-ZoneLockdown-list-ZoneLockdown-rules
func (api *API) ListZoneLockdowns(ctx context.Context, rc *ResourceContainer, params LockdownListParams) ([]ZoneLockdown, *ResultInfo, error) {
autoPaginate := true
if params.PerPage >= 1 || params.Page >= 1 {
autoPaginate = false
}
if params.PerPage < 1 {
params.PerPage = 50
}
if params.Page < 1 {
params.Page = 1
}
var zoneLockdowns []ZoneLockdown
var zResponse ZoneLockdownListResponse
for {
zResponse = ZoneLockdownListResponse{}
uri := buildURI(fmt.Sprintf("/zones/%s/firewall/lockdowns", rc.Identifier), params)
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return []ZoneLockdown{}, &ResultInfo{}, err
}
err = json.Unmarshal(res, &zResponse)
if err != nil {
return []ZoneLockdown{}, &ResultInfo{}, fmt.Errorf("failed to unmarshal filters JSON data: %w", err)
}
zoneLockdowns = append(zoneLockdowns, zResponse.Result...)
params.ResultInfo = zResponse.ResultInfo.Next()
if params.ResultInfo.Done() || !autoPaginate {
break
}
}
return zoneLockdowns, &zResponse.ResultInfo, nil
}