This check flags GCP firewall rules that have logging turned off, which leaves you blind to allowed and denied traffic during an incident. Enable Firewall Rules Logging on the rule with gcloud compute firewall-rules update RULE_NAME --enable-logging.
When something goes wrong in your VPC, the first question is almost always "what traffic actually hit this rule?" Without firewall rule logging, you cannot answer that. You are left guessing whether an attacker probed an open port, whether a deny rule is doing its job, or whether a legitimate service got blocked by mistake. This Lensix check catches GCP firewall rules where logging is disabled so you can fix the gaps before you need the data.
What this check detects
The vpc_nofirewalllogging check inspects every VPC firewall rule in your GCP project and reports any rule where Firewall Rules Logging is not enabled. By default, logging is off when you create a firewall rule, so this is one of the more common findings in a fresh environment.
Firewall Rules Logging records each connection that a rule evaluates, including the rule that matched, the source and destination, the action taken (allow or deny), and metadata like the instance involved. These logs flow into Cloud Logging, where you can query them, route them to BigQuery, or forward them to a SIEM.
Note: Firewall Rules Logging is distinct from VPC Flow Logs. Flow Logs are enabled per subnet and sample traffic at the network level. Firewall Rules Logging is enabled per firewall rule and tells you specifically which rule allowed or denied a given connection. You usually want both.
Why it matters
A firewall rule with no logging is a security control you cannot audit. Here is where that bites in practice.
Incident response goes dark
Say an instance in a public subnet starts beaconing to an unknown external host. With logging enabled, you can pull the exact connections, see which egress rule allowed them, and scope the blast radius in minutes. Without it, you are reconstructing events from application logs and guesswork, which costs hours during the exact window when speed matters most.
You cannot validate your own rules
Teams add allow rules under deadline pressure and rarely remove them. Logging lets you confirm whether a rule is even being hit. A permissive 0.0.0.0/0 ingress rule that logs zero matches over 90 days is a strong candidate for deletion. Without logs, that rule lingers forever as unmonitored attack surface.
Compliance and audit gaps
Frameworks like CIS GCP, PCI DSS, and SOC 2 expect network traffic to be logged and reviewable. An auditor asking "show me denied connection attempts to your database tier" needs a real answer. The CIS Google Cloud Foundations Benchmark explicitly recommends logging on firewall rules that allow or deny traffic to sensitive resources.
Warning: Firewall Rules Logging generates log volume that lands in Cloud Logging, and ingestion beyond the free allotment is billed per GiB. High-traffic rules on busy instances can produce a lot of entries, so enable it deliberately and use metadata trimming (covered below) to keep costs predictable.
How to fix it
You enable logging on the firewall rule itself. The fix is non-disruptive, it does not change what the rule allows or denies, it only starts recording matches.
Using the gcloud CLI
Enable logging on an existing rule:
gcloud compute firewall-rules update RULE_NAME \
--enable-logging
To reduce log volume and cost, set the logging metadata to exclude the verbose fields you do not need:
gcloud compute firewall-rules update RULE_NAME \
--enable-logging \
--logging-metadata=exclude-all
The exclude-all option still logs the connection, the matched rule, and the action, but drops instance and VM metadata. Use include-all when you want the full record for high-value rules.
When creating a new rule, enable logging from the start:
gcloud compute firewall-rules create allow-https \
--network=prod-vpc \
--direction=INGRESS \
--action=ALLOW \
--rules=tcp:443 \
--source-ranges=0.0.0.0/0 \
--enable-logging \
--logging-metadata=include-all
Using the Google Cloud Console
- Go to VPC network → Firewall.
- Click the firewall rule you want to update.
- Click Edit.
- Under Logs, switch the toggle to On.
- Optionally expand the metadata options to include or exclude instance details.
- Click Save.
Using Terraform
Add a log_config block to the google_compute_firewall resource:
resource "google_compute_firewall" "allow_https" {
name = "allow-https"
network = google_compute_network.prod_vpc.id
direction = "INGRESS"
source_ranges = ["0.0.0.0/0"]
allow {
protocol = "tcp"
ports = ["443"]
}
log_config {
metadata = "INCLUDE_ALL_METADATA"
}
}
Removing the log_config block disables logging, so its presence is what flips the control on. Set metadata to EXCLUDE_ALL_METADATA for the lower-cost option.
Tip: To enable logging across every rule that currently lacks it, list the offenders and loop over them. Run this in a non-production project first to confirm the output.
for rule in $(gcloud compute firewall-rules list \
--filter="logConfig.enable=false" \
--format="value(name)"); do
gcloud compute firewall-rules update "$rule" \
--enable-logging \
--logging-metadata=exclude-all
done
How to prevent it from happening again
Fixing existing rules is the easy part. Keeping logging on as your environment grows takes a guardrail.
Enforce it with Organization Policy
GCP does not ship a built-in constraint that forces firewall logging, so the practical enforcement point is your IaC pipeline plus continuous monitoring. Treat firewall rules without log_config as a build failure.
Gate Terraform in CI with OPA or Conftest
Add a policy that rejects any google_compute_firewall resource missing a logging config. With Conftest, a Rego rule looks like this:
package main
deny[msg] {
resource := input.resource.google_compute_firewall[name]
not resource.log_config
msg := sprintf("firewall rule '%s' must define log_config", [name])
}
Wire it into your pipeline against the Terraform plan output:
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json
conftest test plan.json
Tip: Pair the CI gate with continuous scanning in Lensix. The gate stops new misconfigurations at merge time, while ongoing scans catch rules created out of band through the console or ad hoc gcloud commands.
Route the logs somewhere useful
Logging is only valuable if someone can act on it. Set up a log sink so firewall logs land where your security team works:
gcloud logging sinks create firewall-logs-to-bq \
bigquery.googleapis.com/projects/PROJECT_ID/datasets/firewall_logs \
--log-filter='resource.type="gce_subnetwork" AND logName:"firewall"'
Best practices
- Log every allow and deny rule that touches sensitive tiers. Databases, bastion hosts, and anything reachable from the internet should always have logging on.
- Use
exclude-allmetadata as the default and reserveinclude-allfor high-value rules where you need full instance context during investigations. - Set retention deliberately. Decide how long firewall logs need to live for your compliance scope, then configure retention on the destination rather than paying to keep everything in Cloud Logging indefinitely.
- Review low-hit and zero-hit allow rules quarterly. Logging gives you the data to prune rules that no longer carry traffic, shrinking your attack surface.
- Build dashboards on denied connections. A spike in denies against a particular port often signals scanning or a misconfigured client, and it is a cheap early-warning signal.
Firewall logging is one of those controls that feels optional until the moment you need it, at which point its absence is painful. Turning it on costs little, the fix is non-disruptive, and the visibility it buys you is the difference between a contained incident and a long, blind investigation.

