123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /**
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0.
- */
- #include <cassert>
- #include <aws/core/Region.h>
- #include <aws/core/utils/DNS.h>
- #include <aws/core/utils/Outcome.h>
- #include <aws/core/utils/StringUtils.h>
- #include <aws/s3/S3ARN.h>
- namespace Aws
- {
- namespace S3
- {
- S3ARN::S3ARN(const Aws::String& arn) : Utils::ARN(arn)
- {
- ParseARNResource();
- }
- S3ARNOutcome S3ARN::Validate(const char* clientRegion) const
- {
- // Take pseudo region into consideration here.
- Aws::String region = clientRegion ? clientRegion : "";
- Aws::StringStream ss;
- if (this->GetResourceType() == ARNResourceType::OUTPOST && region.find("fips") != Aws::String::npos)
- {
- ss.str("");
- ss << "Outposts ARN do not support fips regions right now.";
- return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", ss.str(), false));
- }
- else if (this->GetRegion() != Aws::Region::ComputeSignerRegion(clientRegion))
- {
- ss.str("");
- ss << "Region mismatch between \"" << this->GetRegion() << "\" defined in ARN and \""
- << clientRegion << "\" defined in client configuration. "
- << "You can specify AWS_S3_USE_ARN_REGION to ignore region defined in client configuration.";
- return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", ss.str(), false));
- }
- else
- {
- return Validate();
- }
- }
- S3ARNOutcome S3ARN::Validate() const
- {
- Aws::String errorMessage;
- bool success = false;
- Aws::StringStream ss;
- if (!*this)
- {
- errorMessage = "Invalid ARN.";
- }
- // Validation on partition.
- else if (this->GetPartition().find("aws") != 0)
- {
- ss.str("");
- ss << "Invalid partition in ARN: " << this->GetPartition() << ". Valid options: aws, aws-cn, and etc.";
- }
- // Validation on service.
- else if (this->GetService() != ARNService::S3 && this->GetService() != ARNService::S3_OUTPOSTS && this->GetService() != ARNService::S3_OBJECT_LAMBDA)
- {
- ss.str("");
- ss << "Invalid service in ARN: " << this->GetService() << ". Valid options: " << ARNService::S3 << ", " << ARNService::S3_OUTPOSTS << ", " << ARNService::S3_OBJECT_LAMBDA << ".";
- errorMessage = ss.str();
- }
- // Validation on region.
- // TODO: Failure on different partitions.
- else if (this->GetRegion().empty())
- {
- errorMessage = "Invalid ARN with empty region.";
- }
- else if (!Utils::IsValidDnsLabel(this->GetRegion()))
- {
- ss.str("");
- ss << "Invalid region in ARN: " << this->GetRegion() << ". Region should be a RFC 3986 Host label.";
- errorMessage = ss.str();
- }
- // Validation on account ID
- else if (!Utils::IsValidDnsLabel(this->GetAccountId()))
- {
- ss.str("");
- ss << "Invalid account ID in ARN: " << this->GetAccountId() << ". Account ID should be a RFC 3986 Host label.";
- errorMessage = ss.str();
- }
- // Validation on Access Point ARN and Object Lambda Access Point ARN:
- else if (this->GetResourceType() == ARNResourceType::ACCESSPOINT)
- {
- if (!Utils::IsValidDnsLabel(this->GetResourceId()))
- {
- ss.str("");
- ss << "Invalid resource ID in accesspoint ARN: " << this->GetResourceId() << ". Resource ID should be a RFC 3986 Host label.";
- errorMessage = ss.str();
- }
- else if (!this->GetResourceQualifier().empty())
- {
- ss.str("");
- ss << "Invalid accesspoint ARN with non empty resource qualifier: " << this->GetResourceQualifier();
- errorMessage = ss.str();
- }
- else if (!this->GetSubResourceType().empty() || !this->GetSubResourceId().empty())
- {
- ss.str("");
- ss << "Invalid accesspoint ARN with non empty sub resource type: " << this->GetSubResourceType() << ", sub resource ID: " << this->GetSubResourceId();
- errorMessage = ss.str();
- }
- else
- {
- success = true;
- }
- }
- // Validation on Outposts ARN:
- else if (this->GetResourceType() == ARNResourceType::OUTPOST)
- {
- if (this->GetRegion().find("fips") != Aws::String::npos)
- {
- ss.str("");
- ss << "Outposts ARN do not support fips regions right now.";
- errorMessage = ss.str();
- }
- else if (!Utils::IsValidDnsLabel(this->GetResourceId()))
- {
- ss.str("");
- ss << "Invalid outpost ID in Outposts ARN: " << this->GetResourceId() << ". Outpost ID should be a RFC 3986 Host label.";
- errorMessage = ss.str();
- }
- else if (this->GetSubResourceType() != ARNResourceType::ACCESSPOINT)
- {
- ss.str("");
- ss << "Invalid sub resource type in Outposts ARN: " << this->GetSubResourceType() << ". Valid options: " << ARNResourceType::ACCESSPOINT;
- errorMessage = ss.str();
- }
- else if (!Utils::IsValidDnsLabel(this->GetSubResourceId()))
- {
- ss.str("");
- ss << "Invalid accesspoint name in Outposts ARN: " << this->GetSubResourceId() << ", accesspoint name should be a RFC 3986 Host label.";
- errorMessage = ss.str();
- }
- else
- {
- success = true;
- }
- }
- // ARN with unknown resource type.
- else
- {
- ss.str("");
- ss << "Invalid resource type in ARN: " << this->GetResourceType() << ". Valid options: " << ARNResourceType::ACCESSPOINT << ", " << ARNResourceType::OUTPOST << ".";
- errorMessage = ss.str();
- }
- if (success)
- {
- return S3ARNOutcome(success);
- }
- else
- {
- return S3ARNOutcome(Aws::Client::AWSError<S3Errors>(S3Errors::VALIDATION, "VALIDATION", errorMessage, false));
- }
- }
- void S3ARN::ParseARNResource()
- {
- if (!*this) return;
- Aws::String resource = this->GetResource();
- Aws::Vector<Aws::String> resourceSegments;
- if (resource.find(':') != std::string::npos)
- {
- resourceSegments = Utils::StringUtils::Split(resource, ':', 4, Utils::StringUtils::SplitOptions::INCLUDE_EMPTY_ENTRIES);
- }
- else if (resource.find('/') != std::string::npos)
- {
- resourceSegments = Utils::StringUtils::Split(resource, '/', 4, Utils::StringUtils::SplitOptions::INCLUDE_EMPTY_ENTRIES);
- }
- else
- {
- resourceSegments.emplace_back(resource);
- }
- switch (resourceSegments.size())
- {
- case 1:
- m_resourceId = resourceSegments[0];
- break;
- case 2:
- m_resourceType = resourceSegments[0];
- m_resourceId = resourceSegments[1];
- break;
- case 3:
- m_resourceType = resourceSegments[0];
- m_resourceId = resourceSegments[1];
- m_resourceQualifier = resourceSegments[2];
- break;
- case 4:
- m_resourceType = resourceSegments[0];
- m_resourceId = resourceSegments[1];
- m_subResourceType = resourceSegments[2];
- m_subResourceId = resourceSegments[3];
- break;
- default:
- assert(false);
- break;
- }
- }
- }
- }
|