// Gets the bucket name from resource path internal static string GetBucketName(string resourcePath) { resourcePath = resourcePath.Trim().Trim(separators); /// If the resource is an outposts resource, we want to handle getting the bucket name /// later and just return the trimmed path. if (Arn.IsArn(resourcePath)) { Arn arn; try { arn = Arn.Parse(resourcePath); } catch (AmazonAccountIdException) { throw new AmazonAccountIdException(); // Throw with the default exception message. } if (arn.IsOutpostArn()) { return(resourcePath); } } var parts = resourcePath.Split(separators); var bucketName = parts[0]; // Check to see if the bucket name is an arn using a '/' to break up the access point prefix and identifier. // If it is then bucketName will currently be missing the resource identifier which is the next token in the split. // // For example a resource path using an arn to get an object will look like this: // arn:aws:s3:us-west-2:12345689:accesspoint/mybucket/myobject.txt. // We need this method to return "arn:aws:s3:us-west-2:12345689:accesspoint/mybucket" but by splitting on "/" // only "arn:aws:s3:us-west-2:12345689:accesspoint" is captured. This if block checks to see it is the resource path has an access point arn and then // grab the bucket name which is the next token in the split. if (Arn.IsArn(bucketName) && bucketName.EndsWith(ArnExtensions.ResourceTypeAccessPoint)) { bucketName += "/" + parts[1]; } return(bucketName); }
/// <summary> /// Marshaller the request object to the HTTP request. /// </summary> /// <param name="publicRequest"></param> /// <returns></returns> public IRequest Marshall(GetBucketPolicyRequest publicRequest) { var request = new DefaultRequest(publicRequest, "Amazon.S3Control"); request.HttpMethod = "GET"; 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}/policy"; 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); }
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.UseSigV4 = true; } 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; Arn s3Arn = Arn.Parse(bucketResourcePathToken); if (s3Arn.IsService("s3") && s3Arn.TryParseAccessPoint(out accessPoint)) { ValidateS3AccessPoint(s3Arn, s3Config, regionEndpoint); UriBuilder ub; 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"; ub = new UriBuilder($"{scheme}://{accessPoint}-{s3Arn.AccountId}.s3-accesspoint{(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); UriBuilder ub; 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"; ub = new UriBuilder($"{scheme}://{accessPoint}-{s3Arn.AccountId}.{s3ObjectLambdaServiceName}.{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; UriBuilder ub; 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. request.AuthenticationRegion = s3Arn.Region; request.UseSigV4 = true; removeBucketFromResourcePath = true; } else { // 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.UseSigV4 = true; } 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.UseSigV4 && 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(PutAccessPointPolicyRequest publicRequest) { var request = new DefaultRequest(publicRequest, "Amazon.S3Control"); request.HttpMethod = "PUT"; if (Arn.IsArn(publicRequest.Name)) { publicRequest.AccountId = Amazon.S3Control.Internal.S3ArnUtils.GetAccountIdBasedOnArn( publicRequest.AccountId, Arn.Parse(publicRequest.Name).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}/policy"; var stringWriter = new StringWriter(CultureInfo.InvariantCulture); using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Encoding = System.Text.Encoding.UTF8, OmitXmlDeclaration = true })) { xmlWriter.WriteStartElement("PutAccessPointPolicyRequest", "http://awss3control.amazonaws.com/doc/2018-08-20/"); if (publicRequest.IsSetPolicy()) { xmlWriter.WriteElementString("Policy", "http://awss3control.amazonaws.com/doc/2018-08-20/", StringUtils.FromString(publicRequest.Policy)); } 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> /// 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"; request.MarshallerVersion = 2; 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> /// 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 StringWriter(CultureInfo.InvariantCulture); using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Encoding = System.Text.Encoding.UTF8, OmitXmlDeclaration = true })) { 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"; 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); }
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.UseSigV4 = true; } 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"); } bool isHttp; bool removeBucketFromResourcePath = false; if (Arn.IsArn(bucketResourcePathToken)) { string accessPoint; Arn accessPointArn; if ((accessPointArn = Arn.Parse(bucketResourcePathToken)).TryParseAccessPoint(out accessPoint)) { if (!string.IsNullOrEmpty(config.ServiceURL)) { throw new AmazonClientException( "The request is using an access point ARN for the bucket name and the S3 service client is configured to use a specific host using the ServiceURL property. " + "Access point ARNs define the host for the request which makes it incompatible with the host being set ServiceURL. " + "When using access point arns set the region and not the ServiceURL for the S3 service client."); } if (s3Config.UseAccelerateEndpoint) { throw new AmazonClientException( "The request is using an access point ARN for the bucket name and the S3 service client is configured to use accelerate endpoints which is not supported. " + "To use this access point create a new S3 service client with the UseAccelerateEndpoint property set to false." ); } if (string.IsNullOrEmpty(accessPointArn.AccountId)) { throw new AmazonClientException("Account ID is missing in access point ARN"); } if (string.IsNullOrEmpty(accessPointArn.Region)) { throw new AmazonClientException("AWS region is missing in access point ARN"); } if (!string.Equals(config.RegionEndpoint.PartitionName, accessPointArn.Partition, StringComparison.Ordinal)) { throw new AmazonClientException("The access point used in the request is in a different AWS partition then the region configured for the AmazonS3Client."); } ValidateUseArnRegion(accessPointArn, s3Config); request.UseSigV4 = true; isHttp = config.UseHttp; removeBucketFromResourcePath = true; var scheme = isHttp ? "http" : "https"; UriBuilder ub = new UriBuilder($"{scheme}://{accessPoint}-{accessPointArn.AccountId}.s3-accesspoint{(config.UseDualstackEndpoint ? ".dualstack" : "")}.{accessPointArn.Region}.{config.RegionEndpoint.PartitionDnsSuffix}"); request.Endpoint = ub.Uri; // 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. request.AuthenticationRegion = accessPointArn.Region; } else { throw new AmazonClientException("Invalid ARN specified for bucket name. Only access point ARNs are allowed for the value of bucket name."); } } else { // 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 (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.UseSigV4 && 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); } }