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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ The same docker image can run on AWS Lambda, Amazon EC2, AWS Fargate, and local

### Docker Images

Add one line to your Dockerfile:
Copy the adapter into your Dockerfile and identify the OS-only runtime to AWS SDKs:

```dockerfile
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_EXECUTION_ENV=AWS_Lambda_provided_custom
```

Pre-compiled multi-arch images (x86_64 and arm64) are available at [public.ecr.aws/awsguru/aws-lambda-adapter](https://gallery.ecr.aws/awsguru/aws-lambda-adapter). [Non-AWS base images](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) may be used since the [Runtime Interface Client](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html#images-ric) ships with the Lambda Web Adapter.
Expand Down
6 changes: 5 additions & 1 deletion docs/guide/src/getting-started/docker-images.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
# Docker Images

To use Lambda Web Adapter with Docker images, package your web app in a Dockerfile and add one line to copy the adapter binary:
To use Lambda Web Adapter with Docker images, package your web app in a Dockerfile, copy the adapter binary, and identify the OS-only runtime to AWS SDKs:

```dockerfile
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_EXECUTION_ENV=AWS_Lambda_provided_custom
```

`AWS_EXECUTION_ENV` allows AWS SDK user agents to identify requests from OS-only Lambda runtimes. It must be set in the application image because a multi-stage `COPY --from` transfers the adapter binary, not environment metadata from the adapter image.

[Non-AWS base images](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) can be used since the [Runtime Interface Client](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html#images-ric) ships with the adapter.

## Example: Node.js Express App

```dockerfile
FROM public.ecr.aws/docker/library/node:20-slim
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_EXECUTION_ENV=AWS_Lambda_provided_custom
ENV PORT=7000
WORKDIR "/var/task"
ADD src/package.json /var/task/package.json
Expand Down
5 changes: 3 additions & 2 deletions docs/guide/src/getting-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ AWS Lambda Web Adapter works with Lambda functions packaged as both Docker image

## Minimal Example (Docker)

Add one line to your existing Dockerfile:
Copy the adapter into your existing Dockerfile and identify the OS-only runtime to AWS SDKs:

```dockerfile
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
ENV AWS_EXECUTION_ENV=AWS_Lambda_provided_custom
```

That's it. Your web app now runs on Lambda.
Your web app can now run on Lambda, and AWS SDK user agents can identify Lambda as its execution environment.

## Minimal Example (Zip)

Expand Down
2 changes: 2 additions & 0 deletions docs/guide/src/getting-started/zip-packages.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ AWS_LAMBDA_EXEC_WRAPPER=/opt/bootstrap

Set your function handler to your web application's startup script, e.g. `run.sh`.

The layer bootstrap sets `AWS_EXECUTION_ENV` to `AWS_Lambda_provided_custom` when the variable is otherwise unset. This allows AWS SDK user agents to identify requests from OS-only Lambda runtimes. An explicitly configured value is preserved.

## SAM Template Example

```yaml
Expand Down
7 changes: 6 additions & 1 deletion layer/bootstrap
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
#!/bin/bash

exec -- "${LAMBDA_TASK_ROOT}/${_HANDLER}"
# OS-only runtimes do not define AWS_EXECUTION_ENV. Set the standard custom-runtime
# value so AWS SDK user agents can identify requests originating from Lambda, while
# preserving a value explicitly configured by the customer.
export AWS_EXECUTION_ENV="${AWS_EXECUTION_ENV:-AWS_Lambda_provided_custom}"

exec -- "${LAMBDA_TASK_ROOT}/${_HANDLER}"
41 changes: 41 additions & 0 deletions tests/integ_tests/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1389,3 +1389,44 @@ async fn test_no_tenant_id_header_when_absent() {
endpoint.assert();
assert_eq!(200, response.status());
}

#[test]
fn test_layer_bootstrap_sets_execution_environment() {
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};

let unique = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos();
let task_root = std::env::temp_dir().join(format!("lambda-web-adapter-bootstrap-{}-{unique}", std::process::id()));
fs::create_dir(&task_root).unwrap();

let handler = task_root.join("handler");
fs::write(&handler, "#!/bin/sh\nprintf '%s' \"$AWS_EXECUTION_ENV\"\n").unwrap();
fs::set_permissions(&handler, fs::Permissions::from_mode(0o755)).unwrap();

let bootstrap = concat!(env!("CARGO_MANIFEST_DIR"), "/layer/bootstrap");
let run = |execution_env: Option<&str>| {
let mut command = Command::new(bootstrap);
command.env("LAMBDA_TASK_ROOT", &task_root).env("_HANDLER", "handler");
match execution_env {
Some(value) => {
command.env("AWS_EXECUTION_ENV", value);
}
None => {
command.env_remove("AWS_EXECUTION_ENV");
}
}
command.output().unwrap()
};

let defaulted = run(None);
assert!(defaulted.status.success());
assert_eq!(defaulted.stdout, b"AWS_Lambda_provided_custom");

let configured = run(Some("customer-configured-value"));
assert!(configured.status.success());
assert_eq!(configured.stdout, b"customer-configured-value");

fs::remove_dir_all(task_root).unwrap();
}
Loading