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?
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}
.