Skip to content

Commit 89c38e1

Browse files
wps132230Pushen Wang
authored andcommitted
S3 ARN support for FIPS and global regions.
1 parent b85cce2 commit 89c38e1

File tree

11 files changed

+469
-176
lines changed

11 files changed

+469
-176
lines changed

aws-cpp-sdk-core/include/aws/core/Region.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ namespace Aws
4747

4848
// If a pseudo region, for example, aws-global or us-east-1-fips is provided, it should be converted to the region name used for signing.
4949
Aws::String AWS_CORE_API ComputeSignerRegion(const Aws::String& region);
50+
51+
// A FIPs region starts with "fips-" or ends with "-fips".
52+
bool AWS_CORE_API IsFipsRegion(const Aws::String& region);
5053
}
5154

5255
} // namespace Aws

aws-cpp-sdk-core/source/Region.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,18 @@ namespace Aws
3636
return region;
3737
}
3838
}
39+
40+
bool IsFipsRegion(const Aws::String& region)
41+
{
42+
if (region.size() >= 5 && region.compare(0, 5, "fips-") == 0)
43+
{
44+
return true;
45+
}
46+
else if (region.size() >= 5 && region.compare(region.size() - 5, 5, "-fips") == 0)
47+
{
48+
return true;
49+
}
50+
return false;
51+
}
3952
}
4053
}

aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp

Lines changed: 132 additions & 23 deletions
Large diffs are not rendered by default.

aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp

Lines changed: 265 additions & 59 deletions
Large diffs are not rendered by default.

aws-cpp-sdk-s3/source/S3ARN.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,23 @@ namespace Aws
2424
// Take pseudo region into consideration here.
2525
Aws::String region = clientRegion ? clientRegion : "";
2626
Aws::StringStream ss;
27-
if (this->GetResourceType() == ARNResourceType::OUTPOST && region.find("fips") != Aws::String::npos)
27+
if (this->GetResourceType() == ARNResourceType::OUTPOST && Aws::Region::IsFipsRegion(region))
2828
{
2929
ss.str("");
3030
ss << "Outposts ARN do not support fips regions right now.";
3131
return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", ss.str(), false));
3232
}
33-
else if (this->GetRegion() != Aws::Region::ComputeSignerRegion(clientRegion))
33+
else if (region == Aws::Region::AWS_GLOBAL || region == "s3-external-1")
34+
{
35+
ss.str("");
36+
ss << "Region: \"" << region << "\" is not a regional endpoint.";
37+
return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", ss.str(), false));
38+
}
39+
else if (this->GetRegion() != Aws::Region::ComputeSignerRegion(region))
3440
{
3541
ss.str("");
3642
ss << "Region mismatch between \"" << this->GetRegion() << "\" defined in ARN and \""
37-
<< clientRegion << "\" defined in client configuration. "
43+
<< region << "\" defined in client configuration. "
3844
<< "You can specify AWS_S3_USE_ARN_REGION to ignore region defined in client configuration.";
3945
return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", ss.str(), false));
4046
}
@@ -115,7 +121,7 @@ namespace Aws
115121
// Validation on Outposts ARN:
116122
else if (this->GetResourceType() == ARNResourceType::OUTPOST)
117123
{
118-
if (this->GetRegion().find("fips") != Aws::String::npos)
124+
if (Aws::Region::IsFipsRegion(this->GetRegion()))
119125
{
120126
ss.str("");
121127
ss << "Outposts ARN do not support fips regions right now.";

aws-cpp-sdk-s3/source/S3Client.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4089,7 +4089,8 @@ ComputeEndpointOutcome S3Client::ComputeEndpointString(const Aws::String& bucket
40894089
"Path style addressing is not compatible with Access Point ARN or Outposts ARN in Bucket field, please consider using virtual addressing for this client instead.", false));
40904090
}
40914091

4092-
S3ARNOutcome s3ArnOutcome = m_useArnRegion ? arn.Validate() : arn.Validate(m_region.c_str());
4092+
bool useClientRegion = !m_useArnRegion || Aws::Region::IsFipsRegion(m_region);
4093+
S3ARNOutcome s3ArnOutcome = useClientRegion ? arn.Validate(m_region.c_str()) : arn.Validate();
40934094
if (!s3ArnOutcome.IsSuccess())
40944095
{
40954096
return ComputeEndpointOutcome(s3ArnOutcome.GetError());
@@ -4102,12 +4103,12 @@ ComputeEndpointOutcome S3Client::ComputeEndpointString(const Aws::String& bucket
41024103
return ComputeEndpointOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION",
41034104
"S3 Object Lambda Access Point ARNs do not support dualstack right now.", false));
41044105
}
4105-
ss << S3Endpoint::ForObjectLambdaAccessPointArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
4106+
ss << S3Endpoint::ForObjectLambdaAccessPointArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
41064107
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, ARNService::S3_OBJECT_LAMBDA));
41074108
}
41084109
else if (arn.GetResourceType() == ARNResourceType::ACCESSPOINT)
41094110
{
4110-
ss << S3Endpoint::ForAccessPointArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
4111+
ss << S3Endpoint::ForAccessPointArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
41114112
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, SERVICE_NAME));
41124113
}
41134114
else if (arn.GetResourceType() == ARNResourceType::OUTPOST)
@@ -4117,7 +4118,7 @@ ComputeEndpointOutcome S3Client::ComputeEndpointString(const Aws::String& bucket
41174118
return ComputeEndpointOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION",
41184119
"Outposts Access Points do not support dualstack right now.", false));
41194120
}
4120-
ss << S3Endpoint::ForOutpostsArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
4121+
ss << S3Endpoint::ForOutpostsArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
41214122
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, "s3-outposts"));
41224123
}
41234124
}

aws-cpp-sdk-s3/source/S3Endpoint.cpp

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ namespace S3Endpoint
3939
}
4040

4141
const Aws::String& region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
42-
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
42+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(region) ? "-fips" : "";
43+
Aws::String dualstackSuffix = useDualStack ? "dualstack." : "";
4344

44-
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << ".s3-accesspoint.";
45-
if (useDualStack)
46-
{
47-
ss << "dualstack.";
48-
}
49-
ss << region << "." << "amazonaws.com";
45+
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << ".s3-accesspoint" << fipsSuffix << "."
46+
<< dualstackSuffix << Aws::Region::ComputeSignerRegion(region) << "." << "amazonaws.com";
5047

48+
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
5149
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
5250
{
5351
ss << ".cn";
@@ -60,6 +58,7 @@ namespace S3Endpoint
6058
{
6159
AWS_UNREFERENCED_PARAM(useDualStack);
6260
assert(!useDualStack);
61+
assert(!Aws::Region::IsFipsRegion(regionNameOverride));
6362
Aws::StringStream ss;
6463

6564
if (!endpointOverride.empty())
@@ -93,20 +92,11 @@ namespace S3Endpoint
9392
return ss.str();
9493
}
9594

96-
Aws::String region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
97-
Aws::String fipsSuffix = "";
98-
if (region.size() >= 5 && region.compare(0, 5, "fips-") == 0)
99-
{
100-
region = region.substr(5);
101-
fipsSuffix = "-fips";
102-
}
103-
else if (region.size() >= 5 && region.compare(region.size() - 5, 5, "-fips") == 0)
104-
{
105-
region = region.substr(0, region.size() - 5);
106-
fipsSuffix = "-fips";
107-
}
95+
const Aws::String& region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
96+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(region) ? "-fips" : "";
10897

109-
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << "." << ARNService::S3_OBJECT_LAMBDA << fipsSuffix << "." << region << "." << "amazonaws.com";
98+
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << "." << ARNService::S3_OBJECT_LAMBDA << fipsSuffix << "."
99+
<< Aws::Region::ComputeSignerRegion(region) << "." << "amazonaws.com";
110100

111101
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
112102
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
@@ -125,26 +115,10 @@ namespace S3Endpoint
125115
{
126116
assert(!useDualStack);
127117

118+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(regionName) ? "-fips" : "";
128119
Aws::StringStream ss;
129-
ss << serviceName;
120+
ss << serviceName << fipsSuffix << "." << Aws::Region::ComputeSignerRegion(regionName) << ".amazonaws.com";
130121

131-
if (regionName.size() >= 5 && regionName.compare(0, 5, "fips-") == 0)
132-
{
133-
ss << "-fips." << regionName.substr(5);
134-
}
135-
else if (regionName.size() >= 5 && regionName.compare(regionName.size() - 5, 5, "-fips") == 0)
136-
{
137-
ss << "-fips." << regionName.substr(0, regionName.size() - 5);
138-
}
139-
else if (hash == AWS_GLOBAL_HASH || hash == S3_EXTERNAL_1_HASH)
140-
{
141-
ss << "." << Aws::Region::US_EAST_1;
142-
}
143-
else
144-
{
145-
ss << "." << regionName;
146-
}
147-
ss << ".amazonaws.com";
148122
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
149123
{
150124
ss << ".cn";

code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ARNSource.vm

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@ namespace ${rootNamespace}
2727
// Take pseudo region into consideration here.
2828
Aws::String region = clientRegion ? clientRegion : "";
2929
Aws::StringStream ss;
30-
if (this->GetResourceType() == ARNResourceType::OUTPOST && region.find("fips") != Aws::String::npos)
30+
if (this->GetResourceType() == ARNResourceType::OUTPOST && Aws::Region::IsFipsRegion(region))
3131
{
3232
ss.str("");
3333
ss << "Outposts ARN do not support fips regions right now.";
3434
return ${validateOutcome}(Aws::Client::AWSError<${serviceError}>(${serviceError}::VALIDATION, "VALIDATION", ss.str(), false));
3535
}
36-
else if (this->GetRegion() != Aws::Region::ComputeSignerRegion(clientRegion))
36+
else if (region == Aws::Region::AWS_GLOBAL || region == "s3-external-1")
37+
{
38+
ss.str("");
39+
ss << "Region: \"" << region << "\" is not a regional endpoint.";
40+
return ${validateOutcome}(Aws::Client::AWSError<${serviceError}>(${serviceError}::VALIDATION, "VALIDATION", ss.str(), false));
41+
}
42+
else if (this->GetRegion() != Aws::Region::ComputeSignerRegion(region))
3743
{
3844
ss.str("");
3945
ss << "Region mismatch between \"" << this->GetRegion() << "\" defined in ARN and \""
40-
<< clientRegion << "\" defined in client configuration. "
46+
<< region << "\" defined in client configuration. "
4147
<< "You can specify AWS_S3_USE_ARN_REGION to ignore region defined in client configuration.";
4248
return ${validateOutcome}(Aws::Client::AWSError<${serviceError}>(${serviceError}::VALIDATION, "VALIDATION", ss.str(), false));
4349
}
@@ -118,7 +124,7 @@ namespace ${rootNamespace}
118124
// Validation on Outposts ARN:
119125
else if (this->GetResourceType() == ARNResourceType::OUTPOST)
120126
{
121-
if (this->GetRegion().find("fips") != Aws::String::npos)
127+
if (Aws::Region::IsFipsRegion(this->GetRegion()))
122128
{
123129
ss.str("");
124130
ss << "Outposts ARN do not support fips regions right now.";

code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3ClientSource.vm

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ ComputeEndpointOutcome ${className}::ComputeEndpointString(const Aws::String& bu
209209
"Path style addressing is not compatible with Access Point ARN or Outposts ARN in Bucket field, please consider using virtual addressing for this client instead.", false));
210210
}
211211

212-
${metadata.classNamePrefix}ARNOutcome s3ArnOutcome = m_useArnRegion ? arn.Validate() : arn.Validate(m_region.c_str());
212+
bool useClientRegion = !m_useArnRegion || Aws::Region::IsFipsRegion(m_region);
213+
${metadata.classNamePrefix}ARNOutcome s3ArnOutcome = useClientRegion ? arn.Validate(m_region.c_str()) : arn.Validate();
213214
if (!s3ArnOutcome.IsSuccess())
214215
{
215216
return ComputeEndpointOutcome(s3ArnOutcome.GetError());
@@ -222,12 +223,12 @@ ComputeEndpointOutcome ${className}::ComputeEndpointString(const Aws::String& bu
222223
return ComputeEndpointOutcome(Aws::Client::AWSError<${metadata.classNamePrefix}Errors>(${metadata.classNamePrefix}Errors::VALIDATION, "VALIDATION",
223224
"S3 Object Lambda Access Point ARNs do not support dualstack right now.", false));
224225
}
225-
ss << ${metadata.classNamePrefix}Endpoint::ForObjectLambdaAccessPointArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
226+
ss << ${metadata.classNamePrefix}Endpoint::ForObjectLambdaAccessPointArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
226227
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, ARNService::S3_OBJECT_LAMBDA));
227228
}
228229
else if (arn.GetResourceType() == ARNResourceType::ACCESSPOINT)
229230
{
230-
ss << ${metadata.classNamePrefix}Endpoint::ForAccessPointArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
231+
ss << ${metadata.classNamePrefix}Endpoint::ForAccessPointArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
231232
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, SERVICE_NAME));
232233
}
233234
else if (arn.GetResourceType() == ARNResourceType::OUTPOST)
@@ -237,7 +238,7 @@ ComputeEndpointOutcome ${className}::ComputeEndpointString(const Aws::String& bu
237238
return ComputeEndpointOutcome(Aws::Client::AWSError<${metadata.classNamePrefix}Errors>(${metadata.classNamePrefix}Errors::VALIDATION, "VALIDATION",
238239
"Outposts Access Points do not support dualstack right now.", false));
239240
}
240-
ss << ${metadata.classNamePrefix}Endpoint::ForOutpostsArn(arn, m_useArnRegion ? "" : m_region, m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
241+
ss << ${metadata.classNamePrefix}Endpoint::ForOutpostsArn(arn, useClientRegion ? m_region : "", m_useDualStack, m_useCustomEndpoint ? m_baseUri : "");
241242
return ComputeEndpointOutcome(ComputeEndpointResult(ss.str(), signerRegion, "s3-outposts"));
242243
}
243244
}

code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/s3/S3EndpointEnumSource.vm

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,13 @@ namespace ${metadata.classNamePrefix}Endpoint
4040
}
4141

4242
const Aws::String& region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
43-
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
43+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(region) ? "-fips" : "";
44+
Aws::String dualstackSuffix = useDualStack ? "dualstack." : "";
4445

45-
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << ".s3-accesspoint.";
46-
if (useDualStack)
47-
{
48-
ss << "dualstack.";
49-
}
50-
ss << region << "." << "amazonaws.com";
46+
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << ".s3-accesspoint" << fipsSuffix << "."
47+
<< dualstackSuffix << Aws::Region::ComputeSignerRegion(region) << "." << "amazonaws.com";
5148

49+
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
5250
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
5351
{
5452
ss << ".cn";
@@ -61,6 +59,7 @@ namespace ${metadata.classNamePrefix}Endpoint
6159
{
6260
AWS_UNREFERENCED_PARAM(useDualStack);
6361
assert(!useDualStack);
62+
assert(!Aws::Region::IsFipsRegion(regionNameOverride));
6463
Aws::StringStream ss;
6564

6665
if (!endpointOverride.empty())
@@ -94,20 +93,11 @@ namespace ${metadata.classNamePrefix}Endpoint
9493
return ss.str();
9594
}
9695

97-
Aws::String region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
98-
Aws::String fipsSuffix = "";
99-
if (region.size() >= 5 && region.compare(0, 5, "fips-") == 0)
100-
{
101-
region = region.substr(5);
102-
fipsSuffix = "-fips";
103-
}
104-
else if (region.size() >= 5 && region.compare(region.size() - 5, 5, "-fips") == 0)
105-
{
106-
region = region.substr(0, region.size() - 5);
107-
fipsSuffix = "-fips";
108-
}
96+
const Aws::String& region = regionNameOverride.empty() ? arn.GetRegion() : regionNameOverride;
97+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(region) ? "-fips" : "";
10998

110-
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << "." << ARNService::S3_OBJECT_LAMBDA << fipsSuffix << "." << region << "." << "amazonaws.com";
99+
ss << arn.GetResourceId() << "-" << arn.GetAccountId() << "." << ARNService::S3_OBJECT_LAMBDA << fipsSuffix << "."
100+
<< Aws::Region::ComputeSignerRegion(region) << "." << "amazonaws.com";
111101

112102
auto hash = Aws::Utils::HashingUtils::HashString(region.c_str());
113103
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
@@ -126,26 +116,10 @@ namespace ${metadata.classNamePrefix}Endpoint
126116
{
127117
assert(!useDualStack);
128118

119+
Aws::String fipsSuffix = Aws::Region::IsFipsRegion(regionName) ? "-fips" : "";
129120
Aws::StringStream ss;
130-
ss << serviceName;
121+
ss << serviceName << fipsSuffix << "." << Aws::Region::ComputeSignerRegion(regionName) << ".amazonaws.com";
131122

132-
if (regionName.size() >= 5 && regionName.compare(0, 5, "fips-") == 0)
133-
{
134-
ss << "-fips." << regionName.substr(5);
135-
}
136-
else if (regionName.size() >= 5 && regionName.compare(regionName.size() - 5, 5, "-fips") == 0)
137-
{
138-
ss << "-fips." << regionName.substr(0, regionName.size() - 5);
139-
}
140-
else if (hash == AWS_GLOBAL_HASH || hash == S3_EXTERNAL_1_HASH)
141-
{
142-
ss << "." << Aws::Region::US_EAST_1;
143-
}
144-
else
145-
{
146-
ss << "." << regionName;
147-
}
148-
ss << ".amazonaws.com";
149123
if (hash == CN_NORTH_1_HASH || hash == CN_NORTHWEST_1_HASH)
150124
{
151125
ss << ".cn";

0 commit comments

Comments
 (0)