ZuploZuplo
LoginStart for Free
  • Documentation
  • API Reference

Upstream AWS Service Auth Policy

Authenticate to AWS upstreams using an IAM access key pair, optionally exchanged for an IAM role's temporary credentials via STS AssumeRole. This policy resolves AWS credentials and makes them available to the AWS Lambda handler and to custom code, which sign upstream requests with AWS Signature Version 4.

With this policy, you'll benefit from:

  • Reusable Credentials: Resolve AWS credentials once and use them from the AWS Lambda handler or your own code via AwsClient.fromContext(context)
  • Role Assumption: Optionally assume an IAM role (STS AssumeRole) to obtain short-lived, least-privilege temporary credentials
  • Automatic Token Management: Temporary credentials are cached in memory and refreshed before they expire
  • Credential Security: Store access keys securely in your Zuplo environment and keep them out of source control

To avoid storing any long-lived AWS keys at all, use the upstream-aws-federated-auth policy instead, which uses Workload Identity Federation.

Beta

This policy is in beta. You can use it today, but it may change in non-backward compatible ways before the final release.

Enterprise Feature

This policy is only available as part of our enterprise plans. It's free to try only any plan for development only purposes. If you would like to use this in production reach out to us: sales@zuplo.com

Configuration

The configuration shows how to configure the policy in the 'policies.json' document.

Code
{ "name": "my-upstream-aws-service-auth-inbound-policy", "policyType": "upstream-aws-service-auth-inbound", "handler": { "export": "UpstreamAwsServiceAuthInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "accessKeyId": "$env(AWS_ACCESS_KEY_ID)", "region": "us-east-1", "secretAccessKey": "$env(AWS_SECRET_ACCESS_KEY)" } } }

Policy Configuration

  • name <string> - The name of your policy instance. This is used as a reference in your routes.
  • policyType <string> - The identifier of the policy. This is used by the Zuplo UI. Value should be upstream-aws-service-auth-inbound.
  • handler.export <string> - The name of the exported type. Value should be UpstreamAwsServiceAuthInboundPolicy.
  • handler.module <string> - The module containing the policy. Value should be $import(@zuplo/runtime).
  • handler.options <object> - The options for this policy. See Policy Options below.

Policy Options

The options for this policy are specified below. All properties are optional unless specifically marked as required.

  • accessKeyId (required) <string> - The AWS access key ID. Store the value in an environment variable rather than in source.
  • secretAccessKey (required) <string> - The AWS secret access key. Always store this in an environment variable.
  • region (required) <string> - The AWS region. Used for the STS endpoint when 'roleArn' is set, and as the default signing region for consumers of the resolved credentials.
  • sessionToken <string> - The AWS session token, required only when the configured access key pair is itself a temporary credential.
  • roleArn <string> - An IAM role to assume using STS AssumeRole with the configured access keys. When set, the resolved credentials are the role's temporary credentials instead of the static keys.
  • externalId <string> - The external ID to pass to STS AssumeRole when the role's trust policy requires one.
  • roleSessionName <string> - The STS role session name recorded in AWS CloudTrail. Must match the pattern [\w+=,.@-]64. Defaults to "zuplo-gateway".
  • durationSeconds <number> - The lifetime in seconds of the temporary credentials requested from STS (900-43200). The assumed role's maximum session duration may further limit this value. Defaults to 3600.
  • stsEndpoint <string> - Overrides the STS endpoint URL. Only needed for non-standard partitions such as AWS GovCloud or AWS China.
  • tokenRetries <number> - The number of times to retry fetching temporary credentials in the event of a failure. Defaults to 3.
  • expirationOffsetSeconds <number> - The number of seconds before credential expiration at which cached credentials are discarded and refreshed. Defaults to 300.

Using the Policy

Overview

The Upstream AWS Service Auth policy resolves AWS credentials and registers them on the request context. Unlike the other upstream auth policies, it does not add an Authorization header itself — AWS Signature Version 4 signs the exact final request (method, host, path, query and body hash), which is only known inside the handler. Instead, the AWS Lambda handler and your own code read the resolved credentials and sign the requests they build.

There are two modes:

  • Static credentials — the configured accessKeyId / secretAccessKey (and optional sessionToken) are used directly.
  • Assumed role — when roleArn is set, the policy calls STS AssumeRole (signed with the configured keys) and uses the role's short-lived temporary credentials. These are cached in memory and refreshed before they expire.

Using the credentials

With the AWS Lambda handler

Attach this policy to a route whose handler is awsLambdaHandler, and omit the handler's own accessKeyId / secretAccessKey. The handler will use the credentials resolved by the policy.

Code
{ "paths": { "/lambda/{path}*": { "x-zuplo-route": { "handler": { "export": "awsLambdaHandler", "module": "$import(@zuplo/runtime)", "options": { "region": "us-east-1", "functionName": "my-function" } }, "policies": { "inbound": ["upstream-aws-service-auth"] } } } } }

With custom code (for example, API Gateway with IAM auth, or S3)

Attach the policy, then sign outbound requests with AwsClient.fromContext:

Code
import { AwsClient } from "@zuplo/runtime/aws"; import { ZuploContext, ZuploRequest } from "@zuplo/runtime"; export default async function (request: ZuploRequest, context: ZuploContext) { const aws = AwsClient.fromContext(context, { service: "execute-api", region: "us-east-1", }); return aws.fetch( "https://abc123.execute-api.us-east-1.amazonaws.com/prod/orders", ); }

If a route does not attach the policy, you can run it on demand from custom code with await context.invokeInboundPolicy("upstream-aws-service-auth", request) before calling AwsClient.fromContext.

Configuration

Code
{ "name": "upstream-aws-service-auth", "policyType": "upstream-aws-service-auth", "handler": { "export": "UpstreamAwsServiceAuthInboundPolicy", "module": "$import(@zuplo/runtime)", "options": { "accessKeyId": "$env(AWS_ACCESS_KEY_ID)", "secretAccessKey": "$env(AWS_SECRET_ACCESS_KEY)", "region": "us-east-1", "roleArn": "arn:aws:iam::123456789012:role/my-gateway-role" } } }

Store accessKeyId and secretAccessKey in environment variables using $env(...) — never commit them to source.

Read more about how policies work

Edit this page
Last modified on July 10, 2026
On this page
  • Configuration
    • Policy Configuration
    • Policy Options
  • Using the Policy
  • Overview
  • Using the credentials
    • With the AWS Lambda handler
    • With custom code (for example, API Gateway with IAM auth, or S3)
  • Configuration
JSON
JSON
TypeScript
JSON