Skip to content

Commit c5ac8ea

Browse files
committed
feat: Add Lambda-Runtime-Invocation-Id support for cross-wiring protection
Parse the invocation ID from /next response headers, store in invocation_request, and echo it back on /response and /error via do_post. Header only sent when non-empty (backward compatible).
1 parent 356f6ce commit c5ac8ea

3 files changed

Lines changed: 34 additions & 8 deletions

File tree

‎include/aws/lambda-runtime/runtime.h‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ struct invocation_request {
7171
*/
7272
std::string tenant_id;
7373

74+
/**
75+
* The unique invocation ID for cross-wiring protection.
76+
*/
77+
std::string invocation_id;
78+
7479
/**
7580
* The number of milliseconds left before lambda terminates the current execution.
7681
*/
@@ -199,12 +204,12 @@ class runtime {
199204
/**
200205
* Tells lambda that the function has succeeded.
201206
*/
202-
post_outcome post_success(std::string const& request_id, invocation_response const& handler_response);
207+
post_outcome post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id = "");
203208

204209
/**
205210
* Tells lambda that the function has failed.
206211
*/
207-
post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response);
212+
post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id = "");
208213

209214
/**
210215
* Tells lambda that the runtime has failed during initialization.
@@ -218,7 +223,8 @@ class runtime {
218223
std::string const& url,
219224
std::string const& content_type,
220225
std::string const& payload,
221-
std::string const& xray_response);
226+
std::string const& xray_response,
227+
std::string const& invocation_id = "");
222228
std::string const m_user_agent_header;
223229
std::array<std::string const, 3> const m_endpoints;
224230
};

‎src/runtime.cpp‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static constexpr auto COGNITO_IDENTITY_HEADER = "lambda-runtime-cognito-identity
4242
static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms";
4343
static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn";
4444
static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id";
45+
static constexpr auto INVOCATION_ID_HEADER = "lambda-runtime-invocation-id";
4546
struct curl_handle_wrapper {
4647
CURL* handle;
4748
curl_handle_wrapper() : handle(curl_easy_init()) {}
@@ -318,6 +319,11 @@ runtime::next_outcome runtime::get_next()
318319
req.tenant_id = std::move(out).get_result();
319320
}
320321

322+
out = resp.get_header(INVOCATION_ID_HEADER);
323+
if (out.is_success()) {
324+
req.invocation_id = std::move(out).get_result();
325+
}
326+
321327
out = resp.get_header(DEADLINE_MS_HEADER);
322328
if (out.is_success()) {
323329
auto const& deadline_string = std::move(out).get_result();
@@ -335,18 +341,18 @@ runtime::next_outcome runtime::get_next()
335341
return {req};
336342
}
337343

338-
runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response)
344+
runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id)
339345
{
340346
std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response";
341347
return do_post(
342-
url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response());
348+
url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response(), invocation_id);
343349
}
344350

345-
runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response)
351+
runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id)
346352
{
347353
std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error";
348354
return do_post(
349-
url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response());
355+
url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response(), invocation_id);
350356
}
351357

352358
runtime::post_outcome runtime::post_init_error(runtime_response const& init_error_response)
@@ -363,7 +369,8 @@ runtime::post_outcome runtime::do_post(
363369
std::string const& url,
364370
std::string const& content_type,
365371
std::string const& payload,
366-
std::string const& xray_response)
372+
std::string const& xray_response,
373+
std::string const& invocation_id)
367374
{
368375
set_curl_post_result_options();
369376
curl_easy_setopt(lambda_runtime::m_curl_handle, CURLOPT_URL, url.c_str());
@@ -382,6 +389,10 @@ runtime::post_outcome runtime::do_post(
382389
headers = curl_slist_append(headers, "transfer-encoding:");
383390
headers = curl_slist_append(headers, m_user_agent_header.c_str());
384391

392+
if (!invocation_id.empty()) {
393+
headers = curl_slist_append(headers, ("lambda-runtime-invocation-id: " + invocation_id).c_str());
394+
}
395+
385396
logging::log_debug(
386397
LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str());
387398
headers = curl_slist_append(headers, ("content-length: " + std::to_string(payload.length())).c_str());

‎tests/unit/unit_tests.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ TEST(InvocationRequestTest, default_fields_are_empty)
333333
EXPECT_TRUE(req.cognito_identity.empty());
334334
EXPECT_TRUE(req.function_arn.empty());
335335
EXPECT_TRUE(req.tenant_id.empty());
336+
EXPECT_TRUE(req.invocation_id.empty());
336337
}
337338

338339
// --- version tests (no AWS SDK needed) ---
@@ -353,3 +354,11 @@ TEST(VersionTest, version_format)
353354
}
354355
EXPECT_EQ(2, dots);
355356
}
357+
358+
// --- invocation_id cross-wiring protection tests ---
359+
360+
TEST(InvocationRequestTest, invocation_id_default_empty)
361+
{
362+
invocation_request req;
363+
EXPECT_TRUE(req.invocation_id.empty());
364+
}

0 commit comments

Comments
 (0)