Skip to content

Commit 919b763

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 5a7f650 commit 919b763

4 files changed

Lines changed: 310 additions & 16 deletions

File tree

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: 20 additions & 1 deletion
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+
#ifdef FLB_HAVE_TLS
28+
#include <fluent-bit/flb_oauth2.h>
29+
#include <fluent-bit/flb_azure_auth.h>
30+
#endif
2731

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

55+
/* Legacy auth type definitions for backward compatibility */
5156
#define AZURE_BLOB_AUTH_KEY 0
5257
#define AZURE_BLOB_AUTH_SAS 1
5358

@@ -65,6 +70,13 @@ struct flb_azure_blob {
6570
flb_sds_t date_key;
6671
flb_sds_t auth_type;
6772
flb_sds_t sas_token;
73+
74+
/* OAuth authentication fields */
75+
flb_sds_t tenant_id;
76+
flb_sds_t client_id;
77+
flb_sds_t client_secret;
78+
flb_sds_t workload_identity_token_file;
79+
6880
flb_sds_t database_file;
6981
size_t part_size;
7082
time_t upload_parts_timeout;
@@ -112,7 +124,7 @@ struct flb_azure_blob {
112124
* Internal use
113125
*/
114126
int btype; /* blob type */
115-
int atype; /* auth type */
127+
int atype; /* auth type (now uses flb_azure_auth_type enum) */
116128
flb_sds_t real_endpoint;
117129
flb_sds_t base_uri;
118130
flb_sds_t shared_key_prefix;
@@ -121,6 +133,13 @@ struct flb_azure_blob {
121133
unsigned char *decoded_sk; /* decoded shared key */
122134
size_t decoded_sk_size; /* size of decoded shared key */
123135

136+
#ifdef FLB_HAVE_TLS
137+
/* OAuth2 authentication */
138+
flb_sds_t oauth_url;
139+
struct flb_oauth2 *o;
140+
pthread_mutex_t token_mutex;
141+
#endif
142+
124143
#ifdef FLB_HAVE_SQLDB
125144
/*
126145
* SQLite by default is not built with multi-threading enabled, and

plugins/out_azure_blob/azure_blob_conf.c

Lines changed: 145 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}
624+
}
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;
601651
}
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;
@@ -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_SCOPE);
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) {
@@ -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,27 @@ void flb_azure_blob_conf_destroy(struct flb_azure_blob *ctx)
826937
flb_upstream_destroy(ctx->u);
827938
}
828939

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

830962
azb_db_close(ctx);
831963
flb_free(ctx);

0 commit comments

Comments
 (0)