Skip to content
Documentation menu

Docs / Reference / Security

WAFCustomRule

WAFCustomRule manages one WAF custom rule in a zone, in its http_request_firewall_custom phase: the rule blocks or challenges the requests its expression matches, or lets them skip other security features. A Free plan allows five custom rules.

API version
kflare.dev/v1alpha1
Scope
Namespaced
Short name
cfwaf
Token permission
Zone · Zone WAF · Edit

Example

Every field, with the sample's values. The live lines are the repository's sample, which applies as it is; the commented ones are the other fields, filled from other samples where one sets them. Some exclude each other, so check the rules before you uncomment several.

wafcustomrule.yaml
apiVersion: kflare.dev/v1alpha1
kind: WAFCustomRule
metadata:
  name: example-wafcustomrule
  namespace: default
spec:
  zoneRef:
    name: example-zone
  expression: http.request.uri.path wildcard "/admin*" and not ip.src in {192.0.2.0/24}
  description: Block the admin pages from outside the office
  priority: 10
  action: block
  # enabled: true
  # logging:
  #   enabled: true
  # phase: current
  # phases:
  #   - http_ratelimit
  # products:
  #   - bic
  # response:
  #   content: <content>
  #   contentType: text/html  # one of: text/html, text/plain, application/json, text/xml
  #   statusCode: 400
  # ruleset: current

Spec

What you set, with the limits the API server enforces.

FieldDescription
action
stringrequired

Action is what Cloudflare does with the requests the rule matches. Free plans can take every action but log.

- block: blocks them, with Cloudflare's block page or the rule's response. - challenge: issues an interactive challenge. - js_challenge: issues a JavaScript challenge. - managed_challenge: issues the challenge Cloudflare picks for the visitor. - skip: lets them skip the security features its parameters name. - log: only logs them (Enterprise plans).

One of: block, challenge, js_challenge, managed_challenge, skip, log

description
string

Description is shown with the rule in the Cloudflare dashboard.

Limits: at most 4096 characters

enabled
boolean

Enabled turns the rule on or off without deleting it.

Default: true

expression
stringrequired

Expression selects the requests the rule applies to, in Cloudflare's Rules language, for example http.request.uri.path eq "/admin". Cloudflare validates it; the fields and operators it may use depend on the zone's plan.

Limits: 1 to 4096 characters

logging
object

Logging says whether a skip rule records the requests it matches in Security Events. Cloudflare logs them unless enabled is false.

logging.enabled
booleanrequired

Enabled logs the requests the skip rule matches.

phase
string

Phase, set to current, skips the rest of the phase: the zone's custom rules after this one, and the custom rulesets the phase runs after them. It can be combined with products, but not with phases or ruleset.

One of: current

phases
[]string

Phases skips later security phases: rate limiting rules (http_ratelimit), managed rules (http_request_firewall_managed) and Super Bot Fight Mode (http_request_sbfm).

One of: http_ratelimit, http_request_firewall_managed, http_request_sbfm

Limits: at least 1 item

priority
integer

Priority orders the rules kflare manages in a zone and phase: lower runs first, and rules with the same priority run in order of namespace and name. Rules created outside kflare keep their place.

Limits: format int32

products
[]string

Products skips security features of the previous generation: zone lockdown (zoneLockdown), user agent blocking (uaBlock), browser integrity check (bic), hotlink protection (hot), security level (securityLevel), the previous rate limiting (rateLimit) and the previous managed rules (waf).

One of: bic, hot, rateLimit, securityLevel, uaBlock, waf, zoneLockdown

Limits: at least 1 item

response
object

Response replaces Cloudflare's block page for a block rule. It needs a Pro plan or higher: Free zones are not entitled to a custom response.

response.content
stringrequired

Content is the response body, of at most 2,048 bytes.

Limits: 1 to 2048 characters

response.contentType
stringrequired

ContentType is the response's content type.

One of: text/html, text/plain, application/json, text/xml

response.statusCode
integerrequired

StatusCode is the response's HTTP status code, from 400 to 499.

Limits: at least 400 and at most 499; format int64

ruleset
string

Ruleset, set to current, skips the zone's custom rules that run after this one.

One of: current

zoneRef
objectrequiredimmutable

ZoneRef references the Zone, in the same namespace, the rule belongs to. Immutable after creation.

zoneRef.name
string

Name of the referent. This field is effectively required, but due to backwards compatibility is allowed to be empty. Instances of this type with an empty value here are almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

Default: ""

Rules

Checked across fields when the resource is applied.

  • response is allowed only with action block
  • phase is allowed only with action skip
  • phases is allowed only with action skip
  • products is allowed only with action skip
  • ruleset is allowed only with action skip
  • action skip must set at least one of phase, phases, products and ruleset
  • logging is allowed only with action skip
  • phase cannot be used with phases
  • phase cannot be used with ruleset

Status

What kflare reports. conditions holds the Ready condition, whose reason says why a resource isn't ready.

FieldDescription
cloudflareMetadata
object

CloudflareMetadata identifies the rule in Cloudflare.

cloudflareMetadata.ref
string

Ref is the rule's ref, which kflare derives from the resource's kind, namespace and name. kflare finds the rule it manages by its ref.

cloudflareMetadata.ruleID
string

RuleID is the rule's Cloudflare ID.

cloudflareMetadata.rulesetID
string

RulesetID is the zone's entry point ruleset for the rule's phase.

cloudflareMetadata.version
string

Version is the rule's version, which Cloudflare increments whenever the rule changes.

cloudflareMetadata.zoneID
string

ZoneID is the Cloudflare zone the rule is in.

conditions
[]object

Conditions represent the latest available observations of the rule's state.

kubectl get

The columns kubectl get wafcustomrules prints.

ColumnSource
ACTION.spec.action
PRIORITY.spec.priority
RULE ID.status.cloudflareMetadata.ruleID
READY.status.conditions[?(@.type=="Ready")].status
AGE.metadata.creationTimestamp

Samples

From the repository's config/samples, comments included.

cloudflare_v1alpha1_wafcustomrule.yaml
# Generated by kflare-gen from generator/generator.yaml. DO NOT EDIT.
#
# WAFCustomRule is the Schema for the wafcustomrules API.
# It manages one WAF custom rule in a zone, in its
# http_request_firewall_custom phase: the rule blocks or challenges the
# requests its expression matches, or lets them skip other security
# features. A Free plan allows five custom rules.
apiVersion: kflare.dev/v1alpha1
kind: WAFCustomRule
metadata:
  name: example-wafcustomrule
  namespace: default
spec:
  zoneRef:
    name: example-zone
  expression: http.request.uri.path wildcard "/admin*" and not ip.src in {192.0.2.0/24}
  description: Block the admin pages from outside the office
  priority: 10
  action: block

On GitHub