using Amazon.Runtime;
using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Amazon.S3
{
///
/// Extensions methods added to Amazon.Arn type to help parse S3 specific resources from the ARN.
///
public static class ArnExtensions
{
internal const string ResourceTypeAccessPoint = "accesspoint";
internal const string ResourceTypeBucketName = "bucket_name";
internal const string ResourceTypeOutpostAccessPoint = "outpost";
///
/// Attempt to parse the resource component of the ARN into access point resource name.
///
/// An AWS ARN to parse
/// The access point resouce identifier found in the ARN.
/// True if the ARN contains an access point resource identifier.
public static bool TryParseAccessPoint(this Arn arn, out string accessPoint)
{
accessPoint = null;
if (string.IsNullOrEmpty(arn.Resource))
{
return false;
}
if (arn.Resource.StartsWith(ResourceTypeAccessPoint + ":", StringComparison.Ordinal) ||
arn.Resource.StartsWith(ResourceTypeAccessPoint + "/", StringComparison.Ordinal))
{
accessPoint = arn.Resource.Substring(ResourceTypeAccessPoint.Length + 1);
return true;
}
return false;
}
///
/// Attempt to parse the resource component of the ARN into bucket name.
///
/// An AWS ARN to parse
/// The bucket name found in the ARN.
/// True if the ARN contains a bucket name.
public static bool TryParseBucket(this Arn arn, out string bucketName)
{
bucketName = null;
if (string.IsNullOrEmpty(arn.Resource))
{
return false;
}
if (arn.Resource.StartsWith(ResourceTypeBucketName + ":", StringComparison.Ordinal) ||
arn.Resource.StartsWith(ResourceTypeBucketName + "/", StringComparison.Ordinal))
{
bucketName = arn.Resource.Substring(ResourceTypeBucketName.Length + 1);
return true;
}
return false;
}
///
/// Attempt to parse the resource component of the ARN into outpost resource with outpost id and access point name.
///
/// An AWS ARN to parse
/// True if the ARN contains an outpost access point resource identifier.
public static bool IsOutpostArn(this Arn arn)
{
if (string.IsNullOrEmpty(arn.Resource))
{
return false;
}
return arn.Resource.StartsWith(ResourceTypeOutpostAccessPoint, StringComparison.Ordinal);
}
///
/// Checks whether an ARN belongs to a particular service
///
/// True if a match is found
public static bool IsService(this Arn arn, string serviceName)
{
return arn.Service.Equals(serviceName, StringComparison.Ordinal);
}
///
/// Determines whether an ARN is for a multi-region access point
///
/// An AWS ARN to parse
/// True if the ARN is for a multi-region access point
public static bool IsMRAPArn(this Arn arn)
{
if (string.IsNullOrEmpty(arn.Resource))
{
return false;
}
// The resource of MRAP ARNs must begin with a resource-type of `accesspoint`
if (!(arn.Resource.StartsWith(ResourceTypeAccessPoint + ":", StringComparison.Ordinal) ||
arn.Resource.StartsWith(ResourceTypeAccessPoint + "/", StringComparison.Ordinal)))
{
return false;
}
return string.IsNullOrEmpty(arn.Region);
}
///
/// Parse an Arn to extract information on S3 outpost access point
/// and if it is not found or properly formatted, throw an exception
///
///
///
public static S3OutpostResource ParseOutpost(this Arn arn)
{
if (string.IsNullOrEmpty(arn.Resource))
{
throw new AmazonClientException("Arn Resource can not be null");
}
if (!IsOutpostArn(arn))
{
throw new AmazonClientException($"Arn Resource: {arn.Resource} does not resemble an outpost access point");
}
var outpostAccessPointString = arn.Resource;
var separators = new char[] { '/', ':' };
var parts = outpostAccessPointString.Split(separators, 5);
if (parts.Length < 4 || !String.Equals(parts[2], "accesspoint"))
{
throw new AmazonClientException($"Invalid ARN: {arn.ToString()}, outpost resource format is incorrect");
}
var outpost = new S3OutpostResource(arn);
outpost.OutpostId = parts[1];
outpost.AccessPointName = parts[3];
if (parts.Length > 4)
{
outpost.Key = parts[4];
}
return new S3OutpostResource(arn)
{
OutpostId = parts[1],
AccessPointName = parts[3],
Key = parts.Length > 4 ? parts[4] : null
};
}
///
/// Check if the ARN has a valid Account ID
///
/// The ARN which is being validated
public static bool HasValidAccountId(this Arn arn)
{
return string.IsNullOrEmpty(arn.AccountId) || (arn.AccountId.Length == 12 && arn.AccountId.ToCharArray().All(x => char.IsDigit(x)));
}
}
}