Skip to content

feat(out_azure_blob): add support for managed identity#11474

Open
temporaer wants to merge 5 commits intofluent:masterfrom
temporaer:azure-blob-mi
Open

feat(out_azure_blob): add support for managed identity#11474
temporaer wants to merge 5 commits intofluent:masterfrom
temporaer:azure-blob-mi

Conversation

@temporaer
Copy link

@temporaer temporaer commented Feb 16, 2026

This PR adds three new authentication methods to the azure_blob output plugin: system-assigned managed identity, user-assigned managed identity (UAMI), and workload identity (OIDC token exchange). Previously only key (SharedKey HMAC-SHA256) and sas (SAS token) auth were supported.

The implementation follows the same patterns already used in the azure_kusto plugin, adapted for Azure Blob Storage's resource scope (https://storage.azure.com/).

fix #10777

Full disclosure: I got significant help from github copilot when implementing this feature.

Motivation

Users running Fluent Bit on Azure VMs, VMSS, or AKS often prefer managed identities over static credentials (shared keys / SAS tokens). Managed identities eliminate the need to rotate secrets and reduce the attack surface. This brings azure_blob to parity with azure_kusto, which already supports all three token-based auth methods.

Configuration

System-assigned managed identity

[OUTPUT]
    Name          azure_blob
    Match         *
    account_name  mystorageaccount
    container_name mycontainer
    auth_type     managed_identity
    client_id     system

User-assigned managed identity (UAMI)

[OUTPUT]
    Name          azure_blob
    Match         *
    account_name  mystorageaccount
    container_name mycontainer
    auth_type     managed_identity
    client_id     <managed-identity-client-id>

Workload identity (AKS / OIDC federation)

[OUTPUT]
    Name          azure_blob
    Match         *
    account_name  mystorageaccount
    container_name mycontainer
    auth_type     workload_identity
    client_id     <app-client-id>
    tenant_id     <azure-tenant-id>
    workload_identity_token_file  /var/run/secrets/azure/tokens/azure-identity-token

New config properties

Property Required for Description
auth_type all Now accepts: key, sas, managed_identity, workload_identity
client_id MI, WI For MI: set to system (system-assigned) or the UAMI client ID. For WI: the app registration client ID
tenant_id WI Azure AD tenant ID
client_secret Reserved for future service principal support
workload_identity_token_file WI (optional) Path to the federated token file. Defaults to /var/run/secrets/azure/tokens/azure-identity-token

Implementation details

  • Token acquisition: MI uses the Azure IMDS endpoint (169.254.169.254) with Metadata: true header. WI reads an OIDC token from a projected file and exchanges it at the Azure AD token endpoint via client_credentials grant.
  • Authorization: Token-based auth uses Authorization: Bearer <token> instead of the SharedKey canonical request signature. The existing x-ms-version: 2019-12-12 already supports Bearer auth.
  • Thread safety: Token retrieval is protected by pthread_mutex_t (same pattern as azure_kusto).
  • Token caching: Tokens are cached in flb_oauth2 context and refreshed only when expired (flb_oauth2_token_expired()).
  • Backward compatibility: Existing key and sas auth paths are completely unchanged.

Files changed

File Change
plugins/out_azure_blob/azure_blob_msiauth.h New — IMDS URL template, function declarations
plugins/out_azure_blob/azure_blob_msiauth.c New — IMDS + workload identity token retrieval
plugins/out_azure_blob/azure_blob.h Auth type constants, new struct fields (oauth2, client_id, etc.)
plugins/out_azure_blob/azure_blob.c Config map entries for new properties
plugins/out_azure_blob/azure_blob_conf.c Auth type handling, OAuth2 context lifecycle
plugins/out_azure_blob/azure_blob_http.c Bearer token path in azb_http_client_setup()
plugins/out_azure_blob/CMakeLists.txt Added azure_blob_msiauth.c to source list

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • [N/A] Run local packaging test showing all targets (including any new ones) build.
  • [N/A] Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

