Skip to content

Commit

Permalink
fix(sts): do not inject region info for STS service with VPC endpoint…
Browse files Browse the repository at this point in the history
… hostname (#113)

AWS services can be used inside a private VPC without Internet access by creating private links(VPC endpoints). When creating VPC endpoint for an AWS service, the Enable private DNS name is enabled by default, which means that a private DNS record will be created whose value is just the same as the AWS service's public endpoint(for example, s3.amazonaws.com) but pointing at the private VPC endpoint. This is what is expected to be a common practice when using VPC endpoint to access AWS service.

However, user can also disable it to not create this "fake" DNS record, and use the VPC endpoint hostname directly(something like vpce-abcdefghijklmn-abcdefg.sts.us-east-1.vpce.amazonaws.com). In this case, there is no need to inject region info into the endpoint domain since the hostname itself always contains the region for this VPC endpoint.

We've encountered a case in which the user is using a VPC endpoint hostname directly for STS service and region info gets injected unexpectedly, thus STS service cannot be used. This PR fixes it.

More information: https://docs.aws.amazon.com/vpc/latest/privatelink/privatelink-access-aws-services.html#interface-endpoint-dns-hostnames

FTI-5934
  • Loading branch information
windmgc authored May 17, 2024
1 parent 722045b commit a708af6
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ Release process:
- feat: decode AWS api response json body with array metatable
[114](https://github.com/Kong/lua-resty-aws/pull/114)

- fix: do not inject region info for sts service with VPC endpoint hostname
[113](https://github.com/Kong/lua-resty-aws/pull/113)

### 1.4.1 (19-Apr-2024)

Expand Down
33 changes: 33 additions & 0 deletions spec/01-generic/02-aws_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,37 @@ describe("AWS main instance", function()
assert.same("https://sts.eu-central-1.amazonaws.com", sts.config.endpoint)
end)

it("do not inject sts region info for sts vpc endpoint url", function()
local aws = AWS({
region = "eu-central-1",
stsRegionalEndpoints = "regional",
})

aws.config.credentials = aws:Credentials {
accessKeyId = "test_id",
secretAccessKey = "test_key",
}

assert.is.table(aws.config)

local regional_vpc_endpoint_url = "https://vpce-abcdefg-hijklmn-eu-central-1a.sts.eu-central-1.vpce.amazonaws.com"

local sts, _ = aws:STS({
endpoint = regional_vpc_endpoint_url,
})
local _, _ = sts:assumeRole {
RoleArn = "aws:arn::XXXXXXXXXXXXXXXXX:test123",
RoleSessionName = "aws-test",
}

assert.same(regional_vpc_endpoint_url, sts.config.endpoint)

local _, _ = sts:assumeRole {
RoleArn = "aws:arn::XXXXXXXXXXXXXXXXX:test123",
RoleSessionName = "aws-test",
}
assert.same(regional_vpc_endpoint_url, sts.config.endpoint)
end)


end)
9 changes: 7 additions & 2 deletions src/resty/aws/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ local execute_request = require("resty.aws.request.execute")
local split = require("pl.utils").split
local tablex = require("pl.tablex")

local AWS_PUBLIC_DOMAIN_PATTERN = "^(.+)(%.amazonaws%.com)$"
local AWS_VPC_ENDPOINT_DOMAIN_PATTERN = "^(.+)(%.vpce%.amazonaws%.com)$"


-- case-insensitive lookup help.
Expand Down Expand Up @@ -323,8 +325,11 @@ local function generate_service_methods(service)
-- https://github.com/aws/aws-sdk-js/blob/307e82673b48577fce4389e4ce03f95064e8fe0d/lib/services/sts.js#L78-L82
assert(service.config.region, "region is required when using STS regional endpoints")

if not service.config._regionalEndpointInjected then
local pre, post = service.config.endpoint:match("^(.+)(%.amazonaws%.com)$")
-- If the endpoint is a VPC endpoint DNS hostname then we don't need to inject the region
-- VPC endpoint DNS hostnames always contain region, see
-- https://docs.aws.amazon.com/vpc/latest/privatelink/privatelink-access-aws-services.html#interface-endpoint-dns-hostnames
if not service.config._regionalEndpointInjected and not service.config.endpoint:match(AWS_VPC_ENDPOINT_DOMAIN_PATTERN) then
local pre, post = service.config.endpoint:match(AWS_PUBLIC_DOMAIN_PATTERN)
service.config.endpoint = pre .. "." .. service.config.region .. post
service.config.signingRegion = service.config.region
service.config._regionalEndpointInjected = true
Expand Down

0 comments on commit a708af6

Please sign in to comment.