mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-11-11 17:00:30 +08:00
244 lines
7.6 KiB
Go
244 lines
7.6 KiB
Go
package cloudflare
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/goccy/go-json"
|
|
)
|
|
|
|
// FirewallRule is the struct of the firewall rule.
|
|
type FirewallRule struct {
|
|
ID string `json:"id,omitempty"`
|
|
Paused bool `json:"paused"`
|
|
Description string `json:"description"`
|
|
Action string `json:"action"`
|
|
Priority interface{} `json:"priority"`
|
|
Filter Filter `json:"filter"`
|
|
Products []string `json:"products,omitempty"`
|
|
Ref string `json:"ref,omitempty"`
|
|
CreatedOn time.Time `json:"created_on,omitempty"`
|
|
ModifiedOn time.Time `json:"modified_on,omitempty"`
|
|
}
|
|
|
|
// FirewallRulesDetailResponse is the API response for the firewall
|
|
// rules.
|
|
type FirewallRulesDetailResponse struct {
|
|
Result []FirewallRule `json:"result"`
|
|
ResultInfo `json:"result_info"`
|
|
Response
|
|
}
|
|
|
|
// FirewallRuleResponse is the API response that is returned
|
|
// for requesting a single firewall rule on a zone.
|
|
type FirewallRuleResponse struct {
|
|
Result FirewallRule `json:"result"`
|
|
ResultInfo `json:"result_info"`
|
|
Response
|
|
}
|
|
|
|
// FirewallRuleCreateParams contains required and optional params
|
|
// for creating a firewall rule.
|
|
type FirewallRuleCreateParams struct {
|
|
ID string `json:"id,omitempty"`
|
|
Paused bool `json:"paused"`
|
|
Description string `json:"description"`
|
|
Action string `json:"action"`
|
|
Priority interface{} `json:"priority"`
|
|
Filter Filter `json:"filter"`
|
|
Products []string `json:"products,omitempty"`
|
|
Ref string `json:"ref,omitempty"`
|
|
}
|
|
|
|
// FirewallRuleUpdateParams contains required and optional params
|
|
// for updating a firewall rule.
|
|
type FirewallRuleUpdateParams struct {
|
|
ID string `json:"id"`
|
|
Paused bool `json:"paused"`
|
|
Description string `json:"description"`
|
|
Action string `json:"action"`
|
|
Priority interface{} `json:"priority"`
|
|
Filter Filter `json:"filter"`
|
|
Products []string `json:"products,omitempty"`
|
|
Ref string `json:"ref,omitempty"`
|
|
}
|
|
|
|
type FirewallRuleListParams struct {
|
|
ResultInfo
|
|
}
|
|
|
|
// FirewallRules returns all firewall rules.
|
|
//
|
|
// Automatically paginates all results unless `params.PerPage` and `params.Page`
|
|
// is set.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/get/#get-all-rules
|
|
func (api *API) FirewallRules(ctx context.Context, rc *ResourceContainer, params FirewallRuleListParams) ([]FirewallRule, *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 firewallRules []FirewallRule
|
|
var fResponse FirewallRulesDetailResponse
|
|
for {
|
|
fResponse = FirewallRulesDetailResponse{}
|
|
uri := buildURI(fmt.Sprintf("/zones/%s/firewall/rules", rc.Identifier), params)
|
|
|
|
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
|
|
if err != nil {
|
|
return []FirewallRule{}, &ResultInfo{}, err
|
|
}
|
|
|
|
err = json.Unmarshal(res, &fResponse)
|
|
if err != nil {
|
|
return []FirewallRule{}, &ResultInfo{}, fmt.Errorf("failed to unmarshal filters JSON data: %w", err)
|
|
}
|
|
|
|
firewallRules = append(firewallRules, fResponse.Result...)
|
|
params.ResultInfo = fResponse.ResultInfo.Next()
|
|
|
|
if params.ResultInfo.Done() || !autoPaginate {
|
|
break
|
|
}
|
|
}
|
|
|
|
return firewallRules, &fResponse.ResultInfo, nil
|
|
}
|
|
|
|
// FirewallRule returns a single firewall rule based on the ID.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/get/#get-by-rule-id
|
|
func (api *API) FirewallRule(ctx context.Context, rc *ResourceContainer, firewallRuleID string) (FirewallRule, error) {
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules/%s", rc.Identifier, firewallRuleID)
|
|
|
|
res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
|
|
if err != nil {
|
|
return FirewallRule{}, err
|
|
}
|
|
|
|
var firewallRuleResponse FirewallRuleResponse
|
|
err = json.Unmarshal(res, &firewallRuleResponse)
|
|
if err != nil {
|
|
return FirewallRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
|
|
}
|
|
|
|
return firewallRuleResponse.Result, nil
|
|
}
|
|
|
|
// CreateFirewallRules creates new firewall rules.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/post/
|
|
func (api *API) CreateFirewallRules(ctx context.Context, rc *ResourceContainer, params []FirewallRuleCreateParams) ([]FirewallRule, error) {
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules", rc.Identifier)
|
|
|
|
res, err := api.makeRequestContext(ctx, http.MethodPost, uri, params)
|
|
if err != nil {
|
|
return []FirewallRule{}, err
|
|
}
|
|
|
|
var firewallRulesDetailResponse FirewallRulesDetailResponse
|
|
err = json.Unmarshal(res, &firewallRulesDetailResponse)
|
|
if err != nil {
|
|
return []FirewallRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
|
|
}
|
|
|
|
return firewallRulesDetailResponse.Result, nil
|
|
}
|
|
|
|
// UpdateFirewallRule updates a single firewall rule.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/put/#update-a-single-rule
|
|
func (api *API) UpdateFirewallRule(ctx context.Context, rc *ResourceContainer, params FirewallRuleUpdateParams) (FirewallRule, error) {
|
|
if params.ID == "" {
|
|
return FirewallRule{}, fmt.Errorf("firewall rule ID cannot be empty")
|
|
}
|
|
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules/%s", rc.Identifier, params.ID)
|
|
|
|
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
|
|
if err != nil {
|
|
return FirewallRule{}, err
|
|
}
|
|
|
|
var firewallRuleResponse FirewallRuleResponse
|
|
err = json.Unmarshal(res, &firewallRuleResponse)
|
|
if err != nil {
|
|
return FirewallRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
|
|
}
|
|
|
|
return firewallRuleResponse.Result, nil
|
|
}
|
|
|
|
// UpdateFirewallRules updates a single firewall rule.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/put/#update-multiple-rules
|
|
func (api *API) UpdateFirewallRules(ctx context.Context, rc *ResourceContainer, params []FirewallRuleUpdateParams) ([]FirewallRule, error) {
|
|
for _, firewallRule := range params {
|
|
if firewallRule.ID == "" {
|
|
return []FirewallRule{}, fmt.Errorf("firewall ID cannot be empty")
|
|
}
|
|
}
|
|
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules", rc.Identifier)
|
|
|
|
res, err := api.makeRequestContext(ctx, http.MethodPut, uri, params)
|
|
if err != nil {
|
|
return []FirewallRule{}, err
|
|
}
|
|
|
|
var firewallRulesDetailResponse FirewallRulesDetailResponse
|
|
err = json.Unmarshal(res, &firewallRulesDetailResponse)
|
|
if err != nil {
|
|
return []FirewallRule{}, fmt.Errorf("%s: %w", errUnmarshalError, err)
|
|
}
|
|
|
|
return firewallRulesDetailResponse.Result, nil
|
|
}
|
|
|
|
// DeleteFirewallRule deletes a single firewall rule.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/delete/#delete-a-single-rule
|
|
func (api *API) DeleteFirewallRule(ctx context.Context, rc *ResourceContainer, firewallRuleID string) error {
|
|
if firewallRuleID == "" {
|
|
return fmt.Errorf("firewall rule ID cannot be empty")
|
|
}
|
|
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules/%s", rc.Identifier, firewallRuleID)
|
|
|
|
_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteFirewallRules deletes multiple firewall rules at once.
|
|
//
|
|
// API reference: https://developers.cloudflare.com/firewall/api/cf-firewall-rules/delete/#delete-multiple-rules
|
|
func (api *API) DeleteFirewallRules(ctx context.Context, rc *ResourceContainer, firewallRuleIDs []string) error {
|
|
v := url.Values{}
|
|
|
|
for _, ruleID := range firewallRuleIDs {
|
|
v.Add("id", ruleID)
|
|
}
|
|
|
|
uri := fmt.Sprintf("/zones/%s/firewall/rules?%s", rc.Identifier, v.Encode())
|
|
|
|
_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|