Backporting

  • [N/A] Backport to latest stable release.

Debug log output

______ _                  _    ______ _ _           _____  _____           _            
|  ___| |                | |   | ___ (_) |         |  ___||  _  |         | |           
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   _|___ \ | |/' |______ __| | _____   __
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / /   \ \|  /| |______/ _` |/ _ \ \ / /
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V //\__/ /\ |_/ /     | (_| |  __/\ V / 
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/ \____(_)\___/       \__,_|\___| \_/


[2026/02/16 21:45:32.525018883] [ info] [fluent bit] version=5.0.0, commit=, pid=647
[2026/02/16 21:45:32.525088684] [ info] [storage] ver=1.5.4, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2026/02/16 21:45:32.525096684] [ info] [simd    ] SSE2
[2026/02/16 21:45:32.525100084] [ info] [cmetrics] version=1.0.7
[2026/02/16 21:45:32.525103184] [ info] [ctraces ] version=0.7.0
[2026/02/16 21:45:32.525149384] [ info] [input:tail:tail.0] initializing
[2026/02/16 21:45:32.525155884] [ info] [input:tail:tail.0] storage_strategy='memory' (memory only)
[2026/02/16 21:45:32.548283617] [ info] [input:tail:tail.0] db: delete unmonitored stale inodes from the database: count=0
[2026/02/16 21:45:32.548323717] [ info] [input:tail:tail.1] initializing
[2026/02/16 21:45:32.548329917] [ info] [input:tail:tail.1] storage_strategy='memory' (memory only)
[2026/02/16 21:45:32.567864745] [ info] [input:tail:tail.1] db: delete unmonitored stale inodes from the database: count=0
[2026/02/16 21:45:32.567899745] [ info] [input:tail:tail.2] initializing
[2026/02/16 21:45:32.567905945] [ info] [input:tail:tail.2] storage_strategy='memory' (memory only)
[2026/02/16 21:45:32.749351105] [ info] [input:tail:tail.2] db: delete unmonitored stale inodes from the database: count=0
[2026/02/16 21:45:32.751532908] [ info] [output:azure_blob:azure_blob.0] account_name=mystorageaccount, container_name=foobar, blob_type=appendblob, emulator_mode=no, endpoint=mystorageaccount.blob.core.windows.net, auth_type=managed_identity (user)
[2026/02/16 21:45:32.768757133] [ info] [sp] stream processor started
[2026/02/16 21:45:32.768848233] [ info] [engine] Shutdown Grace Period=5, Shutdown Input Grace Period=2
[2026/02/16 21:45:32.769298534] [ info] [input:tail:tail.0] inotify_fs_add(): inode=131159 watch_fd=1 name=/mnt/batch/tasks/workitems/testing-14/job-1/amlt-latest-10-89555518/stdout.txt
[2026/02/16 21:45:32.769333634] [ info] [input:tail:tail.1] inotify_fs_add(): inode=131160 watch_fd=1 name=/mnt/batch/tasks/workitems/testing-14/job-1/amlt-latest-10-89555518/stderr.txt
[2026/02/16 21:45:32.769794335] [ info] [output:azure_blob:azure_blob.0] initializing worker
[2026/02/16 21:45:32.769814435] [ info] [output:azure_blob:azure_blob.0] worker #0 started
[2026/02/16 21:45:37.272930467] [ info] [output:azure_blob:azure_blob.0] auto_create_container is disabled, assuming container 'foobar' already exists
[2026/02/16 21:45:37.273596367] [ info] [output:azure_blob:azure_blob.0] auto_create_container is disabled, assuming container 'foobar' already exists
[2026/02/16 21:45:37.515413193] [ info] [azure blob msi auth] HTTP Status=200
[2026/02/16 21:45:37.515437193] [ info] [azure blob msi auth] access token from '169.254.169.254:80' retrieved
[2026-02-16T21:45:37Z] tick 2 - Hello from RANK 0 on NODE 0
[2026/02/16 21:45:37.602224374] [ info] [output:azure_blob:azure_blob.0] blob not found: /foobar/projects/testing/logs/7228725291.11927-058d08f2-0e54/fluent-bit/task.stderr?comp=appendblock
[2026/02/16 21:45:37.686645153] [ info] [output:azure_blob:azure_blob.0] blob created successfully: /foobar/projects/testing/logs/7228725291.11927-058d08f2-0e54/fluent-bit/task.stderr
[2026/02/16 21:45:37.710969976] [ info] [output:azure_blob:azure_blob.0] blob not found: /foobar/projects/testing/logs/7228725291.11927-058d08f2-0e54/fluent-bit/task.stdout?comp=appendblock
[2026/02/16 21:45:37.766834628] [ info] [output:azure_blob:azure_blob.0] content uploaded successfully: 
[2026/02/16 21:45:37.794382053] [ info] [output:azure_blob:azure_blob.0] blob created successfully: /foobar/projects/testing/logs/7228725291.11927-058d08f2-0e54/fluent-bit/task.stdout
[2026/02/16 21:45:37.875111629] [ info] [output:azure_blob:azure_blob.0] content uploaded successfully: 
[2026/02/16 21:45:42.272846535] [ info] [output:azure_blob:azure_blob.0] auto_create_container is disabled, assuming container 'foobar' already exists
[2026/02/16 21:45:42.273014535] [ info] [output:azure_blob:azure_blob.0] auto_create_container is disabled, assuming container 'foobar' already exists
[2026/02/16 21:45:42.353756410] [ info] [output:azure_blob:azure_blob.0] content uploaded successfully: 
[2026/02/16 21:45:42.354504911] [ info] [output:azure_blob:azure_blob.0] content uploaded successfully: 
[2026/02/16 21:45:42.431655283] [ info] [output:azure_blob:azure_blob.0] blob id (null) committed successfully
[2026/02/16 21:45:42.433302285] [ info] [output:azure_blob:azure_blob.0] blob id (null) committed successfully

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Added Managed Identity (system/user) and Workload Identity authentication for Azure Blob with OAuth2 token retrieval, caching, and new config options for client and tenant credentials and workload token file.
  • Chores

    • Build updated to include the new MSI/WI authentication component.
  • Tests

    • Added runtime tests covering key, SAS, managed identity, workload identity, and various validation/error scenarios.

@coderabbitai
Copy link

coderabbitai bot commented Feb 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Managed Identity (system/user) and Workload Identity authentication to the out_azure_blob plugin: new MSI/WI token retrieval and exchange logic, OAuth2 context handling and token caching with mutexes, build/test updates, and new runtime tests. No changes to public API signatures beyond added helper declarations.

Changes

Cohort / File(s) Summary
Build & Tests
plugins/out_azure_blob/CMakeLists.txt, tests/runtime/CMakeLists.txt, tests/runtime/out_azure_blob.c
Include azure_blob_msiauth.c in plugin build, add runtime test target and a comprehensive test suite covering KEY/SAS/MI/WI and negative startup cases.
Core Header & Data Structures
plugins/out_azure_blob/azure_blob.h
Add OAuth2 include, MSAL/IMDS URL macro, new auth mode macros (MI_SYSTEM, MI_USER, WI), OAuth2 context fields (oauth_url, o, token_mutex) and credential fields (client_id, tenant_id, client_secret, workload_identity_token_file).
Configuration & Init/Cleanup
plugins/out_azure_blob/azure_blob_conf.c, plugins/out_azure_blob/azure_blob.c
Parse new auth_type values (managed_identity, workload_identity), validate identity-specific config, construct MSAL/IMDS endpoints, create/destroy OAuth2 context and token mutex, and centralize error/cleanup paths.
HTTP & Auth Flow
plugins/out_azure_blob/azure_blob_http.c
Add OAuth2-based Bearer token handling for MI/WI: token expiry checks, mutex-protected token retrieval, Authorization header construction, and integration with existing KEY/SAS branches.
MSI/WI Implementation
plugins/out_azure_blob/azure_blob_msiauth.c, plugins/out_azure_blob/azure_blob_msiauth.h
New module with flb_azure_blob_msiauth_token_get() (IMDS GET & caching) and flb_azure_blob_workload_identity_token_get() (read federated token file and exchange with Azure AD). Includes HTTP calls, JSON parsing, file read helper, and robust error handling/cleanup.

Sequence Diagram(s)

sequenceDiagram
    participant FB as Fluent Bit (out_azure_blob)
    participant HTTP as azure_blob_http.c
    participant OAuth as OAuth2 Context
    participant IMDS as Azure IMDS / MSAL
    participant ABS as Azure Blob Storage

    FB->>HTTP: Prepare request
    HTTP->>OAuth: Check cached token / expiry
    alt token missing or expired
        OAuth->>IMDS: Request token (IMDS GET or MSAL POST / WI exchange)
        IMDS-->>OAuth: Return access_token + expiry
        OAuth->>OAuth: Cache token (expires_at)
    else token valid
        OAuth-->>HTTP: Return cached token
    end
    HTTP->>HTTP: Build "Authorization: Bearer <token>"
    HTTP->>ABS: Send HTTP request with Bearer header
    ABS-->>HTTP: Response
    HTTP-->>FB: Complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • edsiper
  • cosmo0920

Poem

🐰 Hop, hop, hooray — tokens in tow,
IMDS and MSAL help credentials grow.
Mutex guards keep secrets tight,
WI and MI bounce into sight.
Bearer headers now unlock the flow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.82% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main feature: adding managed identity authentication support to the azure_blob output plugin.
Linked Issues check ✅ Passed All code changes fulfill the objectives from issue #10777: system/user-assigned managed identity support, IMDS token acquisition, auth_type configuration, and workload identity implementation.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked objective: adding managed identity and workload identity authentication to the azure_blob plugin with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

fix fluent#10777

Signed-off-by: Hannes Schulz <Hannes.Schulz@microsoft.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@plugins/out_azure_blob/azure_blob_conf.c`:
- Around line 782-833: The OAuth2 context (created by flb_oauth2_create),
ctx->oauth_url SDS and the pthread_mutex_init in flb_azure_blob_conf_create are
not cleaned up on subsequent error returns (e.g., after azb_db_open fails),
leaking resources; fix by adding a unified cleanup path (e.g., an error/cleanup
label) and replace early returns after these allocations with a jump to that
label which calls flb_azure_blob_conf_destroy(ctx) (or otherwise destroys
ctx->o, frees ctx->oauth_url and destroys the mutex) before returning NULL so
flb_oauth2_create, ctx->oauth_url and the initialized token mutex are always
released on failure.

