Cloudflare WAF Rules Management in Java

Cloudflare WAF (Web Application Firewall) provides powerful security protection for web applications. This comprehensive guide covers managing Cloudflare WAF rules programmatically using Java, including rule creation, deployment, monitoring, and automation.

Cloudflare API Client Implementation

Example 1: Core Cloudflare API Client

package com.example.cloudflare.waf;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class CloudflareApiClient {
private final OkHttpClient httpClient;
private final String apiToken;
private final String baseUrl;
private final ObjectMapper objectMapper;
public CloudflareApiClient(String apiToken, String baseUrl) {
this.apiToken = apiToken;
this.baseUrl = baseUrl;
this.objectMapper = new ObjectMapper();
this.httpClient = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build();
}
public CloudflareResponse executeRequest(String method, String endpoint, 
Object body) throws CloudflareException {
try {
Request.Builder requestBuilder = new Request.Builder()
.url(baseUrl + endpoint)
.header("Authorization", "Bearer " + apiToken)
.header("Content-Type", "application/json");
if (body != null) {
String jsonBody = objectMapper.writeValueAsString(body);
RequestBody requestBody = RequestBody.create(
jsonBody, MediaType.parse("application/json"));
requestBuilder.method(method, requestBody);
} else {
requestBuilder.method(method, null);
}
Request request = requestBuilder.build();
try (Response response = httpClient.newCall(request).execute()) {
String responseBody = response.body() != null ? 
response.body().string() : "";
if (!response.isSuccessful()) {
throw new CloudflareException(
"API request failed: " + response.code() + " - " + responseBody);
}
return objectMapper.readValue(responseBody, CloudflareResponse.class);
}
} catch (IOException e) {
throw new CloudflareException("Failed to execute API request", e);
}
}
public static class CloudflareResponse {
private boolean success;
private Object result;
private Object[] errors;
private Object[] messages;
// Getters and setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public Object getResult() { return result; }
public void setResult(Object result) { this.result = result; }
public Object[] getErrors() { return errors; }
public void setErrors(Object[] errors) { this.errors = errors; }
public Object[] getMessages() { return messages; }
public void setMessages(Object[] messages) { this.messages = messages; }
}
public static class CloudflareException extends Exception {
public CloudflareException(String message) {
super(message);
}
public CloudflareException(String message, Throwable cause) {
super(message, cause);
}
}
}

WAF Rule Management

Example 2: WAF Rule Manager

