Skip to content

Commit 941a1b2

Browse files
authored
[v2] support opt-in regional sts endpoint (#2106)
* [v2] support opt-in regional sts endpoint * add changelog
1 parent 15745d8 commit 941a1b2

File tree

10 files changed

+282
-6
lines changed

10 files changed

+282
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
Unreleased Changes
22
------------------
33

4+
* Feature - Aws::Core - Support enable STS regional endpoints by `sts_regional_endpoints: 'regional'`
5+
46
2.11.379 (2019-10-22)
57
------------------
68

aws-sdk-core/lib/aws-sdk-core.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ module Plugins
327327
autoload :S3RequestSigner, 'aws-sdk-core/plugins/s3_request_signer'
328328
autoload :S3SseCpk, 'aws-sdk-core/plugins/s3_sse_cpk'
329329
autoload :S3UrlEncodedKeys, 'aws-sdk-core/plugins/s3_url_encoded_keys'
330+
autoload :STSRegionalEndpoints, 'aws-sdk-core/plugins/sts_regional_endpoints'
330331
autoload :SQSQueueUrls, 'aws-sdk-core/plugins/sqs_queue_urls'
331332
autoload :SQSMd5s, 'aws-sdk-core/plugins/sqs_md5s'
332333
autoload :StubResponses, 'aws-sdk-core/plugins/stub_responses'

aws-sdk-core/lib/aws-sdk-core/api/customizations.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@ def is_eventstream?(api, shape_name)
274274
Aws::Plugins::S3RequestSigner
275275
))
276276