In `@plugins/out_azure_blob/azure_blob_http.c`:
- Around line 365-411: The MI and WI paths allocate `auth` with
flb_sds_create_size without checking for NULL, risking dereference in
flb_sds_cat_safe/flb_http_add_header; add a NULL check after flb_sds_create_size
in both the AZURE_BLOB_AUTH_MI_SYSTEM/AZURE_BLOB_AUTH_MI_USER block and the
AZURE_BLOB_AUTH_WI block: if flb_sds_create_size returns NULL, log an error with
flb_plg_error (include context and that allocation failed), unlock
ctx->token_mutex and return -1, otherwise proceed to flb_sds_cat_safe,
flb_http_add_header and flb_sds_destroy as before.

In `@plugins/out_azure_blob/azure_blob_msiauth.c`:
- Around line 172-187: The chain of flb_sds_cat calls building the request body
can return NULL mid-chain causing a NULL dereference; update the code around the
flb_sds_cat calls (the body variable concatenations) to check that body is
non-NULL immediately after each flb_sds_cat (or at least after each logical
group of concatenations) and on NULL perform the same cleanup
(flb_sds_destroy(federated_token)) and return -1; ensure you never call
flb_sds_cat with a NULL body and keep the existing error log message via
flb_error("[azure blob workload identity] failed to build request body") when
handling the failure.
- Around line 106-138: In read_token_from_file, handle the case where the
4096-byte stack buffer may truncate the token: after fread, check if bytes_read
== sizeof(buf) - 1 and emit a warning via flb_warn or flb_error indicating the
token may have been truncated (include token_file in the message); also change
the emptiness check from "bytes_read <= 0" to "bytes_read == 0" (since
bytes_read is size_t) so only zero-length reads are treated as errors, and
ensure you still null-terminate buf and create the flb_sds_t token as before.