package com.example.cloudflare.waf;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.*;
public class WafRuleManager {
private final CloudflareApiClient apiClient;
public WafRuleManager(CloudflareApiClient apiClient) {
this.apiClient = apiClient;
}
public List<WafRule> listRules(String zoneId) throws CloudflareException {
String endpoint = String.format("/zones/%s/firewall/rules", zoneId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
List<WafRule> rules = new ArrayList<>();
if (response.getResult() instanceof ArrayNode) {
ArrayNode rulesArray = (ArrayNode) response.getResult();
for (JsonNode ruleNode : rulesArray) {
rules.add(parseWafRule(ruleNode));
}
}
return rules;
}
public WafRule createRule(String zoneId, WafRule rule) throws CloudflareException {
String endpoint = String.format("/zones/%s/firewall/rules", zoneId);
ObjectNode requestBody = createRuleRequestBody(rule);
CloudflareResponse response = apiClient.executeRequest("POST", endpoint, requestBody);
return parseWafRule((JsonNode) response.getResult());
}
public WafRule updateRule(String zoneId, String ruleId, WafRule rule) 
throws CloudflareException {
String endpoint = String.format("/zones/%s/firewall/rules/%s", zoneId, ruleId);
ObjectNode requestBody = createRuleRequestBody(rule);
CloudflareResponse response = apiClient.executeRequest("PUT", endpoint, requestBody);
return parseWafRule((JsonNode) response.getResult());
}
public void deleteRule(String zoneId, String ruleId) throws CloudflareException {
String endpoint = String.format("/zones/%s/firewall/rules/%s", zoneId, ruleId);
apiClient.executeRequest("DELETE", endpoint, null);
}
public WafRule getRule(String zoneId, String ruleId) throws CloudflareException {
String endpoint = String.format("/zones/%s/firewall/rules/%s", zoneId, ruleId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
return parseWafRule((JsonNode) response.getResult());
}
private ObjectNode createRuleRequestBody(WafRule rule) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode requestBody = mapper.createObjectNode();
ArrayNode rulesArray = mapper.createArrayNode();
ObjectNode ruleNode = mapper.createObjectNode();
// Basic rule properties
if (rule.getDescription() != null) {
ruleNode.put("description", rule.getDescription());
}
ruleNode.put("action", rule.getAction().toString().toLowerCase());
ruleNode.put("priority", rule.getPriority());
// Filter
ObjectNode filterNode = mapper.createObjectNode();
filterNode.put("expression", rule.getFilter().getExpression());
if (rule.getFilter().getDescription() != null) {
filterNode.put("description", rule.getFilter().getDescription());
}
ruleNode.set("filter", filterNode);
// Additional properties based on action
if (rule.getAction() == WafRule.Action.BLOCK && 
rule.getBlockReason() != null) {
ruleNode.put("block_reason", rule.getBlockReason());
}
rulesArray.add(ruleNode);
requestBody.set("rules", rulesArray);
return requestBody;
}
private WafRule parseWafRule(JsonNode ruleNode) {
WafRule rule = new WafRule();
rule.setId(ruleNode.get("id").asText());
rule.setDescription(ruleNode.has("description") ? 
ruleNode.get("description").asText() : null);
rule.setAction(WafRule.Action.valueOf(
ruleNode.get("action").asText().toUpperCase()));
rule.setPriority(ruleNode.get("priority").asInt());
JsonNode filterNode = ruleNode.get("filter");
WafFilter filter = new WafFilter();
filter.setId(filterNode.get("id").asText());
filter.setExpression(filterNode.get("expression").asText());
filter.setDescription(filterNode.has("description") ? 
filterNode.get("description").asText() : null);
rule.setFilter(filter);
if (ruleNode.has("block_reason")) {
rule.setBlockReason(ruleNode.get("block_reason").asText());
}
return rule;
}
public static class WafRule {
public enum Action {
BLOCK, CHALLENGE, JS_CHALLENGE, ALLOW, LOG, BYPASS
}
private String id;
private String description;
private Action action;
private int priority;
private WafFilter filter;
private String blockReason;
// Constructors
public WafRule() {}
public WafRule(String description, Action action, int priority, 
WafFilter filter) {
this.description = description;
this.action = action;
this.priority = priority;
this.filter = filter;
}
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public Action getAction() { return action; }
public void setAction(Action action) { this.action = action; }
public int getPriority() { return priority; }
public void setPriority(int priority) { this.priority = priority; }
public WafFilter getFilter() { return filter; }
public void setFilter(WafFilter filter) { this.filter = filter; }
public String getBlockReason() { return blockReason; }
public void setBlockReason(String blockReason) { this.blockReason = blockReason; }
}
public static class WafFilter {
private String id;
private String expression;
private String description;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getExpression() { return expression; }
public void setExpression(String expression) { this.expression = expression; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
}
}

Security Rule Templates

Example 3: Common WAF Rule Templates

package com.example.cloudflare.waf;
import java.util.*;
public class WafRuleTemplates {
public static WafRuleManager.WafRule createSqlInjectionRule() {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("(http.request.uri.query \"[*]\" contains \"union select\") or " +
"(http.request.uri.query \"[*]\" contains \"drop table\") or " +
"(http.request.uri.query \"[*]\" contains \"insert into\") or " +
"(http.request.uri.query \"[*]\" contains \"delete from\") or " +
"(http.request.uri.query \"[*]\" contains \"update set\")");
filter.setDescription("SQL Injection patterns");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Block SQL Injection Attempts",
WafRuleManager.WafRule.Action.BLOCK,
1,
filter
);
rule.setBlockReason("SQL Injection detected");
return rule;
}
public static WafRuleManager.WafRule createXssRule() {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("(http.request.uri.query \"[*]\" contains \"<script>\") or " +
"(http.request.uri.query \"[*]\" contains \"javascript:\") or " +
"(http.request.uri.query \"[*]\" contains \"onload=\") or " +
"(http.request.uri.query \"[*]\" contains \"onerror=\")");
filter.setDescription("XSS attack patterns");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Block XSS Attempts",
WafRuleManager.WafRule.Action.BLOCK,
2,
filter
);
rule.setBlockReason("XSS attack detected");
return rule;
}
public static WafRuleManager.WafRule createScannerBotRule() {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("(http.user_agent contains \"nmap\") or " +
"(http.user_agent contains \"sqlmap\") or " +
"(http.user_agent contains \"nikto\") or " +
"(http.user_agent contains \"metasploit\") or " +
"(http.user_agent contains \"burpsuite\")");
filter.setDescription("Security scanner user agents");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Block Security Scanners",
WafRuleManager.WafRule.Action.BLOCK,
3,
filter
);
rule.setBlockReason("Security scanner detected");
return rule;
}
public static WafRuleManager.WafRule createRateLimitRule(int requestsPerMinute) {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression(String.format(
"(http.request.uri.path contains \"/api/\") and " +
"(cf.threat_score gt 10) and " +
"(rate_limit(\"%s\", %d))",
"api_rate_limit", requestsPerMinute
));
filter.setDescription("API rate limiting for high threat scores");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"API Rate Limiting",
WafRuleManager.WafRule.Action.BLOCK,
4,
filter
);
return rule;
}
public static WafRuleManager.WafRule createCountryBlockRule(List<String> blockedCountries) {
if (blockedCountries.isEmpty()) {
throw new IllegalArgumentException("Blocked countries list cannot be empty");
}
String countryExpression = blockedCountries.stream()
.map(country -> "ip.geoip.country eq \"" + country + "\"")
.reduce((a, b) -> a + " or " + b)
.get();
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression(countryExpression);
filter.setDescription("Block traffic from specific countries: " + blockedCountries);
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Country Blocking",
WafRuleManager.WafRule.Action.BLOCK,
5,
filter
);
rule.setBlockReason("Access from blocked country");
return rule;
}
public static WafRuleManager.WafRule createBadBotRule() {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("(cf.client.bot) and " +
"(not cf.bot_management.verified_bot) and " +
"(cf.bot_management.score lt 30)");
filter.setDescription("Block malicious bots");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Block Malicious Bots",
WafRuleManager.WafRule.Action.BLOCK,
6,
filter
);
return rule;
}
public static WafRuleManager.WafRule createSensitivePathRule() {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("(http.request.uri.path contains \"/.git/\") or " +
"(http.request.uri.path contains \"/.env\") or " +
"(http.request.uri.path contains \"/wp-admin\") or " +
"(http.request.uri.path contains \"/phpmyadmin\") or " +
"(http.request.uri.path contains \"/backup\")");
filter.setDescription("Block access to sensitive paths");
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Block Sensitive Path Access",
WafRuleManager.WafRule.Action.BLOCK,
7,
filter
);
rule.setBlockReason("Sensitive path access attempt");
return rule;
}
}

