aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
3.07k stars 574 forks source link

Override service region through environment variables #6537

Open skeggse opened 5 months ago

skeggse commented 5 months ago

Some workloads operate in a very restricted network context, and need to communicate with AWS APIs. Sometimes, that includes cross-region access. Consider the following scenario:

We can configure one aspect of this behavior to work as desired, namely with AWS_STS_REGIONAL_ENDPOINTS=regional environment variable. This makes us use the regional STS endpoint. However, the default credential provider chain for SDKs still inherits the region from the configured client, meaning that we try to communicate with STS in eu-central-1 if we configure the S3 client to talk to that region.

The Service-specific endpoints feature looked like it would solve this problem: I could force supported SDKs to use only the local endpoint by configuring it through environment variables! This even works for the AssumeRoleWithWebIdentity call itself: since that request isn't signed, it doesn't matter that the STS client is configured to use a different region than the one we're sending the actual assume role request to. However, for STS requests that are signed, and where we're not explicitly passing in an endpoint URL, the signatures end up not matching:

An error occurred (SignatureDoesNotMatch) when calling the GetCallerIdentity operation: Credential should be scoped to a valid region.

So, a request (not sure if feature or bug): provide a way to explicitly override the region used for a specific service, or at least for STS since that's the backbone of practically all other AWS requests. Alternately, if there's an easy way to do this today, I'd love to hear about it (and maybe get it explicitly documented)!

References:

aBurmeseDev commented 1 week ago

Hi @skeggse - apologies for the wait here.

In your scenario, where you need to use the STS service in a different region than the S3 service, you can achieve this by creating separate clients for each service and configuring the appropriate endpoint or region for each client.

Here's an example:

const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { STSClient, AssumeRoleWithWebIdentityCommand } = require('@aws-sdk/client-sts');

// Configure the S3 client with the desired region
const s3Client = new S3Client({ region: 'eu-central-1' });

// Configure the STS client with a custom endpoint URL or region
const stsClient = new STSClient({
  region: 'us-east-1', // Or any other region where you have access to the STS endpoint
  endpoint: 'https://sts.us-east-1.amazonaws.com' // Explicitly set the STS endpoint URL
});

// Use the stsClient to assume the role
const assumeRoleCommand = new AssumeRoleWithWebIdentityCommand({
  // Provide the required parameters for AssumeRoleWithWebIdentity
});

stsClient.send(assumeRoleCommand)
  .then((assumeRoleResponse) => {
    // Use the assumed role credentials with the S3 client
    const s3Credentials = assumeRoleResponse.Credentials;
    const s3Client = new S3Client({
      region: 'eu-central-1',
      credentials: {
        accessKeyId: s3Credentials.AccessKeyId,
        secretAccessKey: s3Credentials.SecretAccessKey,
        sessionToken: s3Credentials.SessionToken,
      },
    });

    // Now you can use the s3Client to perform operations in the eu-central-1 region
    const putObjectCommand = new PutObjectCommand({
      Bucket: 'your-bucket-name',
      Key: 'object-key',
      Body: 'Hello, world!',
    });

    return s3Client.send(putObjectCommand);
  })
  .then((putObjectResponse) => {
    console.log('Object uploaded successfully:', putObjectResponse);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

Hope it helps and let us know if there's any follow-up questions! Best, John

skeggse commented 1 week ago

Aha, thanks for pointing out the unclear component in my question!

The strategy you've outlined works fine if:

Neither of these are true for us.

This is a blocker to certain VPC security controls for multi-region applications.