In `@tests/runtime/out_azure_blob.c`:
- Around line 53-374: Many tests (e.g., flb_test_azure_blob_json_invalid,
flb_test_azure_blob_managed_identity_system,
flb_test_azure_blob_workload_identity, flb_test_azure_blob_mi_missing_client_id,
etc.) repeat identical setup steps; extract that into a small helper (e.g.,
azure_blob_test_setup) that creates and configures ctx, in_ffd and out_ffd
(calls flb_create, flb_service_set, flb_input + flb_input_set(tag), flb_output +
flb_output_set for match, account_name, container_name) and returns or outputs
those handles, then update each test to call this helper and only set the
auth-specific flb_output_set options and assertions thereafter to reduce
boilerplate and make intent clearer.
🧹 Nitpick comments (3)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@plugins/out_azure_blob/azure_blob_conf.c`:
- Around line 782-833: The OAuth2 context (created by flb_oauth2_create),
ctx->oauth_url SDS and the pthread_mutex_init in flb_azure_blob_conf_create are
not cleaned up on subsequent error returns (e.g., after azb_db_open fails),
leaking resources; fix by adding a unified cleanup path (e.g., an error/cleanup
label) and replace early returns after these allocations with a jump to that
label which calls flb_azure_blob_conf_destroy(ctx) (or otherwise destroys
ctx->o, frees ctx->oauth_url and destroys the mutex) before returning NULL so
flb_oauth2_create, ctx->oauth_url and the initialized token mutex are always
released on failure.

In `@plugins/out_azure_blob/azure_blob_msiauth.c`:
- Around line 106-138: In read_token_from_file, handle the case where the
4096-byte stack buffer may truncate the token: after fread, check if bytes_read
== sizeof(buf) - 1 and emit a warning via flb_warn or flb_error indicating the
token may have been truncated (include token_file in the message); also change
the emptiness check from "bytes_read <= 0" to "bytes_read == 0" (since
bytes_read is size_t) so only zero-length reads are treated as errors, and
ensure you still null-terminate buf and create the flb_sds_t token as before.

In `@tests/runtime/out_azure_blob.c`:
- Around line 53-374: Many tests (e.g., flb_test_azure_blob_json_invalid,
flb_test_azure_blob_managed_identity_system,
flb_test_azure_blob_workload_identity, flb_test_azure_blob_mi_missing_client_id,
etc.) repeat identical setup steps; extract that into a small helper (e.g.,
azure_blob_test_setup) that creates and configures ctx, in_ffd and out_ffd
(calls flb_create, flb_service_set, flb_input + flb_input_set(tag), flb_output +
flb_output_set for match, account_name, container_name) and returns or outputs
those handles, then update each test to call this helper and only set the
auth-specific flb_output_set options and assertions thereafter to reduce
boilerplate and make intent clearer.
plugins/out_azure_blob/azure_blob_msiauth.c (1)

106-138: Token file read may silently truncate large tokens.

The 4096-byte stack buffer limits the token to 4095 bytes. While typical Azure federated identity JWTs are well within this limit, a silently truncated token would cause hard-to-diagnose auth failures. Consider logging a warning when bytes_read == sizeof(buf) - 1 to aid debugging.

Also, bytes_read is size_t (unsigned), so <= 0 on line 128 is effectively == 0.

🔧 Proposed improvement
     bytes_read = fread(buf, 1, sizeof(buf) - 1, fp);
     fclose(fp);
 
-    if (bytes_read <= 0) {
+    if (bytes_read == 0) {
         flb_error("[azure blob workload identity] could not read token from file: %s",
                   token_file);
         return NULL;
     }
+    if (bytes_read == sizeof(buf) - 1) {
+        flb_warn("[azure blob workload identity] token file may be truncated "
+                 "(read %zu bytes): %s", bytes_read, token_file);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_azure_blob/azure_blob_msiauth.c` around lines 106 - 138, In
read_token_from_file, handle the case where the 4096-byte stack buffer may
truncate the token: after fread, check if bytes_read == sizeof(buf) - 1 and emit
a warning via flb_warn or flb_error indicating the token may have been truncated
(include token_file in the message); also change the emptiness check from
"bytes_read <= 0" to "bytes_read == 0" (since bytes_read is size_t) so only
zero-length reads are treated as errors, and ensure you still null-terminate buf
and create the flb_sds_t token as before.
plugins/out_azure_blob/azure_blob_conf.c (1)

