/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using Amazon.Runtime; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Amazon.S3Control.Internal { /// /// A resource in an S3 Outpost /// public class S3OutpostResource : IS3Resource { private Arn _arn; /// /// Create a new S3OutpostResource object /// /// An ARN for the S3 Outpost resource public S3OutpostResource(Arn arn) { _arn = arn; } /// /// Type of the S3 Resource. /// public S3ResourceType Type { get; set; } private string _name; /// /// Name of the access point or bucket /// public string Name { get { return this._name; } set { var accessPointOrBucketString = GetTypeString(true, true); if (string.IsNullOrEmpty(value)) { throw new AmazonClientException($"{accessPointOrBucketString} can not be null"); } var invalidCharacter = value.FirstOrDefault(x => !char.IsLetterOrDigit(x) && x != '-'); if (!invalidCharacter.Equals(default)) { throw new AmazonClientException($"Invalid ARN, {accessPointOrBucketString} Name contains invalid character, {invalidCharacter}"); } this._name = value; } } /// /// Key for object in bucket /// public string Key { get; set; } private string _outpostId; /// /// ID of the S3 Outpost /// public string OutpostId { get { return this._outpostId; } set { if (!S3ArnUtils.IsValidOutpostId(value)) { throw new AmazonClientException($"Invalid outpost ID: {value}. ID must contain only alphanumeric characters and dashes"); } this._outpostId = value; } } /// /// The full name of the S3 Outpost Resource (without the key) /// public string FullResourceName => $"arn:{_arn.Partition}:{_arn.Service}:{_arn.Region}:" + $"{_arn.AccountId}:outpost:{OutpostId}:" + $"{GetTypeString(false, false)}:{Name}"; /// /// Validate the outpost ARN /// /// A client config to validate with /// The region to use for cross region checks public void ValidateArnWithClientConfig(IClientConfig config, RegionEndpoint region) { var s3Config = config as AmazonS3ControlConfig; var accessPointOrBucketString = GetTypeString(false, true); var capitalizedAccessPointOrBucketString = GetTypeString(true, true); if (!_arn.Service.Equals(S3ArnUtils.S3OutpostsService)) { throw new AmazonClientException("Invalid ARN, not S3 Outposts ARN"); } if (s3Config.UseDualstackEndpoint) { throw new AmazonClientException($"Invalid configuration Outpost {capitalizedAccessPointOrBucketString}s do not support dualstack"); } if (string.IsNullOrEmpty(_arn.AccountId)) { throw new AmazonClientException($"Account ID is missing in {capitalizedAccessPointOrBucketString} ARN"); } if (string.IsNullOrEmpty(_arn.Region)) { throw new AmazonClientException($"AWS region is missing in {capitalizedAccessPointOrBucketString} ARN"); } if (s3Config.RegionEndpoint != null && !string.Equals(region.PartitionName, _arn.Partition)) { throw new AmazonClientException($"Invalid configuration, cross partition Outpost {capitalizedAccessPointOrBucketString} ARN"); } if (!s3Config.UseArnRegion && !string.Equals(_arn.Region, region.SystemName, StringComparison.Ordinal) && !string.Equals($"{_arn.Region}-fips", region.SystemName, StringComparison.Ordinal)) { throw new AmazonClientException($"Invalid configuration, cross region Outpost {capitalizedAccessPointOrBucketString} ARN"); } } /// /// Get the endpoint for the outpost request /// /// the client config from the customer /// public Uri GetEndpoint(IClientConfig config) { var s3Config = config as AmazonS3ControlConfig; var region = s3Config.UseArnRegion ? _arn.Region : config.RegionEndpoint?.SystemName; var scheme = config.UseHttp ? "http" : "https"; var fips = config.UseFIPSEndpoint ? "-fips" : ""; UriBuilder ub = new UriBuilder($"{scheme}://s3-outposts{fips}.{region}.{config.RegionEndpoint?.PartitionDnsSuffix}"); return ub.Uri; } internal string GetTypeString(bool inCaps, bool hasSpaces) { switch(Type) { case S3ResourceType.AccessPoint: if (hasSpaces) { return inCaps ? "Access Point" : "access point"; } else { return inCaps ? "AccessPoint" : "accesspoint"; } case S3ResourceType.Bucket: return inCaps ? "Bucket" : "bucket"; default: return ""; } } } }