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
6 changes: 5 additions & 1 deletion include/fluent-bit/aws/flb_aws_imds.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
#define FLB_AWS_IMDS_HOST "169.254.169.254"
#define FLB_AWS_IMDS_HOST_LEN 15
#define FLB_AWS_IMDS_PORT 80
#define FLB_AWS_IMDS_TIMEOUT 1 /* 1 second */
#define FLB_AWS_IMDS_TIMEOUT 1 /* 1 second - for standard AWS IMDS */
#define FLB_AWS_IMDS_TIMEOUT_CUSTOM 10 /* 10 seconds - for custom IMDS endpoints like IAM Roles Anywhere */

/* Environment variable for custom IMDS endpoint */
#define AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV "AWS_EC2_METADATA_SERVICE_ENDPOINT"

#define FLB_AWS_IMDS_VERSION_EVALUATE 0
#define FLB_AWS_IMDS_VERSION_1 1
Expand Down
60 changes: 54 additions & 6 deletions src/aws/flb_aws_credentials_ec2.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ struct flb_aws_provider *flb_ec2_provider_create(struct flb_config *config,
struct flb_aws_provider_ec2 *implementation;
struct flb_aws_provider *provider;
struct flb_upstream *upstream;
char *endpoint;
flb_sds_t host = NULL;
flb_sds_t port_str = NULL;
flb_sds_t protocol = NULL;
flb_sds_t path = NULL;
const char *use_host;
int use_port;
int ret;

provider = flb_calloc(1, sizeof(struct flb_aws_provider));

Expand All @@ -253,17 +261,57 @@ struct flb_aws_provider *flb_ec2_provider_create(struct flb_config *config,
provider->provider_vtable = &ec2_provider_vtable;
provider->implementation = implementation;

upstream = flb_upstream_create(config, FLB_AWS_IMDS_HOST, FLB_AWS_IMDS_PORT,
FLB_IO_TCP, NULL);
/* Check for custom IMDS endpoint */
use_host = FLB_AWS_IMDS_HOST;
use_port = FLB_AWS_IMDS_PORT;
int use_custom_endpoint = FLB_FALSE;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Mid-function variable declaration.

int use_custom_endpoint = FLB_FALSE; is declared mid-block instead of alongside the other locals at the top of the function. As per coding guidelines, "Declare variables at the start of functions rather than mid-block."

🛠️ Proposed fix
     const char *use_host;
     int use_port;
     int ret;
+    int use_custom_endpoint;
 
     provider = flb_calloc(1, sizeof(struct flb_aws_provider));
@@
     use_host = FLB_AWS_IMDS_HOST;
     use_port = FLB_AWS_IMDS_PORT;
-    int use_custom_endpoint = FLB_FALSE;
-    
+    use_custom_endpoint = FLB_FALSE;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int use_custom_endpoint = FLB_FALSE;
int use_custom_endpoint;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aws/flb_aws_credentials_ec2.c` at line 267, Move the use_custom_endpoint
declaration to the function’s existing local-variable declaration block at the
start of the function, preserving its FLB_FALSE initialization and removing the
mid-function declaration.

Source: Coding guidelines


endpoint = getenv(AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV);
if (endpoint && strlen(endpoint) > 0) {
ret = flb_utils_url_split_sds(endpoint, &protocol, &host, &port_str, &path);
if (ret >= 0 && host) {
use_host = host;
use_custom_endpoint = FLB_TRUE;
if (port_str) {
use_port = atoi(port_str);
if (use_port <= 0 || use_port > 65535) {
use_port = FLB_AWS_IMDS_PORT;
}
}
flb_info("[aws_credentials] Using custom IMDS endpoint: %s:%d",
use_host, use_port);
}
flb_sds_destroy(protocol);
flb_sds_destroy(port_str);
flb_sds_destroy(path);
}
Comment on lines +264 to +287

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Silent fallback when the custom endpoint URL fails to parse.

If flb_utils_url_split_sds fails or returns no host, use_custom_endpoint stays FLB_FALSE and the code falls back to the default IMDS host with no log at all. A user who sets AWS_EC2_METADATA_SERVICE_ENDPOINT to a malformed value has no way to know their configuration was silently ignored and requests are instead going to 169.254.169.254. As per coding guidelines, "Validate both success and failure paths, including invalid payloads, boundary sizes, and null or missing fields."

🛠️ Proposed fix to log on parse failure
     endpoint = getenv(AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV);
     if (endpoint && strlen(endpoint) > 0) {
         ret = flb_utils_url_split_sds(endpoint, &protocol, &host, &port_str, &path);
         if (ret >= 0 && host) {
             use_host = host;
             use_custom_endpoint = FLB_TRUE;
             if (port_str) {
                 use_port = atoi(port_str);
                 if (use_port <= 0 || use_port > 65535) {
                     use_port = FLB_AWS_IMDS_PORT;
                 }
             }
             flb_info("[aws_credentials] Using custom IMDS endpoint: %s:%d",
                      use_host, use_port);
         }
+        else {
+            flb_error("[aws_credentials] invalid %s value: %s, using default IMDS endpoint",
+                      AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV, endpoint);
+        }
         flb_sds_destroy(protocol);
         flb_sds_destroy(port_str);
         flb_sds_destroy(path);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* Check for custom IMDS endpoint */
use_host = FLB_AWS_IMDS_HOST;
use_port = FLB_AWS_IMDS_PORT;
int use_custom_endpoint = FLB_FALSE;
endpoint = getenv(AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV);
if (endpoint && strlen(endpoint) > 0) {
ret = flb_utils_url_split_sds(endpoint, &protocol, &host, &port_str, &path);
if (ret >= 0 && host) {
use_host = host;
use_custom_endpoint = FLB_TRUE;
if (port_str) {
use_port = atoi(port_str);
if (use_port <= 0 || use_port > 65535) {
use_port = FLB_AWS_IMDS_PORT;
}
}
flb_info("[aws_credentials] Using custom IMDS endpoint: %s:%d",
use_host, use_port);
}
flb_sds_destroy(protocol);
flb_sds_destroy(port_str);
flb_sds_destroy(path);
}
/* Check for custom IMDS endpoint */
use_host = FLB_AWS_IMDS_HOST;
use_port = FLB_AWS_IMDS_PORT;
int use_custom_endpoint = FLB_FALSE;
endpoint = getenv(AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV);
if (endpoint && strlen(endpoint) > 0) {
ret = flb_utils_url_split_sds(endpoint, &protocol, &host, &port_str, &path);
if (ret >= 0 && host) {
use_host = host;
use_custom_endpoint = FLB_TRUE;
if (port_str) {
use_port = atoi(port_str);
if (use_port <= 0 || use_port > 65535) {
use_port = FLB_AWS_IMDS_PORT;
}
}
flb_info("[aws_credentials] Using custom IMDS endpoint: %s:%d",
use_host, use_port);
}
else {
flb_error("[aws_credentials] invalid %s value: %s, using default IMDS endpoint",
AWS_EC2_METADATA_SERVICE_ENDPOINT_ENV, endpoint);
}
flb_sds_destroy(protocol);
flb_sds_destroy(port_str);
flb_sds_destroy(path);
}
🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 275-275: Avoid atoi/atol/atoll/atof: they perform no error detection, returning 0 on non-numeric input and invoking undefined behavior on out-of-range values. This rule flags every use of these functions regardless of data provenance. Convert strings with strtol/strtoul/strtod and check errno (and the endptr) so malformed or overflowing input is rejected.
Context: atoi(port_str)
Note: [CWE-20] Improper Input Validation.

(atoi-no-error-detection-c)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aws/flb_aws_credentials_ec2.c` around lines 264 - 287, Update the custom
endpoint handling around flb_utils_url_split_sds to log a warning when parsing
fails or no host is returned, while preserving the existing fallback to the
default IMDS endpoint and cleanup of parsed values. Keep successful valid-host
handling unchanged.

Source: Coding guidelines


upstream = flb_upstream_create(config, use_host, use_port, FLB_IO_TCP, NULL);
Comment on lines +264 to +289

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does fluent-bit's flb_upstream_create_url function handle https scheme and set FLB_IO_TLS automatically?

💡 Result:

Yes, the flb_upstream_create_url function in Fluent Bit correctly handles the https scheme and automatically sets the FLB_IO_TLS flag if it is not already present [1][2]. When flb_upstream_create_url parses a URL, it examines the protocol component [1][2]. If the protocol is identified as https and no port is explicitly specified, the function defaults the port to 443 [1][2]. During this process, it checks the provided flags; if the FLB_IO_TLS bit is not set, it performs a bitwise OR operation to add FLB_IO_TLS to the flags [1][2]. This ensures that the upstream context is initialized with the appropriate transport security settings for an HTTPS connection [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)flb_aws_credentials_ec2\.c$|(^|/)flb_upstream\.c$|(^|/)flb_upstream\.h$|(^|/)aws.*credentials.*ec2.*\.(c|h)$' || true

echo "== target section =="
sed -n '1,340p' src/aws/flb_aws_credentials_ec2.c | nl -ba | sed -n '220,310p'

echo "== upstream create/url symbols =="
rg -n "flb_upstream_create\(|flb_upstream_create_url|AWSCONFIG_HTTPS|AWS_EC2_METADATA_SERVICE_ENDPOINT|FLB_IO_TLS|FLB_AWS_IMDS" src/aws/flb_aws_credentials_ec2.c src/flb_upstream.c src/include/flb_upstream.h 2>/dev/null || true

echo "== flb_upstream_create_url implementation slice =="
rg -n "flb_upstream_create_url" src/flb_upstream.c src -g '*upstream*'
sed -n '1,420p' src/flb_upstream.c | nl -ba | sed -n '1,520p' | rg -C 25 "flb_upstream_create_url|AWSCONFIG_HTTPS|protocol" || true

Repository: fluent/fluent-bit

Length of output: 362


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files =="
git ls-files | grep -E '(^|/)flb_aws_credentials_ec2\.c$|(^|/)flb_upstream\.c$|(^|/)flb_upstream\.h$|(^|/)tests/internal/aws_credentials_ec2\.c$' || true

echo "== target section =="
awk '{printf "%d\t%s\n", NR, $0}' src/aws/flb_aws_credentials_ec2.c | sed -n '230,305p'

echo "== upstream symbols in target/context files =="
grep -n "flb_upstream_create\|flb_upstream_create_url\|AWS_EC2_METADATA_SERVICE_ENDPOINT\|FLB_AWS_IMDS\|FLB_IO_TLS\|AWSCONFIG_HTTPS\|AWS_EC2_METADATA_SERVICE_ENDPOINT_TLS" src/aws/flb_aws_credentials_ec2.c src/flb_upstream.c include/fluent-bit/flb_upstream.h tests/internal/aws_credentials_ec2.c

echo "== flb_upstream_create_url implementation =="
awk '{printf "%d\t%s\n", NR, $0}' src/flb_upstream.c | sed -n '1,380p' | grep -C 25 "flb_upstream_create_url\|AWSCONFIG_HTTPS\|protocol\|https\|FLB_IO_TLS"

echo "== AWS cred create helper declarations/usages around credentials env =="
awk '{printf "%d\t%s\n", NR, $0}' src/aws/flb_aws_credentials_ec2.c | sed -n '20,140p'

Repository: fluent/fluent-bit

Length of output: 12203


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== flb_upstream_create_url implementation =="
awk '{printf "%d\t%s\n", NR, $0}' src/flb_upstream.c | sed -n '410,470p'

echo "== headers around constants =="
awk '{printf "%d\t%s\n", NR, $0}' include/fluent-bit/aws/flb_aws_imds.h | sed -n '1,160p'
awk '{printf "%d\t%s\n", NR, $0}' include/fluent-bit/flb_http_client.h | sed -n '1,80p'

echo "== credential tests around HTTPS custom endpoint =="
awk '{printf "%d\t%s\n", NR, $0}' tests/internal/aws_credentials_ec2.c | sed -n '1000,1080p'
grep -Rn "AWS_EC2_METADATA_SERVICE_ENDPOINT.*https\|https://" tests include src/aws | head -n 80

Repository: fluent/fluent-bit

Length of output: 22267


Propagate the IMDS URL protocol into the upstream flags.

flb_utils_url_split_sds() already parses protocol, but this path always destroys it and creates the EC2 metadata upstream with FLB_IO_TCP and no TLS. An https:// custom IMDS endpoint is accepted, then connected to over plaintext; default to HTTPS/TLS for https:// URLs, use flb_upstream_create_url(), or make the scheme explicit.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 275-275: Avoid atoi/atol/atoll/atof: they perform no error detection, returning 0 on non-numeric input and invoking undefined behavior on out-of-range values. This rule flags every use of these functions regardless of data provenance. Convert strings with strtol/strtoul/strtod and check errno (and the endptr) so malformed or overflowing input is rejected.
Context: atoi(port_str)
Note: [CWE-20] Improper Input Validation.

(atoi-no-error-detection-c)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aws/flb_aws_credentials_ec2.c` around lines 264 - 289, Update the custom
endpoint handling around flb_utils_url_split_sds() and flb_upstream_create() to
preserve the parsed protocol and propagate HTTPS as TLS-enabled upstream
configuration. Use the URL-aware upstream creation path or explicitly set the
corresponding secure flags, while retaining plain TCP for HTTP/default
endpoints; only destroy protocol after the upstream setup no longer needs it.


if (host) {
flb_sds_destroy(host);
}

if (!upstream) {
flb_aws_provider_destroy(provider);
flb_debug("[aws_credentials] unable to connect to EC2 IMDS.");
return NULL;
}

/* IMDSv2 token request will timeout if hops = 1 and running within container */
upstream->base.net.connect_timeout = FLB_AWS_IMDS_TIMEOUT;
upstream->base.net.io_timeout = FLB_AWS_IMDS_TIMEOUT;
/*
* Set timeout based on endpoint type:
* - Standard AWS IMDS: 1 second (fast local endpoint)
* - Custom IMDS endpoints (e.g., IAM Roles Anywhere): 10 seconds (certificate auth takes longer)
*/
if (use_custom_endpoint) {
upstream->base.net.connect_timeout = FLB_AWS_IMDS_TIMEOUT_CUSTOM;
upstream->base.net.io_timeout = FLB_AWS_IMDS_TIMEOUT_CUSTOM;
Comment on lines +306 to +308

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the custom timeout after upstream setup

When AWS_EC2_METADATA_SERVICE_ENDPOINT is set, this gives the EC2 upstream a 10s timeout only at provider creation, but every AWS output later calls provider_vtable->upstream_set(...); upstream_set_fn_ec2 then restores both timeouts to FLB_AWS_IMDS_TIMEOUT (1s). That means slow custom endpoints such as aws_signing_helper serve can still time out on credential refreshes after plugin initialization, so the provider needs to remember the custom timeout and restore that same value in upstream_set_fn_ec2.

Useful? React with 👍 / 👎.

flb_info("[aws_credentials] Using extended timeout (%d seconds) for custom IMDS endpoint",
FLB_AWS_IMDS_TIMEOUT_CUSTOM);
} else {
upstream->base.net.connect_timeout = FLB_AWS_IMDS_TIMEOUT;
upstream->base.net.io_timeout = FLB_AWS_IMDS_TIMEOUT;
}
upstream->base.net.keepalive = FLB_FALSE; /* On timeout, the connection is broken */

implementation->client = generator->create();
Expand All @@ -278,7 +326,7 @@ struct flb_aws_provider *flb_ec2_provider_create(struct flb_config *config,
implementation->client->provider = NULL;
implementation->client->region = NULL;
implementation->client->service = NULL;
implementation->client->port = 80;
implementation->client->port = use_port;
implementation->client->flags = 0;
implementation->client->proxy = NULL;
implementation->client->upstream = upstream;
Expand Down
87 changes: 25 additions & 62 deletions src/aws/flb_aws_imds.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,9 @@ struct flb_aws_imds *flb_aws_imds_create(const struct flb_aws_imds_config *imds_
flb_aws_imds_destroy(ctx);
return NULL;
}
if (0 != strncmp(ec2_imds_client->upstream->tcp_host, FLB_AWS_IMDS_HOST,
FLB_AWS_IMDS_HOST_LEN)) {
flb_debug("[imds] ec2_imds_client tcp host must be set to %s", FLB_AWS_IMDS_HOST);
flb_aws_imds_destroy(ctx);
return NULL;
}
if (ec2_imds_client->upstream->tcp_port != FLB_AWS_IMDS_PORT) {
flb_debug("[imds] ec2_imds_client tcp port must be set to %i", FLB_AWS_IMDS_PORT);
flb_aws_imds_destroy(ctx);
return NULL;
}

/* Allow custom IMDS endpoints via AWS_EC2_METADATA_SERVICE_ENDPOINT */
/* The hardcoded host/port checks have been removed to support custom endpoints */
Comment on lines +84 to +85

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the IMDS creation test expectations

Removing the host/port rejection makes flb_aws_imds_create() succeed for any non-null upstream, but test_ec2_imds_create_and_destroy still asserts that "Invalid host", an extended host string, and port 0xBAD return NULL. That existing internal test will now fail and leak the successful contexts it overwrites, so the test needs to be adjusted to the new custom-endpoint contract.

Useful? React with 👍 / 👎.


/* Connect client */
ctx->ec2_imds_client = ec2_imds_client;
Expand Down Expand Up @@ -250,7 +242,6 @@ static int get_imds_version(struct flb_aws_imds *ctx)
{
int ret;
struct flb_aws_client *client = ctx->ec2_imds_client;
struct flb_aws_header invalid_token_header;
struct flb_http_client *c = NULL;

if (ctx->imds_version != FLB_AWS_IMDS_VERSION_EVALUATE) {
Expand All @@ -259,65 +250,37 @@ static int get_imds_version(struct flb_aws_imds *ctx)

/*
* Evaluate version
* To evaluate wether IMDSv2 is available, send an invalid token
* in IMDS request. If response status is 'Unauthorized', then IMDSv2
* is available.
* Try to get an IMDSv2 token first. If that fails, fall back to IMDSv1.
* This approach is more compatible with custom IMDS implementations like IAM Roles Anywhere.
*/
invalid_token_header = imds_v2_token_token_header_template;
invalid_token_header.val = "INVALID";
invalid_token_header.val_len = 7;
c = client->client_vtable->request(client, FLB_HTTP_GET, FLB_AWS_IMDS_ROOT, NULL, 0,
&invalid_token_header, 1);

ctx->imds_version = FLB_AWS_IMDS_VERSION_2;
ret = refresh_imds_v2_token(ctx);
if (ret == 0) {
Comment on lines +256 to +258

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Update the strict IMDS mock sequence

This changes version detection so the first mocked request is now PUT /latest/api/token, but the existing tests/internal/aws_credentials_ec2.c cases still start their response chains with GET / plus the invalid-token header. The mock checks requests in order, so test_ec2_provider_v2, test_ec2_provider_v1, and the error-path cases will fail before they reach the credential requests unless those expectations are rewritten for the new probe order.

Useful? React with 👍 / 👎.

/* Successfully got IMDSv2 token */
flb_info("[imds] using IMDSv2");
return FLB_AWS_IMDS_VERSION_2;
}

/* IMDSv2 token request failed, try IMDSv1 */
flb_debug("[imds] IMDSv2 token request failed, testing IMDSv1");
ctx->imds_version = FLB_AWS_IMDS_VERSION_EVALUATE;
c = client->client_vtable->request(client, FLB_HTTP_GET, FLB_AWS_IMDS_ROOT,
NULL, 0, NULL, 0);

if (!c) {
flb_debug("[imds] imds endpoint unavailable");
return FLB_AWS_IMDS_VERSION_EVALUATE;
}

/* Unauthorized response means that IMDS version 2 is in use */
if (c->resp.status == 401) {
ctx->imds_version = FLB_AWS_IMDS_VERSION_2;
ret = refresh_imds_v2_token(ctx);
if (ret == -1) {
/*
* Token cannot be refreshed, test IMDSv1
* If IMDSv1 cannot be used, response will be status 401
*/
flb_http_client_destroy(c);
ctx->imds_version = FLB_AWS_IMDS_VERSION_EVALUATE;
c = client->client_vtable->request(client, FLB_HTTP_GET, FLB_AWS_IMDS_ROOT,
NULL, 0, NULL, 0);
if (!c) {
flb_debug("[imds] imds v1 attempt, endpoint unavailable");
return FLB_AWS_IMDS_VERSION_EVALUATE;
}

if (c->resp.status == 200) {
flb_info("[imds] to use IMDSv2, set --http-put-response-hop-limit to 2");
}
else {
/* IMDSv1 unavailable. IMDSv2 beyond network hop count */
flb_warn("[imds] failed to retrieve IMDSv2 token and IMDSv1 unavailable. "
"This is likely due to instance-metadata-options "
"--http-put-response-hop-limit being set to 1 and --http-tokens "
"set to required. "
"To use IMDSv2, please set --http-put-response-hop-limit to 2 as "
"described https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/"
"configuring-instance-metadata-options.html");
}
}
}

/*
* Success means that IMDS version 1 is in use
*/

if (c->resp.status == 200) {
flb_warn("[imds] falling back on IMDSv1");
flb_info("[imds] falling back to IMDSv1");
ctx->imds_version = FLB_AWS_IMDS_VERSION_1;
flb_http_client_destroy(c);
return FLB_AWS_IMDS_VERSION_1;
}

flb_http_client_destroy(c);
return ctx->imds_version;
return FLB_AWS_IMDS_VERSION_EVALUATE;
}

/*
Expand Down
39 changes: 39 additions & 0 deletions tests/internal/aws_credentials_ec2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,44 @@ static void test_ec2_imds_create_and_destroy()
flb_config_exit(config_fluent);
}

static void test_ec2_provider_custom_endpoint()
{
setenv("AWS_EC2_METADATA_SERVICE_ENDPOINT", "http://127.0.0.1:9911", 1);

setup_test(FLB_AWS_CLIENT_MOCK(
response(
expect(URI, "/latest/api/token"),
expect(METHOD, FLB_HTTP_PUT),
set(STATUS, 200),
set(PAYLOAD, "TESTTOKEN")
),
response(
expect(URI, "/latest/meta-data/iam/security-credentials/"),
expect(HEADER, "X-aws-ec2-metadata-token", "TESTTOKEN"),
expect(METHOD, FLB_HTTP_GET),
set(STATUS, 200),
set(PAYLOAD, "test-role")
),
response(
expect(URI, "/latest/meta-data/iam/security-credentials/test-role"),
expect(HEADER, "X-aws-ec2-metadata-token", "TESTTOKEN"),
expect(METHOD, FLB_HTTP_GET),
set(STATUS, 200),
set(PAYLOAD, "{\"AccessKeyId\":\"AKIATEST\",\"SecretAccessKey\":\"SECRET\",\"Token\":\"TOKEN\"}")
)
));

creds = provider->provider_vtable->get_credentials(provider);
TEST_CHECK(creds != NULL);
TEST_CHECK(strcmp("AKIATEST", creds->access_key_id) == 0);
TEST_CHECK(strcmp("SECRET", creds->secret_access_key) == 0);
TEST_CHECK(strcmp("TOKEN", creds->session_token) == 0);

flb_aws_credentials_destroy(creds);
unsetenv("AWS_EC2_METADATA_SERVICE_ENDPOINT");
cleanup_test();
}

TEST_LIST = {
{ "test_ec2_provider_v2" , test_ec2_provider_v2},
{ "test_ec2_provider_v1" , test_ec2_provider_v1},
Expand All @@ -1033,5 +1071,6 @@ TEST_LIST = {
{ "test_ec2_provider_acquire_token_error" , test_ec2_provider_acquire_token_error},
{ "test_ec2_provider_metadata_request_error" , test_ec2_provider_metadata_request_error},
{ "test_ec2_imds_create_and_destroy" , test_ec2_imds_create_and_destroy},
{ "test_ec2_provider_custom_endpoint" , test_ec2_provider_custom_endpoint},
{ 0 }
};
Loading