782-833: Resource leak on early-return after OAuth2 context creation.

After the OAuth2 context, oauth_url, and token_mutex are created (e.g., line 813 or 832), if a subsequent step like azb_db_open (line 844) fails, the function returns NULL without calling flb_azure_blob_conf_destroy. This leaks the OAuth2 context, oauth_url SDS, and leaves the mutex initialized.

This is a pre-existing pattern throughout flb_azure_blob_conf_create (other resources also leak on early returns), but the OAuth2 upstream + TLS context is a heavier resource to leak. Consider either a cleanup goto label or calling flb_azure_blob_conf_destroy before returning NULL.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_azure_blob/azure_blob_conf.c` around lines 782 - 833, The OAuth2
context (created by flb_oauth2_create), ctx->oauth_url SDS and the
pthread_mutex_init in flb_azure_blob_conf_create are not cleaned up on
subsequent error returns (e.g., after azb_db_open fails), leaking resources; fix
by adding a unified cleanup path (e.g., an error/cleanup label) and replace
early returns after these allocations with a jump to that label which calls
flb_azure_blob_conf_destroy(ctx) (or otherwise destroys ctx->o, frees
ctx->oauth_url and destroys the mutex) before returning NULL so
flb_oauth2_create, ctx->oauth_url and the initialized token mutex are always
released on failure.
tests/runtime/out_azure_blob.c (1)

53-374: Consider extracting shared setup into a helper to reduce boilerplate.

Every test function repeats the same flb_createflb_service_setflb_inputflb_input_setflb_outputflb_output_set (account_name, container_name, match) sequence. A small helper returning ctx/in_ffd/out_ffd would cut ~8 lines per test and make the auth-specific config stand out more clearly.

That said, this pattern is common in existing Fluent Bit test files, so this is purely a readability nit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/runtime/out_azure_blob.c` around lines 53 - 374, Many tests (e.g.,
flb_test_azure_blob_json_invalid, flb_test_azure_blob_managed_identity_system,
flb_test_azure_blob_workload_identity, flb_test_azure_blob_mi_missing_client_id,
etc.) repeat identical setup steps; extract that into a small helper (e.g.,
azure_blob_test_setup) that creates and configures ctx, in_ffd and out_ffd
(calls flb_create, flb_service_set, flb_input + flb_input_set(tag), flb_output +
flb_output_set for match, account_name, container_name) and returns or outputs
those handles, then update each test to call this helper and only set the
auth-specific flb_output_set options and assertions thereafter to reduce
boilerplate and make intent clearer.

