/// <summary> /// Check if the value of any dictionary item /// is of type ARN. /// <b>Note:</b> this assumes that there is just 0-1 ARN in the path resource dictionary /// </summary> /// <param name="dictValues">The dictionary</param> /// <param name="arn">ARN found in dictionary</param> /// <returns>A boolean whether or not the dictionary contains an ARN in the values</returns> internal static bool DictionaryContainsArn(IDictionary <string, string> dictValues, out Arn arn) { Arn outArn = null; var matchingKvp = dictValues.FirstOrDefault(kvp => Arn.TryParse(kvp.Value, out outArn)); arn = matchingKvp.Value != null ? outArn : null; return(arn != null); }
public TopicConfig(Arn arn) : base(arn) { Topic = arn.ToString(); }
public static void ProcessRequestHandlers(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var config = executionContext.RequestContext.ClientConfig; // If the marshalled request has the SSE header and it is set to KMS, // force SigV4 for this request. // Current operations that may set this header: // CopyObject, CopyPart, InitiateMultipart, PutObject string sseHeaderValue; if (request.Headers.TryGetValue(HeaderKeys.XAmzServerSideEncryptionHeader, out sseHeaderValue) && string.Equals(sseHeaderValue, ServerSideEncryptionMethod.AWSKMS.Value, StringComparison.Ordinal)) { request.SignatureVersion = SignatureVersion.SigV4; } var bucketResourcePathToken = GetBucketName(request.ResourcePath); if (string.IsNullOrEmpty(bucketResourcePathToken)) { return; } var s3Config = config as AmazonS3Config; if (s3Config == null) { throw new AmazonClientException("Current config object is not of type AmazonS3Config"); } //If a ServiceURL is set the config ClientRegion should be null. Under this case //the region needs to be determined from the ServiceURL. var regionEndpoint = config.RegionEndpoint; if (regionEndpoint == null && !string.IsNullOrEmpty(config.ServiceURL)) { var regionName = AWSSDKUtils.DetermineRegion(config.ServiceURL); regionEndpoint = RegionEndpoint.GetBySystemName(regionName); } bool isHttp; bool removeBucketFromResourcePath = false; if (Arn.IsArn(bucketResourcePathToken)) { string accessPoint; UriBuilder ub; Arn s3Arn = Arn.Parse(bucketResourcePathToken); if (s3Arn.IsService("s3") && s3Arn.TryParseAccessPoint(out accessPoint)) { if (s3Arn.IsMRAPArn()) { var partitionDnsSuffix = RegionEndpoint.GetDnsSuffixForPartition(s3Arn.Partition); ValidateMRAPAccessPoint(s3Arn, s3Config, accessPoint, partitionDnsSuffix); request.SignatureVersion = SignatureVersion.SigV4a; request.AuthenticationRegion = "*"; isHttp = config.UseHttp; var scheme = isHttp ? "http" : "https"; ub = new UriBuilder($"{scheme}://{accessPoint}.accesspoint.s3-global.{partitionDnsSuffix}"); } else // Non-MRAP access point { ValidateS3AccessPoint(s3Arn, s3Config, regionEndpoint); if (!string.IsNullOrEmpty(config.ServiceURL)) { ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); ub.Host = string.Concat($"{accessPoint}-{s3Arn.AccountId}.", ub.Host); } else { isHttp = config.UseHttp; var scheme = isHttp ? "http" : "https"; var fipsSuffix = regionEndpoint?.SystemName?.ToLower().Contains("fips") == true ? "-fips" : ""; ub = new UriBuilder($"{scheme}://{accessPoint}-{s3Arn.AccountId}.s3-accesspoint{fipsSuffix}{(config.UseDualstackEndpoint ? ".dualstack" : "")}.{s3Arn.Region}.{config.RegionEndpoint.PartitionDnsSuffix}"); } } request.Endpoint = ub.Uri; } else if (s3Arn.IsService(s3ObjectLambdaServiceName) && s3Arn.TryParseAccessPoint(out accessPoint)) { ValidateS3ObjectLambdaAccessPoint(s3Arn, s3Config, regionEndpoint); if (!string.IsNullOrEmpty(config.ServiceURL)) { ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); ub.Host = string.Concat($"{accessPoint}-{s3Arn.AccountId}.", ub.Host); } else { isHttp = s3Config.UseHttp; var scheme = isHttp ? "http" : "https"; var fipsSuffix = regionEndpoint?.SystemName?.ToLower().Contains("fips") == true ? "-fips" : ""; ub = new UriBuilder($"{scheme}://{accessPoint}-{s3Arn.AccountId}.{s3ObjectLambdaServiceName}{fipsSuffix}.{s3Arn.Region}.{config.RegionEndpoint.PartitionDnsSuffix}"); } request.Endpoint = ub.Uri; } else if (s3Arn.IsOutpostArn()) { var outpost = s3Arn.ParseOutpost(); ValidateOutpostAccessPoint(s3Arn, s3Config, regionEndpoint); var region = s3Config.UseArnRegion ? s3Arn.Region : regionEndpoint.SystemName; bucketResourcePathToken = outpost.FullAccessPointName; if (!string.IsNullOrEmpty(config.ServiceURL)) { ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); ub.Host = string.Concat($"{outpost.AccessPointName}-{s3Arn.AccountId}.{outpost.OutpostId}.", ub.Host); } else { isHttp = config.UseHttp; var scheme = isHttp ? "http" : "https"; ub = new UriBuilder($"{scheme}://{outpost.AccessPointName}-{s3Arn.AccountId}.{outpost.OutpostId}.s3-outposts.{region}.{config.RegionEndpoint.PartitionDnsSuffix}"); } request.Endpoint = ub.Uri; } else { throw new AmazonClientException("Invalid ARN specified for bucket name. Only access point ARNs are allowed for the value of bucket name."); } request.OverrideSigningServiceName = s3Arn.Service; // The access point arn can be using a region different from the configured region for the service client. // If so be sure to set the authentication region so the signer will use the correct region. if (!s3Arn.IsMRAPArn()) // Except for MRAP where signing region and ARN region diverge { request.AuthenticationRegion = s3Arn.Region; request.SignatureVersion = SignatureVersion.SigV4; } removeBucketFromResourcePath = true; } else // not an arn { // If path style is not forced and the bucket name is DNS // compatible modify the endpoint to use virtual host style // addressing var bucketIsDnsCompatible = IsDnsCompatibleBucketName(bucketResourcePathToken); var ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); if (!s3Config.ForcePathStyle && bucketIsDnsCompatible) { // If using HTTPS, bucketName cannot contain a period if (isHttp || bucketResourcePathToken.IndexOf('.') < 0) { // Add bucket to host ub.Host = string.Concat(bucketResourcePathToken, ".", ub.Host); request.Endpoint = ub.Uri; removeBucketFromResourcePath = true; } } if (request.OriginalRequest.GetType() == typeof(WriteGetObjectResponseRequest)) { if (!string.IsNullOrEmpty(config.ServiceURL)) { ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); } else { isHttp = s3Config.UseHttp; var scheme = isHttp ? "http" : "https"; var region = regionEndpoint.SystemName == "us-east-1-regional" ? "us-east-1" : regionEndpoint.SystemName; ub = new UriBuilder($"{scheme}://{request.Headers["x-amz-request-route"]}.{s3ObjectLambdaServiceName}.{region}.{config.RegionEndpoint.PartitionDnsSuffix}"); } request.Endpoint = ub.Uri; request.OverrideSigningServiceName = s3ObjectLambdaServiceName; request.SignatureVersion = SignatureVersion.SigV4; } if (s3Config.UseAccelerateEndpoint) { // Validate if bucket name is accelerate compatible and enable acceleration by using // Accelerate endpoint for this request if (!bucketIsDnsCompatible || BucketNameContainsPeriod(bucketResourcePathToken)) { throw new AmazonClientException( @"S3 accelerate is enabled for this request but the bucket name is not accelerate compatible." + " The bucket name must be DNS compatible (http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html)" + " and must not contain any period (.) characters to be accelerate compatible."); } var originalRequest = request.OriginalRequest; bool accelerateSupportedApi = !UnsupportedAccelerateRequestTypes.Contains(originalRequest.GetType()); // Skip requests which are not supported if (accelerateSupportedApi) { request.Endpoint = GetAccelerateEndpoint(bucketResourcePathToken, s3Config); if (request.SignatureVersion == SignatureVersion.SigV4 && s3Config.RegionEndpoint != null) { request.AlternateEndpoint = s3Config.RegionEndpoint; } } } } if (removeBucketFromResourcePath) { // Remove bucket from resource path but retain in canonical resource // prefix, so it gets included when we sign the request later var resourcePath = request.ResourcePath; var canonicalBucketName = string.Concat("/", bucketResourcePathToken); if (resourcePath.IndexOf(canonicalBucketName, StringComparison.Ordinal) == 0) { resourcePath = resourcePath.Substring(canonicalBucketName.Length); } request.ResourcePath = resourcePath; request.CanonicalResourcePrefix = canonicalBucketName; } // Some parameters should not be sent over HTTP, just HTTPS if (isHttp) { ValidateHttpsOnlyHeaders(request); } }
/// <summary> /// Marshaller the request object to the HTTP request. /// </summary> /// <param name="publicRequest"></param> /// <returns></returns> public IRequest Marshall(PutBucketLifecycleConfigurationRequest publicRequest) { var request = new DefaultRequest(publicRequest, "Amazon.S3Control"); request.HttpMethod = "PUT"; if (Arn.IsArn(publicRequest.Bucket)) { publicRequest.AccountId = Amazon.S3Control.Internal.S3ArnUtils.GetAccountIdBasedOnArn( publicRequest.AccountId, Arn.Parse(publicRequest.Bucket).AccountId ); } if (publicRequest.IsSetAccountId()) { request.Headers["x-amz-account-id"] = publicRequest.AccountId; } if (!publicRequest.IsSetBucket()) { throw new AmazonS3ControlException("Request object does not have required field Bucket set"); } request.AddPathResource("{name}", StringUtils.FromString(publicRequest.Bucket)); request.ResourcePath = "/v20180820/bucket/{name}/lifecycleconfiguration"; var stringWriter = new StringWriter(CultureInfo.InvariantCulture); using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Encoding = System.Text.Encoding.UTF8, OmitXmlDeclaration = true })) { if (publicRequest.IsSetLifecycleConfiguration()) { xmlWriter.WriteStartElement("LifecycleConfiguration", "http://awss3control.amazonaws.com/doc/2018-08-20/"); var publicRequestLifecycleConfigurationRules = publicRequest.LifecycleConfiguration.Rules; if (publicRequestLifecycleConfigurationRules != null && publicRequestLifecycleConfigurationRules.Count > 0) { xmlWriter.WriteStartElement("Rules", "http://awss3control.amazonaws.com/doc/2018-08-20/"); foreach (var publicRequestLifecycleConfigurationRulesValue in publicRequestLifecycleConfigurationRules) { if (publicRequestLifecycleConfigurationRulesValue != null) { xmlWriter.WriteStartElement("Rule", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.AbortIncompleteMultipartUpload != null) { xmlWriter.WriteStartElement("AbortIncompleteMultipartUpload", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.AbortIncompleteMultipartUpload.IsSetDaysAfterInitiation()) { xmlWriter.WriteElementString("DaysAfterInitiation", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromInt(publicRequestLifecycleConfigurationRulesValue.AbortIncompleteMultipartUpload.DaysAfterInitiation)); } xmlWriter.WriteEndElement(); } if (publicRequestLifecycleConfigurationRulesValue.Expiration != null) { xmlWriter.WriteStartElement("Expiration", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.Expiration.IsSetDate()) { xmlWriter.WriteElementString("Date", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromDateTimeToISO8601(publicRequestLifecycleConfigurationRulesValue.Expiration.Date)); } if (publicRequestLifecycleConfigurationRulesValue.Expiration.IsSetDays()) { xmlWriter.WriteElementString("Days", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromInt(publicRequestLifecycleConfigurationRulesValue.Expiration.Days)); } if (publicRequestLifecycleConfigurationRulesValue.Expiration.IsSetExpiredObjectDeleteMarker()) { xmlWriter.WriteElementString("ExpiredObjectDeleteMarker", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromBool(publicRequestLifecycleConfigurationRulesValue.Expiration.ExpiredObjectDeleteMarker)); } xmlWriter.WriteEndElement(); } if (publicRequestLifecycleConfigurationRulesValue.Filter != null) { xmlWriter.WriteStartElement("Filter", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.Filter.And != null) { xmlWriter.WriteStartElement("And", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.Filter.And.IsSetPrefix()) { xmlWriter.WriteElementString("Prefix", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.Filter.And.Prefix)); } var publicRequestLifecycleConfigurationRulesValueFilterAndTags = publicRequestLifecycleConfigurationRulesValue.Filter.And.Tags; if (publicRequestLifecycleConfigurationRulesValueFilterAndTags != null && publicRequestLifecycleConfigurationRulesValueFilterAndTags.Count > 0) { xmlWriter.WriteStartElement("Tags", "http://awss3control.amazonaws.com/doc/2018-08-20/"); foreach (var publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue in publicRequestLifecycleConfigurationRulesValueFilterAndTags) { if (publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue != null) { xmlWriter.WriteStartElement("member", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue.IsSetKey()) { xmlWriter.WriteElementString("Key", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue.Key)); } if (publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue.IsSetValue()) { xmlWriter.WriteElementString("Value", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValueFilterAndTagsValue.Value)); } xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } if (publicRequestLifecycleConfigurationRulesValue.Filter.IsSetPrefix()) { xmlWriter.WriteElementString("Prefix", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.Filter.Prefix)); } if (publicRequestLifecycleConfigurationRulesValue.Filter.Tag != null) { xmlWriter.WriteStartElement("Tag", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.Filter.Tag.IsSetKey()) { xmlWriter.WriteElementString("Key", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.Filter.Tag.Key)); } if (publicRequestLifecycleConfigurationRulesValue.Filter.Tag.IsSetValue()) { xmlWriter.WriteElementString("Value", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.Filter.Tag.Value)); } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } if (publicRequestLifecycleConfigurationRulesValue.IsSetID()) { xmlWriter.WriteElementString("ID", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.ID)); } if (publicRequestLifecycleConfigurationRulesValue.NoncurrentVersionExpiration != null) { xmlWriter.WriteStartElement("NoncurrentVersionExpiration", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValue.NoncurrentVersionExpiration.IsSetNoncurrentDays()) { xmlWriter.WriteElementString("NoncurrentDays", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromInt(publicRequestLifecycleConfigurationRulesValue.NoncurrentVersionExpiration.NoncurrentDays)); } xmlWriter.WriteEndElement(); } var publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitions = publicRequestLifecycleConfigurationRulesValue.NoncurrentVersionTransitions; if (publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitions != null && publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitions.Count > 0) { xmlWriter.WriteStartElement("NoncurrentVersionTransitions", "http://awss3control.amazonaws.com/doc/2018-08-20/"); foreach (var publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue in publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitions) { if (publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue != null) { xmlWriter.WriteStartElement("NoncurrentVersionTransition", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue.IsSetNoncurrentDays()) { xmlWriter.WriteElementString("NoncurrentDays", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromInt(publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue.NoncurrentDays)); } if (publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue.IsSetStorageClass()) { xmlWriter.WriteElementString("StorageClass", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValueNoncurrentVersionTransitionsValue.StorageClass)); } xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); } if (publicRequestLifecycleConfigurationRulesValue.IsSetStatus()) { xmlWriter.WriteElementString("Status", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValue.Status)); } var publicRequestLifecycleConfigurationRulesValueTransitions = publicRequestLifecycleConfigurationRulesValue.Transitions; if (publicRequestLifecycleConfigurationRulesValueTransitions != null && publicRequestLifecycleConfigurationRulesValueTransitions.Count > 0) { xmlWriter.WriteStartElement("Transitions", "http://awss3control.amazonaws.com/doc/2018-08-20/"); foreach (var publicRequestLifecycleConfigurationRulesValueTransitionsValue in publicRequestLifecycleConfigurationRulesValueTransitions) { if (publicRequestLifecycleConfigurationRulesValueTransitionsValue != null) { xmlWriter.WriteStartElement("Transition", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestLifecycleConfigurationRulesValueTransitionsValue.IsSetDate()) { xmlWriter.WriteElementString("Date", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromDateTimeToISO8601(publicRequestLifecycleConfigurationRulesValueTransitionsValue.Date)); } if (publicRequestLifecycleConfigurationRulesValueTransitionsValue.IsSetDays()) { xmlWriter.WriteElementString("Days", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromInt(publicRequestLifecycleConfigurationRulesValueTransitionsValue.Days)); } if (publicRequestLifecycleConfigurationRulesValueTransitionsValue.IsSetStorageClass()) { xmlWriter.WriteElementString("StorageClass", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestLifecycleConfigurationRulesValueTransitionsValue.StorageClass)); } xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } } try { string content = stringWriter.ToString(); request.Content = System.Text.Encoding.UTF8.GetBytes(content); request.Headers["Content-Type"] = "application/xml"; var checksum = Amazon.Util.AWSSDKUtils.GenerateChecksumForContent(content, true); request.Headers[Amazon.Util.HeaderKeys.ContentMD5Header] = checksum; request.Headers[Amazon.Util.HeaderKeys.XAmzApiVersion] = "2018-08-20"; } catch (EncoderFallbackException e) { throw new AmazonServiceException("Unable to marshall request to XML", e); } var hostPrefixLabels = new { AccountId = StringUtils.FromString(publicRequest.AccountId), }; if (!HostPrefixUtils.IsValidLabelValue(hostPrefixLabels.AccountId)) { throw new AmazonS3ControlException("AccountId can only contain alphanumeric characters and dashes and must be between 1 and 63 characters long."); } request.HostPrefix = $"{hostPrefixLabels.AccountId}."; return(request); }
/// <summary> /// Check if aws ARN resembles an outpost ARN /// </summary> /// <param name="arn">An AWS ARN to parse</param> /// <returns>True if the ARN contains an outpost resource identifier.</returns> public static bool IsOutpostArn(this Arn arn) { return(!string.IsNullOrEmpty(arn.Resource) && (S3ArnUtils.ArnSplit.Any(i => arn.Resource.StartsWith($"{ResourceTypeOutpost}{i}")) || arn.Resource.Equals(ResourceTypeOutpost))); }
/// <summary> /// Check if the ARN has a valid service name /// </summary> /// <param name="arn">The ARN which is being validated</param> public static bool IsValidService(this Arn arn) { return(arn.Service.Equals(S3ArnUtils.S3OutpostsService)); }
/// <summary> /// Create a signed URL allowing access to a resource that would /// usually require authentication. /// </summary> /// <remarks> /// <para> /// When using query string authentication you create a query, /// specify an expiration time for the query, sign it with your /// signature, place the data in an HTTP request, and distribute /// the request to a user or embed the request in a web page. /// </para> /// <para> /// A PreSigned URL can be generated for GET, PUT, DELETE and HEAD /// operations on your bucketName, keys, and versions. /// </para> /// </remarks> /// <param name="request">The GetPreSignedUrlRequest that defines the /// parameters of the operation.</param> /// <param name="useSigV2Fallback">determines if signing will fall back to SigV2 if the /// signing region is us-east-1</param> /// <returns>A string that is the signed http request.</returns> /// <exception cref="T:System.ArgumentException" /> /// <exception cref="T:System.ArgumentNullException" /> internal string GetPreSignedURLInternal(GetPreSignedUrlRequest request, bool useSigV2Fallback = true) { if (Credentials == null) { throw new AmazonS3Exception("Credentials must be specified, cannot call method anonymously"); } if (request == null) { throw new ArgumentNullException("request", "The PreSignedUrlRequest specified is null!"); } if (!request.IsSetExpires()) { throw new InvalidOperationException("The Expires specified is null!"); } var aws4Signing = AWSConfigsS3.UseSignatureVersion4; Arn arn; string accessPoint; if (Arn.TryParse(request.BucketName, out arn) && arn.TryParseAccessPoint(out accessPoint)) { aws4Signing = true; } else { var region = AWS4Signer.DetermineSigningRegion(Config, "s3", alternateEndpoint: null, request: null); if (aws4Signing && string.IsNullOrEmpty(region)) { throw new InvalidOperationException("To use AWS4 signing, a region must be specified in the client configuration using the AuthenticationRegion or Region properties, or be determinable from the service URL."); } RegionEndpoint endpoint = RegionEndpoint.GetBySystemName(region); var s3SignatureVersionOverride = endpoint.GetEndpointForService("s3").SignatureVersionOverride; if (s3SignatureVersionOverride == "4" || s3SignatureVersionOverride == null) { aws4Signing = true; } var fallbackToSigV2 = useSigV2Fallback && !AWSConfigsS3.UseSigV4SetExplicitly; if (endpoint == RegionEndpoint.USEast1 && fallbackToSigV2) { aws4Signing = false; } // If the expiration is longer than SigV4 will allow then automatically use SigV2 instead. // But only if the region we're signing for allows SigV2. if (aws4Signing) { var secondsUntilExpiration = GetSecondsUntilExpiration(this.Config, request, aws4Signing); if (secondsUntilExpiration > AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry && s3SignatureVersionOverride == "2") { aws4Signing = false; } } } var immutableCredentials = Credentials.GetCredentials(); var irequest = Marshall(this.Config, request, immutableCredentials.AccessKey, immutableCredentials.Token, aws4Signing); irequest.Endpoint = EndpointResolver.DetermineEndpoint(this.Config, irequest); var context = new Amazon.Runtime.Internal.ExecutionContext(new Amazon.Runtime.Internal.RequestContext(true, new NullSigner()) { Request = irequest, ClientConfig = this.Config }, null); AmazonS3PostMarshallHandler.ProcessRequestHandlers(context); var metrics = new RequestMetrics(); string authorization; if (aws4Signing) { var aws4Signer = new AWS4PreSignedUrlSigner(); var signingResult = aws4Signer.SignRequest(irequest, this.Config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = "&" + signingResult.ForQueryParameters; } else { Amazon.S3.Internal.S3Signer.SignRequest(irequest, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = irequest.Headers[HeaderKeys.AuthorizationHeader]; authorization = authorization.Substring(authorization.IndexOf(":", StringComparison.Ordinal) + 1); authorization = "&Signature=" + AmazonS3Util.UrlEncode(authorization, false); } Uri url = AmazonServiceClient.ComposeUrl(irequest); string result = url.AbsoluteUri + authorization; Protocol protocol = DetermineProtocol(); if (request.Protocol != protocol) { switch (protocol) { case Protocol.HTTP: result = result.Replace("http://", "https://"); break; case Protocol.HTTPS: result = result.Replace("https://", "http://"); break; } } return(result); }
/// <summary> /// Check if the ARN has a valid Account ID /// </summary> /// <param name="arn">The ARN which is being validated</param> public static bool HasValidAccountId(this Arn arn) { return(string.IsNullOrEmpty(arn.AccountId) || (arn.AccountId.Length == 12 && arn.AccountId.ToCharArray().All(x => char.IsDigit(x)))); }
/// <summary> /// Marshaller the request object to the HTTP request. /// </summary> /// <param name="publicRequest"></param> /// <returns></returns> public IRequest Marshall(PutBucketTaggingRequest publicRequest) { var request = new DefaultRequest(publicRequest, "Amazon.S3Control"); request.HttpMethod = "PUT"; if (Arn.IsArn(publicRequest.Bucket)) { publicRequest.AccountId = Amazon.S3Control.Internal.S3ArnUtils.GetAccountIdBasedOnArn( publicRequest.AccountId, Arn.Parse(publicRequest.Bucket).AccountId ); } if (publicRequest.IsSetAccountId()) { request.Headers["x-amz-account-id"] = publicRequest.AccountId; } if (!publicRequest.IsSetBucket()) { throw new AmazonS3ControlException("Request object does not have required field Bucket set"); } request.AddPathResource("{name}", StringUtils.FromString(publicRequest.Bucket)); request.ResourcePath = "/v20180820/bucket/{name}/tagging"; var stringWriter = new XMLEncodedStringWriter(CultureInfo.InvariantCulture); using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Encoding = System.Text.Encoding.UTF8, OmitXmlDeclaration = true, NewLineHandling = NewLineHandling.Entitize })) { if (publicRequest.IsSetTagging()) { xmlWriter.WriteStartElement("Tagging", "http://awss3control.amazonaws.com/doc/2018-08-20/"); var publicRequestTaggingTagSet = publicRequest.Tagging.TagSet; if (publicRequestTaggingTagSet != null && publicRequestTaggingTagSet.Count > 0) { xmlWriter.WriteStartElement("TagSet", "http://awss3control.amazonaws.com/doc/2018-08-20/"); foreach (var publicRequestTaggingTagSetValue in publicRequestTaggingTagSet) { if (publicRequestTaggingTagSetValue != null) { xmlWriter.WriteStartElement("member", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequestTaggingTagSetValue.IsSetKey()) { xmlWriter.WriteElementString("Key", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestTaggingTagSetValue.Key)); } if (publicRequestTaggingTagSetValue.IsSetValue()) { xmlWriter.WriteElementString("Value", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequestTaggingTagSetValue.Value)); } xmlWriter.WriteEndElement(); } } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } } try { string content = stringWriter.ToString(); request.Content = System.Text.Encoding.UTF8.GetBytes(content); request.Headers["Content-Type"] = "application/xml"; ChecksumUtils.SetRequestChecksumMD5(request); request.Headers[Amazon.Util.HeaderKeys.XAmzApiVersion] = "2018-08-20"; } catch (EncoderFallbackException e) { throw new AmazonServiceException("Unable to marshall request to XML", e); } var hostPrefixLabels = new { AccountId = StringUtils.FromString(publicRequest.AccountId), }; if (!HostPrefixUtils.IsValidLabelValue(hostPrefixLabels.AccountId)) { throw new AmazonS3ControlException("AccountId can only contain alphanumeric characters and dashes and must be between 1 and 63 characters long."); } request.HostPrefix = $"{hostPrefixLabels.AccountId}."; return(request); }
/// <summary> /// Marshaller the request object to the HTTP request. /// </summary> /// <param name="publicRequest"></param> /// <returns></returns> public IRequest Marshall(CreateAccessPointRequest publicRequest) { var request = new DefaultRequest(publicRequest, "Amazon.S3Control"); request.HttpMethod = "PUT"; if (Arn.IsArn(publicRequest.Bucket)) { publicRequest.AccountId = Amazon.S3Control.Internal.S3ArnUtils.GetAccountIdBasedOnArn( publicRequest.AccountId, Arn.Parse(publicRequest.Bucket).AccountId ); } if (publicRequest.IsSetAccountId()) { request.Headers["x-amz-account-id"] = publicRequest.AccountId; } if (!publicRequest.IsSetName()) { throw new AmazonS3ControlException("Request object does not have required field Name set"); } request.AddPathResource("{name}", StringUtils.FromString(publicRequest.Name)); request.ResourcePath = "/v20180820/accesspoint/{name}"; request.MarshallerVersion = 2; var stringWriter = new StringWriter(CultureInfo.InvariantCulture); using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Encoding = System.Text.Encoding.UTF8, OmitXmlDeclaration = true })) { xmlWriter.WriteStartElement("CreateAccessPointRequest", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequest.IsSetBucket()) { xmlWriter.WriteElementString("Bucket", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequest.Bucket)); } if (publicRequest.PublicAccessBlockConfiguration != null) { xmlWriter.WriteStartElement("PublicAccessBlockConfiguration", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequest.PublicAccessBlockConfiguration.IsSetBlockPublicAcls()) { xmlWriter.WriteElementString("BlockPublicAcls", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromBool(publicRequest.PublicAccessBlockConfiguration.BlockPublicAcls)); } if (publicRequest.PublicAccessBlockConfiguration.IsSetBlockPublicPolicy()) { xmlWriter.WriteElementString("BlockPublicPolicy", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromBool(publicRequest.PublicAccessBlockConfiguration.BlockPublicPolicy)); } if (publicRequest.PublicAccessBlockConfiguration.IsSetIgnorePublicAcls()) { xmlWriter.WriteElementString("IgnorePublicAcls", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromBool(publicRequest.PublicAccessBlockConfiguration.IgnorePublicAcls)); } if (publicRequest.PublicAccessBlockConfiguration.IsSetRestrictPublicBuckets()) { xmlWriter.WriteElementString("RestrictPublicBuckets", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromBool(publicRequest.PublicAccessBlockConfiguration.RestrictPublicBuckets)); } xmlWriter.WriteEndElement(); } if (publicRequest.VpcConfiguration != null) { xmlWriter.WriteStartElement("VpcConfiguration", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequest.VpcConfiguration.IsSetVpcId()) { xmlWriter.WriteElementString("VpcId", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequest.VpcConfiguration.VpcId)); } xmlWriter.WriteEndElement(); } xmlWriter.WriteEndElement(); } try { string content = stringWriter.ToString(); request.Content = System.Text.Encoding.UTF8.GetBytes(content); request.Headers["Content-Type"] = "application/xml"; request.Headers[Amazon.Util.HeaderKeys.XAmzApiVersion] = "2018-08-20"; } catch (EncoderFallbackException e) { throw new AmazonServiceException("Unable to marshall request to XML", e); } var hostPrefixLabels = new { AccountId = StringUtils.FromString(publicRequest.AccountId), }; if (!HostPrefixUtils.IsValidLabelValue(hostPrefixLabels.AccountId)) { throw new AmazonS3ControlException("AccountId can only contain alphanumeric characters and dashes and must be between 1 and 63 characters long."); } request.HostPrefix = $"{hostPrefixLabels.AccountId}."; return(request); }
/// <summary> /// Checks whether an ARN belongs to a particular service /// </summary> /// <returns>True if a match is found</returns> public static bool IsService(this Arn arn, string serviceName) { return(arn.Service.Equals(serviceName, StringComparison.Ordinal)); }