Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/fluent-bit/flb_oauth2.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct flb_oauth2_config {
flb_sds_t token_url;
flb_sds_t client_id;
flb_sds_t client_secret;
flb_sds_t client_secret_file;
flb_sds_t user_agent;
flb_sds_t scope;
flb_sds_t audience;
Expand Down
5 changes: 5 additions & 0 deletions plugins/out_http/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,11 @@ static struct flb_config_map config_map[] = {
0, FLB_TRUE, offsetof(struct flb_out_http, oauth2_config.client_secret),
"OAuth2 client_secret"
},
{
FLB_CONFIG_MAP_STR, "oauth2.client_secret_file", NULL,
0, FLB_TRUE, offsetof(struct flb_out_http, oauth2_config.client_secret_file),
"Optional OAuth2 client_secret file path"
},
{
FLB_CONFIG_MAP_STR, "oauth2.user_agent", NULL,
0, FLB_TRUE, offsetof(struct flb_out_http, oauth2_config.user_agent),
Expand Down
6 changes: 4 additions & 2 deletions plugins/out_http/http_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,10 @@ struct flb_out_http *flb_http_conf_create(struct flb_output_instance *ins,
return NULL;
}
}
else if (!ctx->oauth2_config.client_secret) {
flb_plg_error(ctx->ins, "oauth2 basic/post require client_secret");
else if (!ctx->oauth2_config.client_secret &&
!ctx->oauth2_config.client_secret_file) {
flb_plg_error(ctx->ins, "oauth2 basic/post require client_secret "
"or client_secret_file");
flb_http_conf_destroy(ctx);
return NULL;
}
Expand Down
6 changes: 4 additions & 2 deletions plugins/out_opentelemetry/opentelemetry_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,10 @@ struct opentelemetry_context *flb_opentelemetry_context_create(struct flb_output
return NULL;
}
}
else if (!ctx->oauth2_config.client_secret) {
flb_plg_error(ctx->ins, "oauth2 basic/post require client_secret");
else if (!ctx->oauth2_config.client_secret &&
!ctx->oauth2_config.client_secret_file) {
flb_plg_error(ctx->ins, "oauth2 basic/post require client_secret "
"or client_secret_file");
flb_opentelemetry_context_destroy(ctx);
return NULL;
}
Expand Down
122 changes: 122 additions & 0 deletions src/flb_oauth2.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ struct flb_config_map oauth2_config_map[] = {
0, FLB_TRUE, offsetof(struct flb_oauth2_config, client_secret),
"OAuth2 client_secret"
},
{
FLB_CONFIG_MAP_STR, "oauth2.client_secret_file", NULL,
0, FLB_TRUE, offsetof(struct flb_oauth2_config, client_secret_file),
"Optional OAuth2 client_secret file path"
},
{
FLB_CONFIG_MAP_STR, "oauth2.user_agent", NULL,
0, FLB_TRUE, offsetof(struct flb_oauth2_config, user_agent),
Expand Down Expand Up @@ -190,6 +195,7 @@ static void oauth2_apply_defaults(struct flb_oauth2_config *cfg)
cfg->token_url = NULL;
cfg->client_id = NULL;
cfg->client_secret = NULL;
cfg->client_secret_file = NULL;
cfg->user_agent = NULL;
cfg->scope = NULL;
cfg->audience = NULL;
Expand Down Expand Up @@ -249,6 +255,15 @@ static int oauth2_clone_config(struct flb_oauth2_config *dst,
}
}

if (src->client_secret_file) {
dst->client_secret_file = flb_sds_create(src->client_secret_file);
if (!dst->client_secret_file) {
flb_errno();
flb_oauth2_config_destroy(dst);
return -1;
}
}

if (src->user_agent) {
dst->user_agent = flb_sds_create(src->user_agent);
if (!dst->user_agent) {
Expand Down Expand Up @@ -339,6 +354,8 @@ void flb_oauth2_config_destroy(struct flb_oauth2_config *cfg)
cfg->client_id = NULL;
flb_sds_destroy(cfg->client_secret);
cfg->client_secret = NULL;
flb_sds_destroy(cfg->client_secret_file);
cfg->client_secret_file = NULL;
flb_sds_destroy(cfg->user_agent);
cfg->user_agent = NULL;
flb_sds_destroy(cfg->scope);
Expand Down Expand Up @@ -1175,11 +1192,95 @@ static int oauth2_http_request(struct flb_oauth2 *ctx, flb_sds_t body)
return -1;
}

/*
* Read the client_secret from a file, trimming trailing CR/LF characters.
* Returns 0 and a newly-allocated flb_sds_t in *out on success, -1 otherwise.
*/
static int oauth2_read_secret_file(const char *path, flb_sds_t *out)
{
int ret;
size_t len;
size_t size = 0;
char *buf = NULL;

ret = flb_utils_read_file((char *) path, &buf, &size);
if (ret != 0 || !buf) {
flb_error("[oauth2] cannot read client_secret_file '%s'", path);
return -1;
}

/* trim trailing new lines */
for (len = size; len > 0; len--) {
if (buf[len - 1] != '\n' && buf[len - 1] != '\r') {
break;
}
}

if (len == 0) {
flb_free(buf);
flb_error("[oauth2] client_secret_file '%s' is empty", path);
return -1;
}

*out = flb_sds_create_len(buf, len);
flb_free(buf);

if (!*out) {
flb_errno();
return -1;
}

return 0;
}

/*
* Load client_secret from client_secret_file, replacing the current value. The
* file is re-read on every refresh so a rotated secret is always picked up,
* independent of filesystem mtime resolution. No-op for auth methods that do
* not use client_secret, or when client_secret_file is unset.
*/
static int oauth2_refresh_client_secret_from_file(struct flb_oauth2 *ctx)
{
int ret;
flb_sds_t secret = NULL;

if (ctx->cfg.auth_method != FLB_OAUTH2_AUTH_METHOD_BASIC &&
ctx->cfg.auth_method != FLB_OAUTH2_AUTH_METHOD_POST) {
return 0;
}

if (!ctx->cfg.client_secret_file) {
return 0;
}

ret = oauth2_read_secret_file(ctx->cfg.client_secret_file, &secret);
if (ret != 0) {
return -1;
}

if (ctx->cfg.client_secret) {
flb_sds_destroy(ctx->cfg.client_secret);
}
ctx->cfg.client_secret = secret;

return 0;
}

static int oauth2_refresh_locked(struct flb_oauth2 *ctx)
{
int ret;
flb_sds_t body;

/*
* Pick up a rotated secret file before building the request so both the
* POST body and the BASIC auth header use the current value.
*/
ret = oauth2_refresh_client_secret_from_file(ctx);
if (ret != 0) {
flb_error("[oauth2] could not refresh client_secret from file");
return -1;
Comment thread
fernandoalexandre marked this conversation as resolved.
}

body = oauth2_build_body(ctx);
if (!body) {
flb_error("[oauth2] could not build request body");
Expand Down Expand Up @@ -1274,6 +1375,27 @@ struct flb_oauth2 *flb_oauth2_create_from_config(struct flb_config *config,
return NULL;
}
}

/*
* When a client_secret_file is configured, load it now so failures are
* surfaced at context creation. If both client_secret and
* client_secret_file are set, the file takes precedence.
*/
if (ctx->cfg.client_secret_file) {
if (ctx->cfg.client_secret) {
flb_debug("[oauth2] both client_secret and client_secret_file are "
"set; client_secret_file takes precedence");
}

ret = oauth2_refresh_client_secret_from_file(ctx);
if (ret != 0) {
flb_error("[oauth2] failed to load client_secret_file '%s'",
ctx->cfg.client_secret_file);
flb_oauth2_destroy(ctx);
return NULL;
}
}

ctx->auth_url = flb_sds_create(ctx->cfg.token_url);
if (!ctx->auth_url) {
flb_errno();
Expand Down
Loading