@temporaer temporaer changed the title feat(azure_blob): add support for managed identity feat(out_azure_blob): add support for managed identity Feb 16, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0d51b8c55

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@plugins/out_azure_blob/azure_blob_msiauth.c`:
- Around line 74-82: The current logging logs IMDS non-200 response payloads at
flb_info; change that to flb_debug so both success (when c->resp.status == 200)
and error payloads use flb_debug for the payload content. Locate the block
referencing c->resp.status and c->resp.payload in azure_blob_msiauth.c (the
flb_info call that prints the error payload) and replace that flb_info payload
log with flb_debug while keeping the existing flb_info that logs the HTTP status
line (flb_info("[azure blob msi auth] HTTP Status=%i", c->resp.status)).
🧹 Nitpick comments (1)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@plugins/out_azure_blob/azure_blob_msiauth.c`:
- Around line 74-82: The current logging logs IMDS non-200 response payloads at
flb_info; change that to flb_debug so both success (when c->resp.status == 200)
and error payloads use flb_debug for the payload content. Locate the block
referencing c->resp.status and c->resp.payload in azure_blob_msiauth.c (the
flb_info call that prints the error payload) and replace that flb_info payload
log with flb_debug while keeping the existing flb_info that logs the HTTP status
line (flb_info("[azure blob msi auth] HTTP Status=%i", c->resp.status)).
plugins/out_azure_blob/azure_blob_msiauth.c (1)

