Skip to content

Commit d7d9263

Browse files
committed
out_azure_blob: add OAuth authentication support
Integrate common Azure authentication module to support: - Managed Identity (system-assigned and user-assigned) - Workload Identity with federated tokens - Service Principal with client credentials This extends the existing shared key and SAS token authentication methods and maintains full backward compatibility. New configuration parameters: - tenant_id: Azure AD tenant ID - client_id: Azure AD client ID or 'system' for system-assigned MI - client_secret: Client secret for service principal auth - workload_identity_token_file: Token file path for workload identity Signed-off-by: zshuang0316 <zshuang0316@163.com>
1 parent 62ba61d commit d7d9263

8 files changed

Lines changed: 317 additions & 31 deletions

File tree

include/fluent-bit/flb_azure_auth.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626

2727
/* Authentication types for Azure services */
2828
typedef enum {
29-
FLB_AZURE_AUTH_KEY = 0, /* Shared Access Key */
30-
FLB_AZURE_AUTH_SAS, /* Shared Access Signature */
29+
FLB_AZURE_AUTH_KEY = 0, /* Shared Access Key (blob-specific) */
30+
FLB_AZURE_AUTH_SAS, /* Shared Access Signature (blob-specific) */
3131
FLB_AZURE_AUTH_SERVICE_PRINCIPAL, /* Service Principal (Client ID + Secret) */
3232
FLB_AZURE_AUTH_MANAGED_IDENTITY_SYSTEM, /* System-assigned Managed Identity */
3333
FLB_AZURE_AUTH_MANAGED_IDENTITY_USER, /* User-assigned Managed Identity */

plugins/out_azure_blob/azure_blob.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1826,7 +1826,7 @@ static struct flb_config_map config_map[] = {
18261826
{
18271827
FLB_CONFIG_MAP_STR, "auth_type", "key",
18281828
0, FLB_TRUE, offsetof(struct flb_azure_blob, auth_type),
1829-
"Set the auth type: key or sas"
1829+
"Set the auth type: key, sas, service_principal, managed_identity, or workload_identity"
18301830
},
18311831

18321832
{
@@ -1835,6 +1835,31 @@ static struct flb_config_map config_map[] = {
18351835
"Azure Blob SAS token"
18361836
},
18371837

1838+
/* OAuth authentication parameters */
1839+
{
1840+
FLB_CONFIG_MAP_STR, "tenant_id", NULL,
1841+
0, FLB_TRUE, offsetof(struct flb_azure_blob, tenant_id),
1842+
"Azure AD tenant ID (required for service_principal and workload_identity auth)"
1843+
},
1844+
1845+
{
1846+
FLB_CONFIG_MAP_STR, "client_id", NULL,
1847+
0, FLB_TRUE, offsetof(struct flb_azure_blob, client_id),
1848+
"Azure AD client ID / Application ID (required for OAuth-based authentication)"
1849+
},
1850+
1851+
{
1852+
FLB_CONFIG_MAP_STR, "client_secret", NULL,
1853+
0, FLB_TRUE, offsetof(struct flb_azure_blob, client_secret),
1854+
"Azure AD client secret (required for service_principal auth)"
1855+
},
1856+
1857+
{
1858+
FLB_CONFIG_MAP_STR, "workload_identity_token_file", NULL,
1859+
0, FLB_TRUE, offsetof(struct flb_azure_blob, workload_identity_token_file),
1860+
"Path to workload identity token file (for workload_identity auth)"
1861+
},
1862+
18381863
{
18391864
FLB_CONFIG_MAP_STR, "database_file", NULL,
18401865
0, FLB_TRUE, offsetof(struct flb_azure_blob, database_file),

plugins/out_azure_blob/azure_blob.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include <fluent-bit/flb_upstream.h>
2525
#include <fluent-bit/flb_sds.h>
2626
#include <fluent-bit/flb_sqldb.h>
27+
#include <fluent-bit/flb_azure_auth.h>
28+
#ifdef FLB_HAVE_TLS
29+
#include <fluent-bit/flb_oauth2.h>
30+
#endif
2731

2832
/* Content-Type */
2933
#define AZURE_BLOB_CT "Content-Type"
@@ -48,9 +52,6 @@
4852
#define AZURE_BLOB_APPENDBLOB 0
4953
#define AZURE_BLOB_BLOCKBLOB 1
5054

51-
#define AZURE_BLOB_AUTH_KEY 0
52-
#define AZURE_BLOB_AUTH_SAS 1
53-
5455
struct flb_azure_blob {
5556
int auto_create_container;
5657
int emulator_mode;
@@ -65,6 +66,13 @@ struct flb_azure_blob {
6566
flb_sds_t date_key;
6667
flb_sds_t auth_type;
6768
flb_sds_t sas_token;
69+
70+
/* OAuth authentication fields */
71+
flb_sds_t tenant_id;
72+
flb_sds_t client_id;
73+
flb_sds_t client_secret;
74+
flb_sds_t workload_identity_token_file;
75+
6876
flb_sds_t database_file;
6977
size_t part_size;
7078
time_t upload_parts_timeout;
@@ -112,7 +120,7 @@ struct flb_azure_blob {
112120
* Internal use
113121
*/
114122
int btype; /* blob type */
115-
int atype; /* auth type */
123+
flb_azure_auth_type atype; /* auth type (uses flb_azure_auth_type enum from flb_azure_auth.h) */
116124
flb_sds_t real_endpoint;
117125
flb_sds_t base_uri;
118126
flb_sds_t shared_key_prefix;
@@ -121,6 +129,13 @@ struct flb_azure_blob {
121129
unsigned char *decoded_sk; /* decoded shared key */
122130
size_t decoded_sk_size; /* size of decoded shared key */
123131

132+
#ifdef FLB_HAVE_TLS
133+
/* OAuth2 authentication */
134+
flb_sds_t oauth_url;
135+
struct flb_oauth2 *o;
136+
pthread_mutex_t token_mutex;
137+
#endif
138+
124139
#ifdef FLB_HAVE_SQLDB
125140
/*
126141
* SQLite by default is not built with multi-threading enabled, and

plugins/out_azure_blob/azure_blob_appendblob.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ flb_sds_t azb_append_blob_uri(struct flb_azure_blob *ctx, char *tag)
4040
flb_sds_printf(&uri, "/%s?comp=appendblock", tag);
4141
}
4242

43-
if (ctx->atype == AZURE_BLOB_AUTH_SAS && ctx->sas_token) {
43+
if (ctx->atype == FLB_AZURE_AUTH_SAS && ctx->sas_token) {
4444
flb_sds_printf(&uri, "&%s", ctx->sas_token);
4545
}
4646

plugins/out_azure_blob/azure_blob_blockblob.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ flb_sds_t azb_block_blob_blocklist_uri(struct flb_azure_blob *ctx, char *name)
4848
flb_sds_printf(&uri, "/%s?comp=blocklist", name);
4949
}
5050

51-
if (ctx->atype == AZURE_BLOB_AUTH_SAS && ctx->sas_token) {
51+
if (ctx->atype == FLB_AZURE_AUTH_SAS && ctx->sas_token) {
5252
flb_sds_printf(&uri, "&%s", ctx->sas_token);
5353
}
5454

@@ -103,7 +103,7 @@ flb_sds_t azb_block_blob_uri(struct flb_azure_blob *ctx, char *name,
103103
}
104104
}
105105

106-
if (ctx->atype == AZURE_BLOB_AUTH_SAS && ctx->sas_token) {
106+
if (ctx->atype == FLB_AZURE_AUTH_SAS && ctx->sas_token) {
107107
flb_sds_printf(&uri, "&%s", ctx->sas_token);
108108
}
109109

@@ -137,7 +137,7 @@ flb_sds_t azb_block_blob_uri_commit(struct flb_azure_blob *ctx,
137137
flb_sds_printf(&uri, "/%s.%s.%" PRIu64 "%s?comp=blocklist", tag, str, ms, ext);
138138
}
139139

140-
if (ctx->atype == AZURE_BLOB_AUTH_SAS && ctx->sas_token) {
140+
if (ctx->atype == FLB_AZURE_AUTH_SAS && ctx->sas_token) {
141141
flb_sds_printf(&uri, "&%s", ctx->sas_token);
142142
}
143143

plugins/out_azure_blob/azure_blob_conf.c

Lines changed: 145 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ static int flb_azure_blob_process_remote_configuration_payload(
213213

214214
context->endpoint_overriden_flag = FLB_TRUE;
215215

216-
if (context->atype == AZURE_BLOB_AUTH_KEY) {
216+
if (context->atype == FLB_AZURE_AUTH_KEY) {
217217
value_backup = context->shared_key;
218218
context->shared_key = NULL;
219219

@@ -233,7 +233,7 @@ static int flb_azure_blob_process_remote_configuration_payload(
233233

234234
context->shared_key_overriden_flag = FLB_TRUE;
235235
}
236-
else if (context->atype == AZURE_BLOB_AUTH_SAS) {
236+
else if (context->atype == FLB_AZURE_AUTH_SAS) {
237237
value_backup = context->sas_token;
238238
context->sas_token = NULL;
239239

@@ -590,27 +590,80 @@ struct flb_azure_blob *flb_azure_blob_conf_create(struct flb_output_instance *in
590590
/* Set Auth type */
591591
tmp = (char *) flb_output_get_property("auth_type", ins);
592592
if (!tmp) {
593-
ctx->atype = AZURE_BLOB_AUTH_KEY;
593+
ctx->atype = FLB_AZURE_AUTH_KEY; /* Default to legacy key auth */
594594
}
595595
else {
596596
if (strcasecmp(tmp, "key") == 0) {
597-
ctx->atype = AZURE_BLOB_AUTH_KEY;
597+
ctx->atype = FLB_AZURE_AUTH_KEY;
598598
}
599599
else if (strcasecmp(tmp, "sas") == 0) {
600-
ctx->atype = AZURE_BLOB_AUTH_SAS;
600+
ctx->atype = FLB_AZURE_AUTH_SAS;
601+
}
602+
#ifdef FLB_HAVE_TLS
603+
else if (strcasecmp(tmp, "service_principal") == 0) {
604+
ctx->atype = FLB_AZURE_AUTH_SERVICE_PRINCIPAL;
605+
606+
/* Verify required parameters for Service Principal auth */
607+
if (!ctx->tenant_id || !ctx->client_id || !ctx->client_secret) {
608+
flb_plg_error(ins, "When using service_principal auth, tenant_id, client_id, and client_secret are required");
609+
return NULL;
610+
}
611+
}
612+
else if (strcasecmp(tmp, "managed_identity") == 0) {
613+
/* Check if client_id indicates system-assigned or user-assigned managed identity */
614+
if (!ctx->client_id) {
615+
flb_plg_error(ins, "When using managed_identity auth, client_id must be set to 'system' for system-assigned or the managed identity client ID");
616+
return NULL;
617+
}
618+
619+
if (strcasecmp(ctx->client_id, "system") == 0) {
620+
ctx->atype = FLB_AZURE_AUTH_MANAGED_IDENTITY_SYSTEM;
621+
} else {
622+
ctx->atype = FLB_AZURE_AUTH_MANAGED_IDENTITY_USER;
623+
}
601624
}
625+
else if (strcasecmp(tmp, "workload_identity") == 0) {
626+
ctx->atype = FLB_AZURE_AUTH_WORKLOAD_IDENTITY;
627+
628+
/* Verify required parameters for Workload Identity auth */
629+
if (!ctx->tenant_id || !ctx->client_id) {
630+
flb_plg_error(ins, "When using workload_identity auth, tenant_id and client_id are required");
631+
return NULL;
632+
}
633+
634+
/* Set default token file path if not specified */
635+
if (!ctx->workload_identity_token_file) {
636+
ctx->workload_identity_token_file = flb_sds_create(FLB_AZURE_WORKLOAD_IDENTITY_TOKEN_FILE);
637+
if (!ctx->workload_identity_token_file) {
638+
flb_errno();
639+
flb_plg_error(ins, "Could not allocate default workload identity token path");
640+
return NULL;
641+
}
642+
}
643+
}
644+
#else
645+
else if (strcasecmp(tmp, "service_principal") == 0 ||
646+
strcasecmp(tmp, "managed_identity") == 0 ||
647+
strcasecmp(tmp, "workload_identity") == 0) {
648+
flb_plg_error(ctx->ins, "OAuth authentication requires TLS support. "\
649+
"Rebuild with -DFLB_TLS=ON");
650+
return NULL;
651+
}
652+
#endif
602653
else {
603-
flb_plg_error(ctx->ins, "invalid auth_type value '%s'", tmp);
654+
flb_plg_error(ctx->ins, "invalid auth_type value '%s'. Valid options are: 'key', 'sas', 'service_principal', 'managed_identity', or 'workload_identity'", tmp);
604655
return NULL;
605656
}
606657
}
607-
if (ctx->atype == AZURE_BLOB_AUTH_KEY &&
658+
659+
/* Validate auth-specific requirements */
660+
if (ctx->atype == FLB_AZURE_AUTH_KEY &&
608661
ctx->shared_key == NULL) {
609662
flb_plg_error(ctx->ins, "'shared_key' has not been set");
610663
return NULL;
611664
}
612665

613-
if (ctx->atype == AZURE_BLOB_AUTH_SAS) {
666+
if (ctx->atype == FLB_AZURE_AUTH_SAS) {
614667
if (ctx->sas_token == NULL) {
615668
flb_plg_error(ctx->ins, "'sas_token' has not been set");
616669
return NULL;
@@ -621,7 +674,7 @@ struct flb_azure_blob *flb_azure_blob_conf_create(struct flb_output_instance *in
621674
}
622675

623676
/* If the shared key is set decode it */
624-
if (ctx->atype == AZURE_BLOB_AUTH_KEY &&
677+
if (ctx->atype == FLB_AZURE_AUTH_KEY &&
625678
ctx->shared_key != NULL) {
626679
ret = set_shared_key(ctx);
627680
if (ret == -1) {
@@ -730,6 +783,37 @@ struct flb_azure_blob *flb_azure_blob_conf_create(struct flb_output_instance *in
730783
}
731784
flb_output_upstream_set(ctx->u, ins);
732785

786+
#ifdef FLB_HAVE_TLS
787+
/* Initialize OAuth2 context for OAuth-based authentication methods */
788+
if (ctx->atype == FLB_AZURE_AUTH_SERVICE_PRINCIPAL ||
789+
ctx->atype == FLB_AZURE_AUTH_MANAGED_IDENTITY_SYSTEM ||
790+
ctx->atype == FLB_AZURE_AUTH_MANAGED_IDENTITY_USER ||
791+
ctx->atype == FLB_AZURE_AUTH_WORKLOAD_IDENTITY) {
792+
793+
/* Build OAuth URL based on auth type */
794+
ctx->oauth_url = flb_azure_auth_build_oauth_url(ctx->atype,
795+
ctx->tenant_id,
796+
ctx->client_id,
797+
FLB_AZURE_BLOB_RESOURCE);
798+
if (!ctx->oauth_url) {
799+
flb_plg_error(ctx->ins, "failed to create OAuth URL");
800+
return NULL;
801+
}
802+
803+
/* Create OAuth2 context */
804+
ctx->o = flb_oauth2_create(ctx->config, ctx->oauth_url, 3000);
805+
if (!ctx->o) {
806+
flb_plg_error(ctx->ins, "cannot create oauth2 context");
807+
return NULL;
808+
}
809+
810+
/* Initialize token mutex */
811+
pthread_mutex_init(&ctx->token_mutex, NULL);
812+
813+
flb_plg_info(ctx->ins, "oauth2 context initialized for auth type");
814+
}
815+
#endif
816+
733817
/* Compose base uri */
734818
ctx->base_uri = flb_sds_create_size(256);
735819
if (!ctx->base_uri) {
@@ -746,7 +830,7 @@ struct flb_azure_blob *flb_azure_blob_conf_create(struct flb_output_instance *in
746830
}
747831

748832
/* Prepare shared key buffer */
749-
if (ctx->atype == AZURE_BLOB_AUTH_KEY) {
833+
if (ctx->atype == FLB_AZURE_AUTH_KEY) {
750834
ctx->shared_key_prefix = flb_sds_create_size(256);
751835
if (!ctx->shared_key_prefix) {
752836
flb_plg_error(ctx->ins, "cannot create shared key prefix");
@@ -772,13 +856,40 @@ struct flb_azure_blob *flb_azure_blob_conf_create(struct flb_output_instance *in
772856

773857
pthread_mutex_init(&ctx->file_upload_commit_file_parts, NULL);
774858

775-
flb_plg_info(ctx->ins,
776-
"account_name=%s, container_name=%s, blob_type=%s, emulator_mode=%s, endpoint=%s, auth_type=%s",
777-
ctx->account_name, ctx->container_name,
778-
ctx->btype == AZURE_BLOB_APPENDBLOB ? "appendblob" : "blockblob",
779-
ctx->emulator_mode ? "yes" : "no",
780-
ctx->real_endpoint ? ctx->real_endpoint : "no",
781-
ctx->atype == AZURE_BLOB_AUTH_KEY ? "key" : "sas");
859+
/* Log configuration summary */
860+
{
861+
const char *auth_type_str;
862+
switch (ctx->atype) {
863+
case FLB_AZURE_AUTH_KEY:
864+
auth_type_str = "key";
865+
break;
866+
case FLB_AZURE_AUTH_SAS:
867+
auth_type_str = "sas";
868+
break;
869+
case FLB_AZURE_AUTH_SERVICE_PRINCIPAL:
870+
auth_type_str = "service_principal";
871+
break;
872+
case FLB_AZURE_AUTH_MANAGED_IDENTITY_SYSTEM:
873+
auth_type_str = "managed_identity (system)";
874+
break;
875+
case FLB_AZURE_AUTH_MANAGED_IDENTITY_USER:
876+
auth_type_str = "managed_identity (user)";
877+
break;
878+
case FLB_AZURE_AUTH_WORKLOAD_IDENTITY:
879+
auth_type_str = "workload_identity";
880+
break;
881+
default:
882+
auth_type_str = "unknown";
883+
}
884+
885+
flb_plg_info(ctx->ins,
886+
"account_name=%s, container_name=%s, blob_type=%s, emulator_mode=%s, endpoint=%s, auth_type=%s",
887+
ctx->account_name, ctx->container_name,
888+
ctx->btype == AZURE_BLOB_APPENDBLOB ? "appendblob" : "blockblob",
889+
ctx->emulator_mode ? "yes" : "no",
890+
ctx->real_endpoint ? ctx->real_endpoint : "no",
891+
auth_type_str);
892+
}
782893
return ctx;
783894
}
784895

@@ -826,6 +937,23 @@ void flb_azure_blob_conf_destroy(struct flb_azure_blob *ctx)
826937
flb_upstream_destroy(ctx->u);
827938
}
828939

940+
#ifdef FLB_HAVE_TLS
941+
/* Cleanup OAuth2 resources */
942+
if (ctx->oauth_url) {
943+
flb_sds_destroy(ctx->oauth_url);
944+
}
945+
946+
if (ctx->o) {
947+
flb_oauth2_destroy(ctx->o);
948+
}
949+
950+
if (ctx->atype == FLB_AZURE_AUTH_SERVICE_PRINCIPAL ||
951+
ctx->atype == FLB_AZURE_AUTH_MANAGED_IDENTITY_SYSTEM ||
952+
ctx->atype == FLB_AZURE_AUTH_MANAGED_IDENTITY_USER ||
953+
ctx->atype == FLB_AZURE_AUTH_WORKLOAD_IDENTITY) {
954+
pthread_mutex_destroy(&ctx->token_mutex);
955+
}
956+
#endif
829957

830958
azb_db_close(ctx);
831959
flb_free(ctx);

0 commit comments

Comments
 (0)