277+
plugins('AWS Security Token Service', add: %w(
278+
Aws::Plugins::STSRegionalEndpoints
279+
))
280+
277281
plugins('AWS S3 Control', add: %w(
278282
Aws::Plugins::S3HostId
279283
Aws::Plugins::S3ControlDns

aws-sdk-core/lib/aws-sdk-core/endpoint_provider.rb

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,34 @@ module Aws
22
# @api private
33
class EndpointProvider
44

5+
# when sts_regional_endpoint set to `legacy`
6+
# endpoint pattern stays global for
7+
# following regions
8+
STS_LEGACY_REGIONS = %w(
9+
ap-northeast-1
10+
ap-south-1
11+
ap-southeast-1
12+
ap-southeast-2
13+
aws-global
14+
ca-central-1
15+
eu-central-1
16+
eu-north-1
17+
eu-west-1
18+
eu-west-2
19+
eu-west-3
20+
sa-east-1
21+
us-east-1
22+
us-east-2
23+
us-west-1
24+
us-west-2
25+
)
26+
527
def initialize(rules)
628
@rules = rules
729
end
830

9-
def resolve(region, service)
10-
"https://" + endpoint_for(region, service)
31+
def resolve(region, service, sts_regional_endpoints = nil)
32+
"https://" + endpoint_for(region, service, sts_regional_endpoints)
1133
end
1234

1335
def signing_region(region, service)
@@ -27,16 +49,21 @@ def dns_suffix_for(region)
2749

2850
private
2951

30-
def endpoint_for(region, service)
52+
def endpoint_for(region, service, sts_regional_endpoints)
3153
partition = get_partition(region)
3254
endpoint = default_endpoint(partition, service, region)
3355
service_cfg = partition.fetch("services", {}).fetch(service, {})
3456

3557
# Check for service-level default endpoint.
3658
endpoint = service_cfg.fetch("defaults", {}).fetch("hostname", endpoint)
3759

60+
# Check for sts legacy behavior
61+
sts_legacy = service == 'sts' &&
62+
sts_regional_endpoints == 'legacy' &&
63+
STS_LEGACY_REGIONS.include?(region)
64+
3865
# Check for global endpoint.
39-
if service_cfg["isRegionalized"] == false
66+
if sts_legacy || service_cfg["isRegionalized"] == false
4067
region = service_cfg.fetch("partitionEndpoint", region)
4168
end
4269

@@ -81,8 +108,8 @@ def default_partition
81108

82109
class << self
83110

84-
def resolve(region, service)
85-
default_provider.resolve(region, service)
111+
def resolve(region, service, sts_regional_endpoints = nil)
112+
default_provider.resolve(region, service, sts_regional_endpoints)
86113
end
87114

88115
def signing_region(region, service)

aws-sdk-core/lib/aws-sdk-core/plugins/regional_endpoint.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class RegionalEndpoint < Seahorse::Client::Plugin
2626
endpoint_prefix = cfg.api.metadata['endpointPrefix']
2727
if cfg.region && endpoint_prefix
2828
EndpointProvider.resolve(cfg.region, endpoint_prefix)
29+
sts_regional = cfg.respond_to?(:sts_regional_endpoints) ? cfg.sts_regional_endpoints : nil
30+
EndpointProvider.resolve(cfg.region, endpoint_prefix, sts_regional)
2931
end
3032
end
3133

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Aws
2+
module Plugins
3+
4+
class STSRegionalEndpoints < Seahorse::Client::Plugin
5+
6+
option(:sts_regional_endpoints,
7+
default: 'legacy',
8+
doc_type: String,
9+
docstring: <<-DOCS) do |cfg|
10+
Passing in 'regional' to enable regional endpoint for STS for all supported
11+
regions (except 'aws-global'), defaults to 'legacy' mode, using global endpoint
12+
for legacy regions.
13+
DOCS
14+
resolve_sts_regional_endpoints(cfg)
15+
end
16+
17+
private
18+
19+
def self.resolve_sts_regional_endpoints(cfg)
20+
env_mode = ENV['AWS_STS_REGIONAL_ENDPOINTS']
21+
env_mode = nil if env_mode == ''
22+
cfg_mode = Aws.shared_config.sts_regional_endpoints(
23+
profile: cfg.profile)
24+
env_mode || cfg_mode || 'legacy'
25+
end
26+
27+
end
28+
29+
end
30+
end

aws-sdk-core/lib/aws-sdk-core/shared_config.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,21 @@ def region(opts = {})
128128
end
129129
end
130130

131+
def sts_regional_endpoints(opts = {})
132+
p = opts[:profile] || @profile_name
133+
if @config_enabled
134+
if @parsed_credentials
135+
mode = @parsed_credentials.fetch(p, {})["sts_regional_endpoints"]
136+
end
137+
if @parsed_config
138+
mode ||= @parsed_config.fetch(p, {})["sts_regional_endpoints"]
139+
end
140+
mode
141+
else
142+
nil
143+
end
144+
end
145+
131146
def endpoint_discovery(opts = {})
132147
p = opts[:profile] || @profile_name
133148
if @config_enabled && @parsed_config

aws-sdk-core/spec/aws/shared_config_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ module Aws
110110
expect(config.endpoint_discovery).to eq("false")
111111
end
112112

113+
context 'sts_regional_endpoints selection' do
114+
115+
it 'can resolve sts_regional_endpoints from config file' do
116+
config = SharedConfig.new(
117+
config_path: mock_config_file,
118+
config_enabled: true,
119+
profile_name: "sts_regional"
120+
)
121+
expect(config.sts_regional_endpoints).to eq('regional')
122+
123+
config = SharedConfig.new(
124+
config_path: mock_config_file,
125+
config_enabled: true,
126+
profile_name: "sts_legacy"
127+
)
128+
expect(config.sts_regional_endpoints).to eq('legacy')
129+
end
130+
131+
end
132+
113133
end
114134
end
115135
end
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
require_relative '../../spec_helper'
2+
3+
module Aws
4+
module STS
5+
describe Client do
6+
7+
describe ':sts_regional_endpoints' do
8+
9+
let(:mock_config_file) {
10+
File.expand_path(File.join(File.dirname(__FILE__),
11+
'..', 'fixtures', 'credentials', 'mock_shared_config'))
12+
}
13+
14+
it 'uses ENV before shared config' do
15+
ENV['AWS_STS_REGIONAL_ENDPOINTS'] = 'regional'
16+
config = SharedConfig.new(
17+
config_path: mock_config_file,
18+
config_enabled: true,
19+
profile_name: "sts_legacy"
20+
)
21+
22+
allow(Aws).to receive(:shared_config).and_return(config)
23+
client = Client.new(
24+
stub_responses: true,
25+
region: 'us-west-2'
26+
)
27+
expect(client.config.sts_regional_endpoints).to eq('regional')
28+
end
29+
30+
it 'defaults to `legacy`' do
31+
client = Client.new(
32+
stub_responses: true,
33+
region: 'us-west-2'
34+
)
35+
expect(client.config.sts_regional_endpoints).to eq('legacy')
36+
resp = client.get_caller_identity
37+
expect(resp.context.http_request.endpoint.to_s).to eq(
38+
'https://sts.amazonaws.com')
39+
end
40+
41+
it 'can be set `regional` in the constructor' do
42+
client = Client.new(
43+
stub_responses: true,
44+
sts_regional_endpoints: 'regional',
45+
region: 'us-west-2'
46+
)
47+
expect(client.config.sts_regional_endpoints).to eq('regional')
48+
resp = client.get_caller_identity
49+
expect(resp.context.http_request.endpoint.to_s).to eq(
50+
'https://sts.us-west-2.amazonaws.com')
51+
end
52+
53+
it 'can be set fron ENV' do
54+
ENV['AWS_STS_REGIONAL_ENDPOINTS'] = 'regional'
55+
client = Client.new(
56+
stub_responses: true,
57+
region: 'us-west-2'
58+
)
59+
expect(client.config.sts_regional_endpoints).to eq('regional')
60+
resp = client.get_caller_identity
61+
expect(resp.context.http_request.endpoint.to_s).to eq(
62+
'https://sts.us-west-2.amazonaws.com')
63+
end
64+
65+
it 'has no effect on fips endpoint' do
66+
client = Client.new(
67+
stub_responses: true,
68+
region: 'us-west-2-fips'
69+
)
70+
expect(client.config.sts_regional_endpoints).to eq('legacy')
71+
resp = client.get_caller_identity
72+
expect(resp.context.http_request.endpoint.to_s).to eq(
73+
'https://sts-fips.us-west-2.amazonaws.com')
74+
75+
client = Client.new(
76+
stub_responses: true,
77+
sts_regional_endpoints: 'regional',
78+
region: 'us-west-2-fips'
79+
)
80+
resp = client.get_caller_identity
81+
expect(resp.context.http_request.endpoint.to_s).to eq(
82+
'https://sts-fips.us-west-2.amazonaws.com')
83+
end
84+
85+
it 'has no effect on aws-global even when `regional`' do
86+
client = Client.new(
87+
stub_responses: true,
88+
sts_regional_endpoints: 'regional',
89+
region: 'aws-global'
90+
)
91+
expect(client.config.sts_regional_endpoints).to eq('regional')
92+
resp = client.get_caller_identity
93+
expect(resp.context.http_request.endpoint.to_s).to eq(
94+
'https://sts.amazonaws.com')
95+
end
96+
97+
it 'has no effect on current regionalized regions' do
98+
client = Client.new(
99+
stub_responses: true,
100+
region: 'ap-east-1'
101+
)
102+
expect(client.config.sts_regional_endpoints).to eq('legacy')
103+
resp = client.get_caller_identity
104+
expect(resp.context.http_request.endpoint.to_s).to eq(
105+
'https://sts.ap-east-1.amazonaws.com')
106+
107+
client = Client.new(
108+
stub_responses: true,
109+
sts_regional_endpoints: 'regional',
110+
region: 'ap-east-1'
111+
)
112+
expect(client.config.sts_regional_endpoints).to eq('regional')
113+
resp = client.get_caller_identity
114+
expect(resp.context.http_request.endpoint.to_s).to eq(
115+
'https://sts.ap-east-1.amazonaws.com')
116+
end
117+
118+
it 'has no effect on cn-north-1 region' do
119+
client = Client.new(
120+
stub_responses: true,
121+
region: 'cn-north-1'
122+
)
123+
expect(client.config.sts_regional_endpoints).to eq('legacy')
124+
resp = client.get_caller_identity
125+
expect(resp.context.http_request.endpoint.to_s).to eq(
126+
'https://sts.cn-north-1.amazonaws.com.cn')
127+
128+
client = Client.new(
129+
stub_responses: true,
130+
sts_regional_endpoints: 'regional',
131+
region: 'cn-north-1'
132+
)
133+
expect(client.config.sts_regional_endpoints).to eq('regional')
134+
resp = client.get_caller_identity
135+
expect(resp.context.http_request.endpoint.to_s).to eq(
136+
'https://sts.cn-north-1.amazonaws.com.cn')
137+
end
138+
139+
it 'configures properly at config' do
140+
client = Client.new(
141+
stub_responses: true,
142+
region: 'us-west-2'
143+
)
144+
expect(client.config.sts_regional_endpoints).to eq('legacy')
145+
expect(client.config.region).to eq('us-west-2')
146+
expect(client.config.sigv4_region).to eq('us-east-1')
147+
expect(client.config.endpoint.to_s).to eq('https://sts.amazonaws.com')
148+
149+
client = Client.new(
150+
stub_responses: true,
151+
sts_regional_endpoints: 'regional',
152+
region: 'us-west-2'
153+
)
154+
expect(client.config.sts_regional_endpoints).to eq('regional')
155+
expect(client.config.region).to eq('us-west-2')
156+
expect(client.config.sigv4_region).to eq('us-west-2')
157+
expect(client.config.endpoint.to_s).to eq(
158+
'https://sts.us-west-2.amazonaws.com')
159+
end
160+
161+
end
162+
163+
end
164+
end
165+
end

aws-sdk-core/spec/fixtures/credentials/mock_shared_config

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,13 @@ endpoint_discovery_enabled = true
7878
aws_access_key_id = AKID
7979
aws_secret_access_key = SECRET
8080
endpoint_discovery_enabled = false
81+
82+
[profile sts_regional]
83+
aws_access_key_id = AKID
84+
aws_secret_access_key = SECRET
85+
sts_regional_endpoints = regional
86+
87+
[profile sts_legacy]
88+
aws_access_key_id = AKID
89+
aws_secret_access_key = SECRET
90+
sts_regional_endpoints = legacy

0 commit comments

Comments
 (0)