74-82: Consider lowering the log level for error-response payloads.

When IMDS returns a non-200 status, the full payload is logged at flb_info level (line 80). Error responses from IMDS may occasionally contain request metadata. Using flb_debug for the payload (same as the success case at line 77) would be more consistent and cautious.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_azure_blob/azure_blob_msiauth.c` around lines 74 - 82, The
current logging logs IMDS non-200 response payloads at flb_info; change that to
flb_debug so both success (when c->resp.status == 200) and error payloads use
flb_debug for the payload content. Locate the block referencing c->resp.status
and c->resp.payload in azure_blob_msiauth.c (the flb_info call that prints the
error payload) and replace that flb_info payload log with flb_debug while
keeping the existing flb_info that logs the HTTP status line (flb_info("[azure
blob msi auth] HTTP Status=%i", c->resp.status)).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/out_azure_blob/azure_blob_conf.c (1)

778-829: Hardcoded OAuth2 timeout of 3000 — consider making it configurable.

The flb_oauth2_create calls on lines 803 and 822 both use a hardcoded timeout of 3000 (milliseconds). In environments with slow IMDS or AAD endpoints (e.g., high-latency networks, overloaded IMDS), this may be insufficient or, conversely, too generous for fast-fail scenarios. Consider exposing this as a configuration property for flexibility, consistent with how other plugins handle OAuth2 timeouts.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_azure_blob/azure_blob_conf.c` around lines 778 - 829, The two
flb_oauth2_create calls currently pass a hardcoded timeout (3000); add a
configurable timeout property (e.g., oauth2_timeout_ms) to the plugin config,
parse/store it into the context (ctx->oauth_timeout_ms with a sensible default
of 3000) during configuration setup, and replace the literal 3000 in both
flb_oauth2_create(config, ctx->oauth_url, 3000) calls with ctx->oauth_timeout_ms
so both IMDS (AZURE_BLOB_AUTH_MI_SYSTEM / AZURE_BLOB_AUTH_MI_USER) and workload
identity (AZURE_BLOB_AUTH_WI) flows use the configured timeout.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/out_azure_blob/azure_blob_conf.c`:
- Around line 914-918: The code currently calls
pthread_mutex_destroy(&ctx->token_mutex) whenever ctx->atype indicates MI/WI
even if initialization may have failed; change the teardown to only destroy the
mutex if it was actually initialized by guarding the destroy with a check that
ctx->o (the oauth2 handle created by flb_oauth2_create) is non-NULL (or another
explicit "initialized" flag), so that pthread_mutex_destroy is only called when
pthread_mutex_init succeeded; update the error/cleanup path that references
ctx->atype, pthread_mutex_init, flb_oauth2_create, and flb_sds_create_size to
use this guard.

---

Nitpick comments:
In `@plugins/out_azure_blob/azure_blob_conf.c`:
- Around line 778-829: The two flb_oauth2_create calls currently pass a
hardcoded timeout (3000); add a configurable timeout property (e.g.,
oauth2_timeout_ms) to the plugin config, parse/store it into the context
(ctx->oauth_timeout_ms with a sensible default of 3000) during configuration
setup, and replace the literal 3000 in both flb_oauth2_create(config,
ctx->oauth_url, 3000) calls with ctx->oauth_timeout_ms so both IMDS
(AZURE_BLOB_AUTH_MI_SYSTEM / AZURE_BLOB_AUTH_MI_USER) and workload identity
(AZURE_BLOB_AUTH_WI) flows use the configured timeout.

@temporaer
Copy link
Author

Valgrind results

Built with

cmake .. -DFLB_DEV=On -DFLB_VALGRIND=On
make flb-rt-out_azure_blob

Command

   cd $HOME/r/fluent-bit/build && conda run -n flb-build valgrind \
     --leak-check=full \
     --show-leak-kinds=all \
     --track-origins=yes \
     --suppressions=../valgrind.supp \
     --error-exitcode=1 \
     ./bin/flb-rt-out_azure_blob

Output

==3818991== Memcheck, a memory error detector
==3818991== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==3818991== Using Valgrind-3.26.0 and LibVEX; rerun with -h for copyright info
==3818991== Command: ./bin/flb-rt-out_azure_blob
==3818991== 
==3818991== 
==3818991== HEAP SUMMARY:
==3818991==     in use at exit: 0 bytes in 0 blocks
==3818991==   total heap usage: 27,856 allocs, 27,856 frees, 4,467,638 bytes allocated
==3818991== 
==3818991== All heap blocks were freed -- no leaks are possible
==3818991== 
==3818991== For lists of detected and suppressed errors, rerun with: -s
==3818991== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Test json_invalid...                            [ OK ]
Test managed_identity_system...                 [ OK ]
Test managed_identity_user...                   [ OK ]
Test workload_identity...                       [ OK ]
Test mi_missing_client_id...                    [ OK ]
Test wi_missing_tenant_id...                    [ OK ]
Test wi_missing_client_id...                    [ OK ]
Test invalid_auth_type...                       [ OK ]
Test key_auth...                                [ OK ]
Test sas_auth...                                [ OK ]
SUCCESS: All unit tests have passed.

Signed-off-by: Hannes Schulz <Hannes.Schulz@microsoft.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@plugins/out_azure_blob/azure_blob_conf.c`:
- Around line 914-918: The code currently guards pthread_mutex_destroy by
ctx->atype, but that can be set to MI/WI before pthread_mutex_init is called
(e.g., if flb_sds_create_size or flb_oauth2_create fails), causing undefined
behavior; change the guard to check that ctx->o is non-NULL (since
pthread_mutex_init is invoked only after a successful flb_oauth2_create which
populates ctx->o) before calling pthread_mutex_destroy(&ctx->token_mutex), and
keep the existing ctx->atype check as needed for clarity.

temporaer and others added 3 commits February 17, 2026 15:45
Add missing NULL checks after flb_sds_create_size() calls in the
shared key, managed identity, and workload identity auth blocks of
azb_http_client_setup(). If the allocation fails, the subsequent
flb_sds_cat_safe and flb_http_add_header calls would dereference
a NULL pointer. On failure, properly clean up resources (destroy
buffers, unlock mutexes) and return -1.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Hannes Schulz <Hannes.Schulz@microsoft.com>
Move the auth_type parsing block before the
flb_azure_blob_apply_remote_configuration() call. Previously, atype
was still zero-initialized (AZURE_BLOB_AUTH_KEY) when remote config
ran, causing it to always try to extract shared_key from the remote
payload. This broke managed_identity and workload_identity setups
that intentionally do not provide key material.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Hannes Schulz <Hannes.Schulz@microsoft.com>
Add a check after fread to detect when the token file exceeds the
4095-byte buffer. Previously the token would be silently truncated,
causing opaque token-exchange failures. Now an error is logged and
the read is rejected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Hannes Schulz <Hannes.Schulz@microsoft.com>
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.

Add Managed Identity (MSI) support for Azure Logs Ingestion output plugin

1 participant

Comments