// 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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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);
        }
예제 #7
0
        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);
            }
        }