Skip to content

Conversation

@fceller
Copy link
Contributor

@fceller fceller commented Dec 30, 2025

Scope & Purpose

Add audit logging for all read operations on the _users system collection. Implementing FRB-419.

  • 💩 Bugfix
  • 🍕 New feature
  • 🔥 Performance improvement
  • 🔨 Refactoring/simplification

1. Core Audit Event Implementation

Files Modified:

  1. arangod/Utils/Events.h

    • Added ReadUser() function declaration
  2. arangod/Utils/Events.cpp (Community Edition)

    • Added stub implementation for ReadUser()
  3. enterprise/Enterprise/Audit/EventsEE.cpp (Enterprise Edition)

    • Added full implementation of ReadUser() audit event
    • Logs to DOCUMENT topic at INFO level
    • Format: read user '<username>' | ok/failed
  4. arangod/RestHandler/RestUsersHandler.cpp

    • Added #include "Utils/Events.h"
    • Added events::ReadUser() calls to all GET endpoints:
      • GET /_api/user → logs as read user '*'
      • GET /_api/user/<user> → logs as read user '<user>'
      • GET /_api/user/<user>/database → logs user read
      • GET /_api/user/<user>/database/<dbname> → logs user read
      • GET /_api/user/<user>/database/<dbname>/<collection> → logs user read
      • GET /_api/user/<user>/config → logs user read

2. Test Implementation

Files Modified:

  1. enterprise/tests/js/common/audit/audit.js

    • Updated toSkip regex to allow "read user" events while filtering other _users operations
    • Added 7 comprehensive test cases (skip in server context):
      • testReadUser - Read specific user
      • testReadUserFailed - Read non-existent user
      • testReadAllUsers - List all users
      • testReadUserDatabasePermissions - Read user DB permissions
      • testReadUserSpecificDatabasePermission - Read specific DB permission
      • testReadUserCollectionPermission - Read collection permission
      • testReadUserConfig - Read user config
  2. enterprise/tests/js/client/audit/audit.js

    • Added 2 test cases for HTTP client context:
      • testReadUser
      • testReadAllUsers
  3. enterprise/tests/js/server/audit/audit.js

    • Removed HTTP-based tests (not applicable in server context)

3. Documentation Updates

Files Modified:

  1. docs-hugo/site/content/arangodb/4.0/operations/security/audit-logging.md

Added New Section: "User Management"

Checklist

  • Tests
    • Regression tests
    • C++ Unit tests
    • integration tests
    • resilience tests
  • 📖 CHANGELOG entry made
  • 📚 documentation written (release notes, API changes, ...)
  • Backports
    • Backport for 3.12.0: (Please link PR)
    • Backport for 3.11: (Please link PR)
    • Backport for 3.10: (Please link PR)

Related Information

(Please reference tickets / specification / other PRs etc)


Note

Implements audit logging for reads from the users API.

  • Introduces events::ReadUser(username, result, context) in Utils/Events.h/.cpp
  • Calls events::ReadUser in RestUsersHandler::getRequest for: listing all users, fetching a user, and reading database/collection permissions and config data
  • Updates CHANGELOG with FRB-419 entry

Written by Cursor Bugbot for commit 9a1f28f. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on January 28

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

full = StringUtils::boolean(param);
}
generateDatabaseResult(um, user, full);
events::ReadUser(user, Result(), ExecContext::current());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Audit log always records success even when operation fails

When handling the /_api/user/<user>/database endpoint (suffixes.size() == 2), events::ReadUser is called with Result() (always success) after generateDatabaseResult returns. However, generateDatabaseResult internally calls um->accessUser() which can fail with TRI_ERROR_USER_NOT_FOUND, and in that case generates an error response. The audit log still records a successful read despite the operation failing. This is inconsistent with the "config" branch which properly captures and passes the actual Result to the audit event.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants