Skip to content

translate_ldap_attribute: fix String race during LDAP init#51690

Open
orestisfl wants to merge 1 commit into
elastic:mainfrom
orestisfl:translate-ldap-attribute-string-race
Open

translate_ldap_attribute: fix String race during LDAP init#51690
orestisfl wants to merge 1 commit into
elastic:mainfrom
orestisfl:translate-ldap-attribute-string-race

Conversation

@orestisfl

Copy link
Copy Markdown
Contributor

Proposed commit message

translate_ldap_attribute: fix String race during LDAP init

The translate_ldap_attribute processor lazily initializes its LDAP client and
stores the selected LDAP address and base DN back on the processor config while
holding clientMu. String read those same fields without synchronization, and
String is reachable concurrently through logger fields and processor-group
error messages.

Store the processor description in an atomic value and make String read that
instead of reading the mutable config fields directly. Refresh the description
after successful LDAP discovery so logs can still show the discovered address
and base DN without making String take clientMu.

Add race-detector regression coverage with a fake LDAP listener that forces
client initialization and concurrent String evaluation.

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • [ ] I have made corresponding changes to the documentation
  • [ ] I have made corresponding change to the default configuration files
  • I have added tests that prove my fix is effective or that my feature works. Where relevant, I have used the stresstest.sh script to run them under stress conditions and race detector to verify their stability.
  • I have added an entry in ./changelog/fragments using the changelog tool.

Disruptive User Impact

None.

How to test this PR locally

Run the stress test:

./script/stresstest.sh --race ./libbeat/processors/translate_ldap_attribute '^TestConcurrentClientInitAndString$' -p 16

Logs

Without the fix, the focused race test reports the original race:

WARNING: DATA RACE
Write at ... libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go:294
Previous read at ... libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go:147
WARNING: DATA RACE
Write at ... libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go:295
Previous read at ... libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go:147
--- FAIL: TestConcurrentClientInitAndString

The translate_ldap_attribute processor lazily initializes its LDAP client and
stores the selected LDAP address and base DN back on the processor config while
holding clientMu. String read those same fields without synchronization, and
String is reachable concurrently through logger fields and processor-group
error messages.

Store the processor description in an atomic value and make String read that
instead of reading the mutable config fields directly. Refresh the description
after successful LDAP discovery so logs can still show the discovered address
and base DN without making String take clientMu while initialization logging is
running.

Add race-detector regression coverage with a fake LDAP listener that forces
client initialization and concurrent String evaluation.
@orestisfl orestisfl added bug libbeat :Processors Team:Security-Windows Platform Windows Platform Team in Security Solution backport-active-all Automated backport with mergify to all the active branches labels Jul 2, 2026
@orestisfl orestisfl self-assigned this Jul 2, 2026
@botelastic botelastic Bot added needs_team Indicates that the issue/PR needs a Team:* label and removed needs_team Indicates that the issue/PR needs a Team:* label labels Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🤖 GitHub comments

Just comment with:

  • run docs-build : Re-trigger the docs validation. (use unformatted text in the comment!)
  • /test : Run the Buildkite pipeline.

@orestisfl orestisfl requested a review from Copilot July 2, 2026 12:41
@orestisfl orestisfl marked this pull request as ready for review July 2, 2026 12:41
@orestisfl orestisfl requested a review from a team as a code owner July 2, 2026 12:41
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/sec-windows-platform (Team:Security-Windows Platform)

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: c04a76e0-4164-48cb-9a7d-157837a00ba4

📥 Commits

Reviewing files that changed from the base of the PR and between 5acbbac and 4aeaab7.

📒 Files selected for processing (3)
  • changelog/fragments/1783070300-fix-translate-ldap-attribute-string-race.yaml
  • libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go
  • libbeat/processors/translate_ldap_attribute/translate_ldap_attribute_test.go

📝 Walkthrough

Walkthrough

The translate_ldap_attribute processor now precomputes its String() output into an atomic.Value field (description) instead of formatting it on every call. storeDescription populates this value during initial config setup and again after ensureClient discovers connection details (e.g., base DN/address). String() now loads from this atomic value for lock-free reads. A new test, TestConcurrentClientInitAndString, verifies the absence of a data race using a fake LDAP server with concurrent readers and writers. A changelog fragment documents the bug fix.

Changes

Area Change
translate_ldap_attribute.go Added sync/atomic import, description atomic.Value field, storeDescription helper called at init and post-client-discovery, updated String() to read from atomic value
translate_ldap_attribute_test.go Added fake LDAP TCP server and TestConcurrentClientInitAndString concurrency test
Changelog Added fragment documenting the data race bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Init as newFromConfig
  participant Processor as processor
  participant EnsureClient as ensureClient
  participant Caller as String()

  Init->>Processor: storeDescription(config)
  Caller->>Processor: description.Load()
  EnsureClient->>Processor: storeDescription(discovered config)
  Caller->>Processor: description.Load()
Loading

Suggested labels: Team:Elastic-Agent-Data-Plane

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • 🛠️ Update Documentation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a data race in the translate_ldap_attribute processor caused by concurrent reads of mutable config fields from String() while the LDAP client is lazily initialized.

Changes:

  • Store the processor’s String() description in an atomic.Value and make String() read only that value (no mutex acquisition, no reads of mutable config fields).
  • Refresh the stored description after successful LDAP discovery so logs still reflect the discovered LDAP address/base DN.
  • Add a race-detector regression test that forces concurrent ensureClient() and String() evaluation.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
libbeat/processors/translate_ldap_attribute/translate_ldap_attribute.go Removes unsynchronized reads from String() by switching to an atomically stored description string.
libbeat/processors/translate_ldap_attribute/translate_ldap_attribute_test.go Adds a focused -race regression test exercising concurrent client init and String() calls.
changelog/fragments/1783070300-fix-translate-ldap-attribute-string-race.yaml Adds a changelog entry for the race fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@orestisfl orestisfl changed the title libbeat/translate_ldap_attribute: fix String race during LDAP init translate_ldap_attribute: fix String race during LDAP init Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-active-all Automated backport with mergify to all the active branches bug Team:Security-Windows Platform Windows Platform Team in Security Solution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants