Back to blog
AWSCloud SecurityDatabasesMonitoring & LoggingOperations & Compliance

Neptune Cluster Not Exporting Logs to CloudWatch

Learn why an Amazon Neptune cluster without CloudWatch log export is an audit blind spot, plus CLI, Terraform, and policy-as-code fixes to lock it down.

TL;DR

This check flags Amazon Neptune clusters that aren't shipping their audit logs to CloudWatch Logs, leaving you blind to who queried your graph database and when. Fix it by enabling the audit log export on the cluster and confirming a CloudWatch log group exists.

Amazon Neptune runs a lot of the relationship-heavy workloads people don't talk about much: fraud rings, identity graphs, recommendation engines, knowledge bases. Those are exactly the datasets where you want a record of every connection attempt and query. If your Neptune cluster isn't exporting logs to CloudWatch, that record either doesn't exist or sits trapped inside the engine where nobody can search it.

The neptune_logexport check looks for a single thing: whether your Neptune cluster has log export to CloudWatch Logs turned on. When it fails, your cluster is operating without a durable, queryable audit trail.


What this check detects

Neptune can publish audit logs to Amazon CloudWatch Logs. The audit log captures connection events and the queries (Gremlin, SPARQL, openCypher) executed against the cluster. This check inspects the cluster's EnabledCloudwatchLogsExports property. If audit is not in that list, the check reports a failure.

Note: Neptune audit logging is a two-part setup. First you enable the neptune_enable_audit_log parameter in the cluster parameter group so the engine actually generates the logs. Then you enable CloudWatch export so those logs leave the instance. This check covers the export half, but both are required to get usable audit data.

Without export enabled, the logs are not retained anywhere you can reach with normal tooling. There is no S3 fallback, no console viewer, no way to run an after-the-fact investigation. The data is simply gone.


Why it matters

A graph database without audit logging is a database you cannot investigate. Here is where that hurts.

You lose your incident response timeline

Say a set of credentials with Neptune access leaks. An attacker uses them to dump your customer relationship graph. Without exported audit logs, you have no way to answer the questions your security team and your regulators will ask: When did the access start? Which queries ran? Did they exfiltrate the whole graph or a subset? You are left guessing, and "we don't know" is an expensive answer.

Compliance frameworks expect database audit trails

SOC 2, PCI DSS, HIPAA, and ISO 27001 all expect that access to sensitive data stores is logged and reviewable. Neptune often holds personal data woven into identity and relationship graphs, which makes it firmly in scope. An auditor who finds no log retention on a production database is going to write a finding.

Warning: Enabling audit logging adds some overhead, and CloudWatch Logs ingestion and storage carry a cost. For a busy cluster the log volume can be significant. Budget for it and set a sensible retention period rather than keeping logs forever by default.

You can't detect slow-burn abuse

Not every threat is a smash-and-grab. Credential misuse, an over-privileged service quietly reading more than it should, a scripted scrape spread across weeks. These patterns only show up when you can query historical access data. Without exported logs there is nothing to query, so the behavior continues unseen.


How to fix it

You need to do two things: make sure the engine generates audit logs, then turn on CloudWatch export.

Step 1: Enable audit logging in the parameter group

Audit logs are controlled by the neptune_enable_audit_log parameter in your cluster parameter group. Check the current value first.

aws neptune describe-db-cluster-parameters \
  --db-cluster-parameter-group-name your-cluster-param-group \
  --query "Parameters[?ParameterName=='neptune_enable_audit_log']"

If it is set to 0, turn it on.

aws neptune modify-db-cluster-parameter-group \
  --db-cluster-parameter-group-name your-cluster-param-group \
  --parameters "ParameterName=neptune_enable_audit_log,ParameterValue=1,ApplyMethod=pending-reboot"

Warning: This parameter uses pending-reboot, so the change does not take effect until each instance in the cluster reboots. Plan a maintenance window or reboot instances during a low-traffic period to avoid surprising your application.

Step 2: Enable CloudWatch Logs export on the cluster

aws neptune modify-db-cluster \
  --db-cluster-identifier your-neptune-cluster \
  --cloudwatch-logs-export-configuration '{"EnableLogTypes":["audit"]}' \
  --apply-immediately

Confirm the export landed.

aws neptune describe-db-clusters \
  --db-cluster-identifier your-neptune-cluster \
  --query "DBClusters[0].EnabledCloudwatchLogsExports"

You should see [ "audit" ] in the output. Neptune creates a log group named /aws/neptune/your-neptune-cluster/audit once events start flowing.

Console steps

  1. Open the Amazon Neptune console and go to Databases.
  2. Select your cluster and click Modify.
  3. Scroll to Log exports and check Audit log.
  4. Make sure the cluster's parameter group has neptune_enable_audit_log set to 1.
  5. Choose Apply immediately or schedule for the next maintenance window, then save.

Terraform

If you manage Neptune as code, set both pieces together so they never drift apart.

resource "aws_neptune_cluster_parameter_group" "this" {
  family = "neptune1.3"
  name   = "neptune-audit-enabled"

  parameter {
    name         = "neptune_enable_audit_log"
    value        = "1"
    apply_method = "pending-reboot"
  }
}

resource "aws_neptune_cluster" "this" {
  cluster_identifier                   = "your-neptune-cluster"
  engine                               = "neptune"
  neptune_cluster_parameter_group_name = aws_neptune_cluster_parameter_group.this.name
  enable_cloudwatch_logs_exports       = ["audit"]
}

Tip: Set a retention policy on the auto-created log group so logs don't accumulate cost forever. A 90-day retention is a common starting point that satisfies most audit requirements while keeping spend predictable: aws logs put-retention-policy --log-group-name /aws/neptune/your-neptune-cluster/audit --retention-in-days 90.


How to prevent it from happening again

Fixing one cluster by hand is fine. Making sure the next ten clusters ship with logging on is the real win.

Bake it into your module

If teams provision Neptune through a shared Terraform module, set enable_cloudwatch_logs_exports = ["audit"] and the parameter group as the default inside that module. Individual teams should have to opt out explicitly, not opt in.

Gate it in CI with policy-as-code

Use a tool like OPA Conftest or Checkov against your Terraform plans before merge. A simple Rego rule catches the gap:

package neptune.logging

deny[msg] {
  resource := input.resource_changes[_]
  resource.type == "aws_neptune_cluster"
  exports := resource.change.after.enable_cloudwatch_logs_exports
  not contains_audit(exports)
  msg := sprintf("Neptune cluster '%s' must export audit logs to CloudWatch", [resource.address])
}

contains_audit(exports) {
  exports[_] == "audit"
}

Wire that into your pipeline so a non-compliant plan fails the build before anything reaches AWS.

Tip: Pair the CI gate with continuous detection. Lensix re-runs the neptune_logexport check across your accounts, so a cluster created outside your IaC pipeline, through the console or a one-off script, still gets caught instead of slipping through.

Use an AWS Config rule for existing accounts

For drift on resources already running, a custom AWS Config rule evaluating EnabledCloudwatchLogsExports gives you an account-wide tripwire and can trigger remediation automatically through SSM Automation.


Best practices

  • Enable both the parameter and the export. Turning on CloudWatch export without neptune_enable_audit_log gives you an empty log group. Verify both.
  • Set explicit retention. Match your retention period to your compliance obligations rather than leaving the default. Never lose logs, never pay to store them indefinitely.
  • Forward logs to a central account. Ship Neptune audit logs to a dedicated logging account using a CloudWatch subscription filter so a compromised workload account can't tamper with its own trail.
  • Alert on the signals that matter. Create metric filters for failed connection spikes or unusual query volume so logs drive action instead of just sitting in storage.
  • Review access alongside logging. Audit logs tell you what happened. Tight IAM policies and IAM database authentication reduce what can happen in the first place. Treat them as a pair.

Note: Audit logs record connection and query activity, not the data returned. They tell you that a query ran and who ran it, which is what you need for an investigation, but they won't show you the result set. Plan your detection rules around query patterns and connection behavior.

Logging is one of those controls that costs almost nothing to enable up front and becomes priceless the day you actually need it. Turn it on for every Neptune cluster, confirm the logs are flowing, and make the next one inherit the setting automatically.