Managed Ruleset Management

Example 4: Managed Ruleset Controller

package com.example.cloudflare.waf;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.*;
public class ManagedRulesetManager {
private final CloudflareApiClient apiClient;
public ManagedRulesetManager(CloudflareApiClient apiClient) {
this.apiClient = apiClient;
}
public List<ManagedRuleset> listRulesets(String zoneId) throws CloudflareException {
String endpoint = String.format("/zones/%s/rulesets", zoneId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
List<ManagedRuleset> rulesets = new ArrayList<>();
if (response.getResult() instanceof ArrayNode) {
ArrayNode rulesetsArray = (ArrayNode) response.getResult();
for (JsonNode rulesetNode : rulesetsArray) {
rulesets.add(parseManagedRuleset(rulesetNode));
}
}
return rulesets;
}
public ManagedRuleset getRuleset(String zoneId, String rulesetId) 
throws CloudflareException {
String endpoint = String.format("/zones/%s/rulesets/%s", zoneId, rulesetId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
return parseManagedRuleset((JsonNode) response.getResult());
}
public void updateRuleset(String zoneId, String rulesetId, 
ManagedRuleset ruleset) throws CloudflareException {
String endpoint = String.format("/zones/%s/rulesets/%s", zoneId, rulesetId);
ObjectNode requestBody = createRulesetRequestBody(ruleset);
apiClient.executeRequest("PUT", endpoint, requestBody);
}
public List<RulesetRule> getRulesetRules(String zoneId, String rulesetId) 
throws CloudflareException {
String endpoint = String.format("/zones/%s/rulesets/%s/rules", zoneId, rulesetId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
List<RulesetRule> rules = new ArrayList<>();
if (response.getResult() instanceof ArrayNode) {
ArrayNode rulesArray = (ArrayNode) response.getResult();
for (JsonNode ruleNode : rulesArray) {
rules.add(parseRulesetRule(ruleNode));
}
}
return rules;
}
public void updateRulesetRule(String zoneId, String rulesetId, String ruleId,
RulesetRule rule) throws CloudflareException {
String endpoint = String.format("/zones/%s/rulesets/%s/rules/%s", 
zoneId, rulesetId, ruleId);
ObjectNode requestBody = createRulesetRuleRequestBody(rule);
apiClient.executeRequest("PUT", endpoint, requestBody);
}
private ObjectNode createRulesetRequestBody(ManagedRuleset ruleset) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode requestBody = mapper.createObjectNode();
requestBody.put("name", ruleset.getName());
requestBody.put("description", ruleset.getDescription());
requestBody.put("kind", ruleset.getKind());
requestBody.put("phase", ruleset.getPhase());
return requestBody;
}
private ObjectNode createRulesetRuleRequestBody(RulesetRule rule) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode requestBody = mapper.createObjectNode();
requestBody.put("action", rule.getAction());
requestBody.put("description", rule.getDescription());
requestBody.put("enabled", rule.isEnabled());
if (rule.getActionParameters() != null) {
requestBody.set("action_parameters", 
mapper.valueToTree(rule.getActionParameters()));
}
if (rule.getExpression() != null) {
requestBody.put("expression", rule.getExpression());
}
return requestBody;
}
private ManagedRuleset parseManagedRuleset(JsonNode rulesetNode) {
ManagedRuleset ruleset = new ManagedRuleset();
ruleset.setId(rulesetNode.get("id").asText());
ruleset.setName(rulesetNode.get("name").asText());
ruleset.setDescription(rulesetNode.get("description").asText());
ruleset.setKind(rulesetNode.get("kind").asText());
ruleset.setPhase(rulesetNode.get("phase").asText());
ruleset.setVersion(rulesetNode.get("version").asText());
return ruleset;
}
private RulesetRule parseRulesetRule(JsonNode ruleNode) {
RulesetRule rule = new RulesetRule();
rule.setId(ruleNode.get("id").asText());
rule.setDescription(ruleNode.get("description").asText());
rule.setEnabled(ruleNode.get("enabled").asBoolean());
rule.setAction(ruleNode.get("action").asText());
if (ruleNode.has("expression")) {
rule.setExpression(ruleNode.get("expression").asText());
}
if (ruleNode.has("action_parameters")) {
// Parse action parameters
}
return rule;
}
public static class ManagedRuleset {
private String id;
private String name;
private String description;
private String kind;
private String phase;
private String version;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getKind() { return kind; }
public void setKind(String kind) { this.kind = kind; }
public String getPhase() { return phase; }
public void setPhase(String phase) { this.phase = phase; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
}
public static class RulesetRule {
private String id;
private String description;
private boolean enabled;
private String action;
private String expression;
private Map<String, Object> actionParameters;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
public String getExpression() { return expression; }
public void setExpression(String expression) { this.expression = expression; }
public Map<String, Object> getActionParameters() { return actionParameters; }
public void setActionParameters(Map<String, Object> actionParameters) { 
this.actionParameters = actionParameters; 
}
}
}

Security Analytics and Monitoring

Example 5: WAF Analytics and Alerting

package com.example.cloudflare.waf;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
public class WafAnalytics {
private final CloudflareApiClient apiClient;
public WafAnalytics(CloudflareApiClient apiClient) {
this.apiClient = apiClient;
}
public SecurityAnalytics getSecurityAnalytics(String zoneId, LocalDateTime since, 
LocalDateTime until) 
throws CloudflareException {
String sinceStr = since.format(DateTimeFormatter.ISO_DATE_TIME);
String untilStr = until.format(DateTimeFormatter.ISO_DATE_TIME);
String endpoint = String.format(
"/zones/%s/security/events?since=%s&until=%s&limit=1000",
zoneId, sinceStr, untilStr
);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
return parseSecurityAnalytics(response);
}
public Map<String, Integer> getTopBlockedRules(String zoneId, int hours) 
throws CloudflareException {
LocalDateTime until = LocalDateTime.now();
LocalDateTime since = until.minusHours(hours);
SecurityAnalytics analytics = getSecurityAnalytics(zoneId, since, until);
Map<String, Integer> ruleCounts = new HashMap<>();
for (SecurityEvent event : analytics.getEvents()) {
if ("block".equals(event.getAction())) {
String ruleId = event.getRuleId();
ruleCounts.put(ruleId, ruleCounts.getOrDefault(ruleId, 0) + 1);
}
}
return ruleCounts.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.collect(LinkedHashMap::new, 
(map, entry) -> map.put(entry.getKey(), entry.getValue()),
Map::putAll);
}
public List<AttackVector> getAttackVectors(String zoneId, int hours) 
throws CloudflareException {
LocalDateTime until = LocalDateTime.now();
LocalDateTime since = until.minusHours(hours);
SecurityAnalytics analytics = getSecurityAnalytics(zoneId, since, until);
Map<String, AttackVector> vectors = new HashMap<>();
for (SecurityEvent event : analytics.getEvents()) {
String source = event.getSource();
String type = event.getType();
String key = source + ":" + type;
AttackVector vector = vectors.getOrDefault(key, 
new AttackVector(source, type));
vector.incrementCount();
if (event.getAction().equals("block")) {
vector.incrementBlocked();
}
vectors.put(key, vector);
}
return new ArrayList<>(vectors.values());
}
public RateLimitAnalytics getRateLimitAnalytics(String zoneId) throws CloudflareException {
String endpoint = String.format("/zones/%s/analytics/dashboard?since=-43200", zoneId);
CloudflareResponse response = apiClient.executeRequest("GET", endpoint, null);
return parseRateLimitAnalytics(response);
}
private SecurityAnalytics parseSecurityAnalytics(CloudflareResponse response) {
SecurityAnalytics analytics = new SecurityAnalytics();
List<SecurityEvent> events = new ArrayList<>();
if (response.getResult() instanceof ArrayNode) {
ArrayNode eventsArray = (ArrayNode) response.getResult();
for (JsonNode eventNode : eventsArray) {
events.add(parseSecurityEvent(eventNode));
}
}
analytics.setEvents(events);
return analytics;
}
private SecurityEvent parseSecurityEvent(JsonNode eventNode) {
SecurityEvent event = new SecurityEvent();
event.setId(eventNode.get("id").asText());
event.setTimestamp(LocalDateTime.parse(
eventNode.get("timestamp").asText(), DateTimeFormatter.ISO_DATE_TIME));
event.setAction(eventNode.get("action").asText());
event.setRuleId(eventNode.get("rule_id").asText());
event.setSource(eventNode.get("source").asText());
event.setType(eventNode.get("type").asText());
event.setCountry(eventNode.get("country").asText());
return event;
}
private RateLimitAnalytics parseRateLimitAnalytics(CloudflareResponse response) {
// Implementation to parse rate limit analytics
return new RateLimitAnalytics();
}
public static class SecurityAnalytics {
private List<SecurityEvent> events = new ArrayList<>();
public List<SecurityEvent> getEvents() { return events; }
public void setEvents(List<SecurityEvent> events) { this.events = events; }
public long getTotalEvents() { return events.size(); }
public long getBlockedEvents() { 
return events.stream().filter(e -> "block".equals(e.getAction())).count(); 
}
}
public static class SecurityEvent {
private String id;
private LocalDateTime timestamp;
private String action;
private String ruleId;
private String source;
private String type;
private String country;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public LocalDateTime getTimestamp() { return timestamp; }
public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
public String getAction() { return action; }
public void setAction(String action) { this.action = action; }
public String getRuleId() { return ruleId; }
public void setRuleId(String ruleId) { this.ruleId = ruleId; }
public String getSource() { return source; }
public void setSource(String source) { this.source = source; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getCountry() { return country; }
public void setCountry(String country) { this.country = country; }
}
public static class AttackVector {
private String source;
private String type;
private int totalCount;
private int blockedCount;
public AttackVector(String source, String type) {
this.source = source;
this.type = type;
}
public void incrementCount() { totalCount++; }
public void incrementBlocked() { blockedCount++; }
// Getters
public String getSource() { return source; }
public String getType() { return type; }
public int getTotalCount() { return totalCount; }
public int getBlockedCount() { return blockedCount; }
public double getBlockRate() { 
return totalCount > 0 ? (double) blockedCount / totalCount * 100 : 0; 
}
}
public static class RateLimitAnalytics {
// Analytics data structure for rate limiting
}
}

Automated WAF Rule Deployment

Example 6: Automated WAF Deployment Service

package com.example.cloudflare.waf;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class AutomatedWafDeployment {
private final WafRuleManager wafRuleManager;
private final WafAnalytics wafAnalytics;
private final String zoneId;
private final ScheduledExecutorService scheduler;
private final Map<String, WafRuleManager.WafRule> deployedRules;
public AutomatedWafDeployment(WafRuleManager wafRuleManager, 
WafAnalytics wafAnalytics, String zoneId) {
this.wafRuleManager = wafRuleManager;
this.wafAnalytics = wafAnalytics;
this.zoneId = zoneId;
this.scheduler = Executors.newScheduledThreadPool(1);
this.deployedRules = new HashMap<>();
}
public void startAutomatedProtection() {
// Deploy initial rule set
deployInitialRules();
// Schedule regular analytics review
scheduler.scheduleAtFixedRate(this::reviewAndUpdateRules, 0, 1, TimeUnit.HOURS);
// Schedule threat intelligence updates
scheduler.scheduleAtFixedRate(this::updateThreatIntelligence, 0, 6, TimeUnit.HOURS);
}
public void stopAutomatedProtection() {
scheduler.shutdown();
}
private void deployInitialRules() {
try {
System.out.println("Deploying initial WAF rules...");
// Deploy common security rules
deployRule(WafRuleTemplates.createSqlInjectionRule());
deployRule(WafRuleTemplates.createXssRule());
deployRule(WafRuleTemplates.createScannerBotRule());
deployRule(WafRuleTemplates.createBadBotRule());
deployRule(WafRuleTemplates.createSensitivePathRule());
// Deploy country blocking for known malicious countries
List<String> blockedCountries = Arrays.asList("CN", "RU", "KP", "IR");
deployRule(WafRuleTemplates.createCountryBlockRule(blockedCountries));
System.out.println("Initial WAF rules deployed successfully");
} catch (CloudflareException e) {
System.err.println("Failed to deploy initial rules: " + e.getMessage());
}
}
private void reviewAndUpdateRules() {
try {
System.out.println("Reviewing WAF analytics and updating rules...");
// Get recent attack data
Map<String, Integer> topBlockedRules = 
wafAnalytics.getTopBlockedRules(zoneId, 24);
// Analyze attack vectors
List<WafAnalytics.AttackVector> attackVectors = 
wafAnalytics.getAttackVectors(zoneId, 24);
// Update rules based on analytics
updateRulesBasedOnAnalytics(topBlockedRules, attackVectors);
// Check for false positives and adjust rules
adjustRuleSensitivity();
} catch (CloudflareException e) {
System.err.println("Failed to review and update rules: " + e.getMessage());
}
}
private void updateThreatIntelligence() {
try {
System.out.println("Updating threat intelligence...");
// This could integrate with external threat intelligence feeds
// For now, we'll update country blocking based on recent attacks
List<WafAnalytics.AttackVector> recentAttacks = 
wafAnalytics.getAttackVectors(zoneId, 168); // 1 week
// Identify countries with high attack rates
Map<String, Long> attackByCountry = new HashMap<>();
for (WafAnalytics.AttackVector vector : recentAttacks) {
// This would need to map IPs to countries
// For demonstration, we'll use a simplified approach
}
// Update country blocking rules
updateCountryBlocking(attackByCountry);
} catch (CloudflareException e) {
System.err.println("Failed to update threat intelligence: " + e.getMessage());
}
}
private void deployRule(WafRuleManager.WafRule rule) throws CloudflareException {
WafRuleManager.WafRule deployedRule = wafRuleManager.createRule(zoneId, rule);
deployedRules.put(rule.getDescription(), deployedRule);
System.out.println("Deployed rule: " + rule.getDescription());
}
private void updateRulesBasedOnAnalytics(Map<String, Integer> topBlockedRules,
List<WafAnalytics.AttackVector> attackVectors) {
// Implement rule adjustments based on analytics
// For example, increase sensitivity for frequently attacked vectors
// Or decrease sensitivity for rules causing false positives
}
private void adjustRuleSensitivity() {
// Implement logic to adjust rule sensitivity based on false positive rate
// and attack detection effectiveness
}
private void updateCountryBlocking(Map<String, Long> attackByCountry) {
// Update country blocking rules based on recent attack patterns
}
public Map<String, WafRuleManager.WafRule> getDeployedRules() {
return Collections.unmodifiableMap(deployedRules);
}
public void emergencyBlockIp(String ipAddress) throws CloudflareException {
WafRuleManager.WafFilter filter = new WafRuleManager.WafFilter();
filter.setExpression("ip.src eq " + ipAddress);
filter.setDescription("Emergency block for IP: " + ipAddress);
WafRuleManager.WafRule rule = new WafRuleManager.WafRule(
"Emergency IP Block - " + ipAddress,
WafRuleManager.WafRule.Action.BLOCK,
0, // Highest priority
filter
);
wafRuleManager.createRule(zoneId, rule);
System.out.println("Emergency IP block deployed for: " + ipAddress);
}
}

Configuration and Best Practices

Example 7: Configuration Management

package com.example.cloudflare.waf;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class WafConfiguration {
private final Properties properties;
public WafConfiguration() {
this.properties = new Properties();
loadConfiguration();
}
private void loadConfiguration() {
try (InputStream input = getClass().getClassLoader()
.getResourceAsStream("cloudflare-waf.properties")) {
if (input != null) {
properties.load(input);
} else {
// Set default values
setDefaultProperties();
}
} catch (IOException e) {
System.err.println("Failed to load configuration, using defaults");
setDefaultProperties();
}
}
private void setDefaultProperties() {
properties.setProperty("cloudflare.api.url", "https://api.cloudflare.com/client/v4");
properties.setProperty("waf.rule.priority.sql", "1");
properties.setProperty("waf.rule.priority.xss", "2");
properties.setProperty("waf.rule.priority.scanner", "3");
properties.setProperty("waf.analytics.review.interval.hours", "1");
properties.setProperty("waf.threat.intel.update.interval.hours", "6");
properties.setProperty("waf.emergency.block.enabled", "true");
}
public String getApiToken() {
return System.getenv("CLOUDFLARE_API_TOKEN");
}
public String getZoneId() {
return properties.getProperty("cloudflare.zone.id");
}
public String getApiUrl() {
return properties.getProperty("cloudflare.api.url");
}
public int getSqlRulePriority() {
return Integer.parseInt(properties.getProperty("waf.rule.priority.sql"));
}
public int getAnalyticsReviewInterval() {
return Integer.parseInt(properties.getProperty("waf.analytics.review.interval.hours"));
}
public boolean isEmergencyBlockEnabled() {
return Boolean.parseBoolean(properties.getProperty("waf.emergency.block.enabled"));
}
public List<String> getDefaultBlockedCountries() {
String countries = properties.getProperty("waf.default.blocked.countries", "CN,RU,KP,IR");
return Arrays.asList(countries.split(","));
}
}

Best Practices Summary

  1. Rule Prioritization: Order rules by severity and performance impact
  2. Regular Reviews: Continuously monitor and adjust rules based on analytics
  3. Layered Defense: Combine managed rulesets with custom rules
  4. Testing: Test rules in log mode before blocking
  5. Monitoring: Implement comprehensive logging and alerting
  6. Automation: Automate rule deployment and updates
  7. Compliance: Ensure rules comply with organizational policies

Conclusion

Managing Cloudflare WAF rules programmatically in Java provides:

  • Automated Security: Continuous protection updates
  • Scalable Management: Handle complex rule sets across multiple zones
  • Real-time Analytics: Monitor and respond to threats quickly
  • Integration: Combine with existing security infrastructure
  • Customization: Tailor protection to specific application needs

By implementing these Java classes and patterns, organizations can build robust, automated WAF management systems that provide comprehensive protection while reducing operational overhead.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper