diff --git a/src/content/docs/aws/connecting/aws-cli.md b/src/content/docs/aws/connecting/aws-cli.md index 3156cbe7..02e7b541 100644 --- a/src/content/docs/aws/connecting/aws-cli.md +++ b/src/content/docs/aws/connecting/aws-cli.md @@ -45,7 +45,8 @@ aws --endpoint-url=http://localhost.localstack.cloud:4566 kinesis list-streams :::note -To enable the creation of pre-signed URLs for S3 buckets, please set both `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` to the value "test." Our pre-signed URL signature verification algorithm validates the pre-signed URL and its expiration. +Pre-signed URLs for S3 are generated with the credentials configured on the client, such as the default `test`/`test` pair shown above. +For LocalStack to be able to validate a pre-signed URL, it must be generated with valid credentials. More details at [S3 signature validation](/aws/services/s3/#signature-validation). ::: ### Configuring a custom profile diff --git a/src/content/docs/aws/connecting/credentials.md b/src/content/docs/aws/connecting/credentials.md index 01e8a0df..84fbbdfa 100644 --- a/src/content/docs/aws/connecting/credentials.md +++ b/src/content/docs/aws/connecting/credentials.md @@ -41,6 +41,8 @@ In all such cases, the account ID is evaluated to `000000000000`. ## Secret Access Key -The value of the secret access key are currently ignored by LocalStack. +The value of the secret access key is generally ignored by LocalStack. +We recommend using the same value as access key ID or `test`. -We recommend using the same value as access key ID or `test` +S3 can optionally validate request signatures, in which case the secret access key matters: it must be the secret the access key ID was issued with, or `test` for access key IDs not issued by LocalStack. +See [S3 signature validation](/aws/services/s3/#signature-validation) for details. diff --git a/src/content/docs/aws/customization/configuration-options.md b/src/content/docs/aws/customization/configuration-options.md index 7b915a7c..34751f7d 100644 --- a/src/content/docs/aws/customization/configuration-options.md +++ b/src/content/docs/aws/customization/configuration-options.md @@ -334,7 +334,8 @@ Please consult the [migration guide](/aws/services/lambda#migrating-to-lambda-v2 | Variable | Example Values | Description | | - | - | - | -| `S3_SKIP_SIGNATURE_VALIDATION`| `0` \| `1` (default) | Used to toggle validation of S3 pre-signed URL request signature. Set to `0` to validate. Note that validation can only pass if the `AWS_SECRET_ACCESS_KEY` is set to `test` or if using credentials returned from `STS.AssumeRole` | +| `S3_SKIP_SIGNATURE_VALIDATION`| `0` \| `1` (default) | Used to toggle validation of S3 pre-signed URLs. Set to `0` to validate their signature and expiration. See [Signature validation](/aws/services/s3/#signature-validation) for the credentials accepted by the validation. | +| `S3_VALIDATE_SIGNATURES` | `0` (default) \| `1` | Used to toggle SigV4 signature validation of regular (non-pre-signed) S3 requests. Set to `1` to validate the request signature and the payload integrity. See [Signature validation](/aws/services/s3/#signature-validation) for the credentials accepted by the validation. | | `S3_SKIP_KMS_KEY_VALIDATION` | `0` \| `1` (default) | Used to toggle validation of provided KMS key in S3 operations. | ### SNS diff --git a/src/content/docs/aws/services/s3.mdx b/src/content/docs/aws/services/s3.mdx index c3cb1537..9805324c 100644 --- a/src/content/docs/aws/services/s3.mdx +++ b/src/content/docs/aws/services/s3.mdx @@ -122,6 +122,9 @@ awslocal s3 presign s3://sample-bucket/image.jpg You will see a generated pre-signed URL for your S3 object. You can use [curl](https://curl.se/) or [`wget`](https://www.gnu.org/software/wget/) to retrieve the S3 object using the pre-signed URL. +By default, LocalStack does not validate the signature or the expiration of pre-signed URLs. +Check out the [Signature validation](#signature-validation) section to enable it. + ## Path-Style and Virtual Hosted-Style Requests Similar to AWS, LocalStack categorizes requests as either [Path style or Virtual-Hosted style](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html) based on the Host header of the request. @@ -154,6 +157,100 @@ The `ForcePathStyle` parameter name can vary between SDK and languages, please c If your endpoint is not prefixed with `s3.`, all requests are treated as **Path style** requests. Using the `s3.localhost.localstack.cloud` endpoint URL is recommended for all requests aimed at S3. +## Signature validation + +Like AWS, S3 in LocalStack can validate the signature of incoming requests and reject requests signed with invalid credentials. +Signature validation is disabled by default, so that S3 accepts requests signed with any credentials. + +Two independent configuration options control signature validation: + +- [`S3_SKIP_SIGNATURE_VALIDATION=0`](/aws/customization/configuration-options/#s3) validates [pre-signed URLs](#pre-signed-urls). +- [`S3_VALIDATE_SIGNATURES=1`](/aws/customization/configuration-options/#s3) validates regular, [SigV4-signed requests](#sigv4-validation). + +### Credentials + +When signature validation is enabled, requests must be signed with credentials that are valid in LocalStack. +The following credentials pass validation: + +- **Default credentials**: the default `test` access key ID with the `test` secret access key, which works out of the box. +- **IAM user credentials**: access keys created for an IAM user with [`CreateAccessKey`](https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html). + Check out the [IAM documentation](/aws/services/iam/#getting-started) to learn how to create a user and its access keys. +- **Temporary credentials**: credentials returned by the STS [`AssumeRole`](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) or [`GetSessionToken`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html) APIs, used together with their session token. + +For example, after [creating a role](/aws/services/sts/#create-an-iam-role), you can retrieve temporary credentials for it using the `AssumeRole` API: + +```bash +awslocal sts assume-role \ + --role-arn arn:aws:iam::000000000000:role/localstack-role \ + --role-session-name localstack-session +``` + +```bash title="Output" +{ + "Credentials": { + "AccessKeyId": "ACCESS_KEY_ID", + "SecretAccessKey": "SECRET_ACCESS_KEY", + "SessionToken": "SESSION_TOKEN", + "Expiration": "TIMESTAMP" + }, + ... +} +``` + +Export the returned credentials and use the AWS CLI or your SDK as usual — requests are now signed with the temporary credentials and pass validation: + +```bash +export AWS_ACCESS_KEY_ID=ACCESS_KEY_ID +export AWS_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY +export AWS_SESSION_TOKEN=SESSION_TOKEN + +awslocal s3api list-buckets +``` + +:::note +An access key ID that was not issued by LocalStack through IAM or STS is expected to be paired with the `test` secret access key. +Signing a request with such an access key ID and a different secret access key results in a `SignatureDoesNotMatch` error. + +One exception is a 12-digit account ID used as access key ID for [multi-account namespacing](/aws/customization/advanced/multi-account-setups/), which cannot pass signature validation. +To send signed requests to another account than the default, use the credentials of an IAM user created in that account, or temporary credentials of a role assumed in it. +::: + +Signature validation authenticates a request, but does not authorize it: LocalStack does not check whether the credentials are allowed to perform the operation. +Authorization is handled by [IAM policy enforcement](/aws/developer-tools/security-testing/iam-policy-enforcement/), which can be enabled independently and combined with signature validation for the closest behavior to AWS. + +### Pre-signed URLs + +A pre-signed URL grants time-limited access to an S3 object: anyone with the URL can access the object without providing credentials. +You can generate a pre-signed URL as shown in the [Getting started](#generate-a-pre-signed-url-for-s3-object) section. + +Presigning is a purely client-side operation: the SDK or the CLI computes the pre-signed URL locally with the credentials it is configured with, without contacting LocalStack. +The signature is only checked when the pre-signed URL is used. +For the validation to pass, the URL must therefore be generated with valid [credentials](#credentials). + +By default, LocalStack accepts pre-signed URLs with an invalid signature or an expired date. +Start LocalStack with `S3_SKIP_SIGNATURE_VALIDATION=0` to validate pre-signed URLs like AWS does: + +- The signature must match the request. Both SigV2 and SigV4 pre-signed URLs are supported. +- The URL must not be expired. +- All `x-amz-*` headers sent with the request must be signed in the URL. + +Requests that fail validation are rejected with a `403` error, such as `SignatureDoesNotMatch` for an invalid signature, or `AccessDenied` for an expired URL. + +### SigV4 validation + +By default, LocalStack accepts regular S3 requests signed with any credentials. +Start LocalStack with `S3_VALIDATE_SIGNATURES=1` to validate [SigV4-signed requests](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) like AWS does. +LocalStack validates the signature in the `Authorization` header, as well as the integrity of the payload declared in the `x-amz-content-sha256` header, including streamed `aws-chunked` uploads. + +If your SDK or CLI is configured with valid [credentials](#credentials), validation is fully transparent and does not require any change. +Requests that fail validation are rejected with the same errors as AWS, such as `SignatureDoesNotMatch` for a signature computed with the wrong secret access key, or `XAmzContentSHA256Mismatch` for a payload that does not match its declared checksum. + +:::note +`S3_VALIDATE_SIGNATURES` only applies to SigV4-signed requests. +Anonymous requests, such as requests to public buckets or static S3 websites, and CORS preflight requests are not affected. +Pre-signed URL validation is exclusively controlled by `S3_SKIP_SIGNATURE_VALIDATION`. +::: + ## Configuring Cross-Origin Resource Sharing on S3 You can configure Cross-Origin Resource Sharing (CORS) on a LocalStack S3 bucket using AWS Command Line Interface (CLI).