phpcloudflarefirewallphp-curl

How do I update a WAF rule on Cloudflare using their API


I am trying to update a rule of a waf on Cloudflare using their API. You will see in the code that I get the rule and content first, then update the rule. All the credentials are correct

$zoneIdentifier = "123"; //Real credentials are correct (tripple checked)
$authKey = "123"; //Real credentials are correct (tripple checked)
$accountID = "123"; //Real credentials are correct (tripple checked)
$ruleId = "123"; //Real credentials are correct (tripple checked)
$filerID = "123"; //Real credentials are correct (tripple checked)

$url = "https://api.cloudflare.com/client/v4/zones/{$zoneIdentifier}/firewall/rules/{$ruleId}";

$headers = [
    "X-Auth-Email: myemail@myemail.com",
    "X-Auth-Key: {$authKey}",
    "Content-Type: application/json",
];

// Function to make a cURL request function makeCurlRequest($url, $headers, $method = "GET", $data = null)
{
$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => $method,
    CURLOPT_POSTFIELDS => $data ? json_encode($data) : null,
    CURLOPT_HTTPHEADER => $headers,
]);

$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
    return false;
}

return json_decode($response, true);
}

// Retrieve information about the rule
$responseData = makeCurlRequest($url, $headers);

if ($responseData !== false) {
// Process the response
$filter = $responseData['result']['filter'];
$expression = $filter['expression'];

// New IP address to add
$newIpAddress = "123.123.1.0"; ///Test IP

// Check Cloudflare's documentation for the correct expression syntax
$newFilterExpression = "(ip.src eq {$newIpAddress})";

// If there's an existing expression, combine it with the new one using 'or'
if ($expression) {
    $newFilterExpression = "{$expression} or {$newFilterExpression}";
}

// Updated rule details
$updatedRule = [
    "id" => $ruleId,
    "paused" => false,
    "description" => "BlockBadIP",
    "action" => "block", 
    "expression" => $newFilterExpression
];

// URL for updating the rule
$updateUrl = "https://api.cloudflare.com/client/v4/zones/{$zoneIdentifier}/firewall/rules/{$ruleId}";

// Set cURL options for the PUT request (update)
$updateResponse = makeCurlRequest($updateUrl, $headers, "PUT", $updatedRule);

// Check for cURL errors in the update response
if ($updateResponse !== false) {
    // Output the update response
} else {
    echo "Update failed.";
}
} else {
echo "Failed to retrieve rule information.";
}

I have done a lot of testing, I can change the name via the API, I can change the action via APIbut the expression never change.

For the $updatedRule variable i have tried

$updatedRule = [
    "id" => $ruleId,
    "paused" => false,
    "description" => "BlockBadIP",
    "action" => "block", 
    "expression" => $newFilterExpression
]; 

and

$updatedRule = [
    "id" => $ruleId,
    "paused" => false,
    "description" => "BlockBadIP",
    "action" => "block", 
    "filter" => [
        "id" => $filerID,
        "expression" => $newFilterExpression
    ],
];. 

Not of these two change the expression, but like I said, I can change the name and the action

There are no errors. The response indicate that success:

["success"]=> bool(true) ["errors"]=> array(0) { } ["messages"]=> array(0)

Yet, the expression is not updated.

Expression sample in plain text: (ip.src eq 123.123.1.0) or (ip.src eq 123.123.1.1) or (ip.src eq 123.123.1.2)

What am I doing wrong?


Solution

  • With the help of the Cloudflare Community, I managed to solve the problem. I used the wrong endpoint for the purpose I was attempting. The correct endpoint for updating a rule in the firewall is https://api.cloudflare.com/client/v4/zones/{$zoneIdentifier}/filters/{$filterID}.