Skip to content

Feature request: Add Signer utility for SigV4 request signing #1258

Description

@hjgraca

Use case

When a Lambda function calls an IAM-authenticated endpoint (API Gateway with IAM auth, a Lambda Function URL set to AWS_IAM, AppSync, or anything behind an IAM authorizer), the outbound HTTP request has to be signed with AWS Signature Version 4.

.NET has no first-class helper for this. Customers either hand-roll the canonical request and signature, which is fiddly and easy to get subtly wrong, or they reach into Amazon.Runtime.AWS4Signer in the AWS SDK, which isn't really meant as a public way to sign arbitrary HttpClient calls. Either way they end up re-resolving credentials and region from the runtime and threading them through every call.

Common cases:

  • Calling an IAM-protected API Gateway API from a Lambda.
  • Invoking another team's Function URL that's locked down with AWS_IAM.
  • Server-to-server AppSync calls using IAM auth.
  • Cross-account calls where IAM signing is the auth mechanism instead of a bearer token.

Powertools for TypeScript shipped a Signer utility in v2.34.0 (aws-powertools/powertools-lambda-typescript#5344). This asks for the .NET equivalent.

One caveat worth stating up front: this is close to net-new for Powertools. TypeScript is the only runtime that has it right now. Java and Python don't (I checked their repos and roadmaps). So this is a port of the TypeScript design onto .NET idioms, sitting on top of the SDK's existing SigV4 code rather than a shared cross-language precedent.

Solution/User Experience

A new AWS.Lambda.Powertools.Signer package that signs a standard HttpRequestMessage with SigV4 and reads credentials and region from the Lambda runtime by default. Signing and sending stay separate, so you can sign a request and hand it to whatever HttpClient you've already configured.

using AWS.Lambda.Powertools.Signer;

var signer = new SigV4Signer(service: "execute-api"); // region + creds from env by default

var request = new HttpRequestMessage(HttpMethod.Get,
    "https://example.execute-api.us-east-1.amazonaws.com/items");

var signed = await signer.SignAsync(request); // same request, now with SigV4 headers

using var httpClient = new HttpClient();
var response = await httpClient.SendAsync(signed);

For the common "just sign and send" path, a DelegatingHandler signs every outbound request. That's the natural .NET fit and plays well with IHttpClientFactory and DI. It's the equivalent of the TypeScript createSignedFetcher.

services.AddHttpClient("signed")
        .AddHttpMessageHandler(() => new SigV4SigningHandler(service: "execute-api"));

var client = httpClientFactory.CreateClient("signed");
var response = await client.GetAsync("https://example.execute-api.us-east-1.amazonaws.com/items");

service is required (for example execute-api, lambda, or appsync). Region defaults to AWS_REGION and credentials default to the execution-role chain, with overrides for assumed-role or cross-account cases. Under the hood it should build on the SDK's SigV4 implementation rather than a hand-written signer, and handle body hashing and the required headers (host, x-amz-date, x-amz-content-sha256, Authorization).

Alternative solutions

  • Use Amazon.Runtime.AWS4Signer directly. It's an SDK-internal type, not meant for signing arbitrary HttpClient requests, so you take on the SDK's request abstractions and the credential/region wiring yourself.
  • Hand-roll SigV4. Lots of boilerplate, and the encoding, payload hashing, and clock-skew details are easy to get wrong.
  • Use an unauthenticated path or a custom authorizer instead. That changes the security model and isn't an option when the endpoint requires IAM auth.

Acknowledgment

  • This feature request meets the Powertools for AWS Lambda (.NET) Tenets
  • Should this be considered in other Powertools for AWS Lambda languages? (TypeScript shipped it in v2.34.0; Java and Python don't have it yet)

Ports the Signer utility from Powertools for AWS Lambda (TypeScript) v2.34.0 (aws-powertools/powertools-lambda-typescript#5344).

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestNew or enhancements to existing features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions