Exemplo n.º 1
0
        /// <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>
        /// 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>
        /// <returns>A string that is the signed http request.</returns>
        /// <exception cref="T:System.ArgumentException" />
        /// <exception cref="T:System.ArgumentNullException" />
        public string GetPreSignedURL(GetPreSignedUrlRequest request)
        {
            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 = AWSConfigs.S3Config.UseSignatureVersion4;
            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);

            if (endpoint.GetEndpointForService("s3").SignatureVersionOverride == "4")
            {
                aws4Signing = true;
            }

            var immutableCredentials = Credentials.GetCredentials();
            var irequest             = Marshall(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)
            {
                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
            {
                this.Signer.Sign(irequest, this.Config, 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);
        }
        static string ConstructCopySourceHeaderValue(string bucket, string key, string version)
        {
            string source;

            if (!String.IsNullOrEmpty(key))
            {
                source = AmazonS3Util.UrlEncode(String.Concat("/", bucket, "/", key), true);
                if (!String.IsNullOrEmpty(version))
                {
                    source = string.Format(CultureInfo.InvariantCulture, "{0}?versionId={1}", source, AmazonS3Util.UrlEncode(version, true));
                }
            }
            else
            {
                source = AmazonS3Util.UrlEncode(bucket, true);
            }

            return(source);
        }
Exemplo n.º 4
0
        static string buildSigningString(string verb, string canonicalizedResource, IDictionary <string, string> parameters, IDictionary <string, string> webHeaders)
        {
            StringBuilder sb    = new StringBuilder("", 256);
            string        value = null;

            sb.Append(verb);
            sb.Append("\n");

            if (webHeaders != null)
            {
                if (webHeaders.ContainsKey(AWSSDKUtils.ContentMD5Header) && !String.IsNullOrEmpty(value = webHeaders[AWSSDKUtils.ContentMD5Header]))
                {
                    sb.Append(value);
                }
                sb.Append("\n");

                if (parameters.ContainsKey(S3QueryParameter.ContentType.ToString()))
                {
                    sb.Append(parameters[S3QueryParameter.ContentType.ToString()]);
                }
                else if (webHeaders.ContainsKey("Content-Type"))
                {
                    sb.Append(webHeaders["Content-Type"]);
                }
                sb.Append("\n");
            }
            else
            {
                // The headers are null, but we still need to append
                // the 2 newlines that are required by S3.
                // Without these, S3 rejects the signature.
                sb.Append("\n\n");
            }

            if (parameters.ContainsKey(S3QueryParameter.Expires.ToString()))
            {
                sb.Append(parameters[S3QueryParameter.Expires.ToString()]);
                webHeaders.Remove(S3Constants.AmzDateHeader);
            }

            sb.Append("\n");
            sb.Append(buildCanonicalizedHeaders(webHeaders));

            if (!string.IsNullOrEmpty(canonicalizedResource))
            {
                int quotePos = canonicalizedResource.IndexOf("?", StringComparison.OrdinalIgnoreCase);
                if (quotePos != -1)
                {
                    var path     = canonicalizedResource.Substring(0, quotePos);
                    var query    = canonicalizedResource.Substring(quotePos);
                    var fullPath = AmazonS3Util.UrlEncode(path, true) + query;
                    sb.Append(fullPath);
                }
                else
                {
                    sb.Append(AmazonS3Util.UrlEncode(canonicalizedResource, true));
                }
            }

            return(sb.ToString());
        }
        static string ConstructCopySourceHeaderValue(string bucket, string key, string version)
        {
            string source;

            if (!String.IsNullOrEmpty(key))
            {
                var isAccessPoint = S3ArnUtils.IsS3AccessPointsArn(bucket) || S3ArnUtils.IsS3OutpostsArn(bucket);
                // 'object/' needed appended to key for copy header with access points
                source = AmazonS3Util.UrlEncode(String.Concat(bucket, isAccessPoint ? "/object/" : "/", key), !isAccessPoint);
                if (!String.IsNullOrEmpty(version))
                {
                    source = string.Format(CultureInfo.InvariantCulture, "{0}?versionId={1}", source, AmazonS3Util.UrlEncode(version, true));
                }
            }
            else
            {
                source = AmazonS3Util.UrlEncode(bucket, true);
            }

            return(source);
        }
Exemplo n.º 6
0
        static string ConstructCopySourceHeaderValue(string bucket, string key, string version)
        {
            string source;

            if (!String.IsNullOrEmpty(key))
            {
                var sourceKey = key.StartsWith("/", StringComparison.Ordinal)
                                        ? key.Substring(1)
                                        : key;
                source = AmazonS3Util.UrlEncode(String.Concat("/", bucket, "/", sourceKey), true);
                if (!String.IsNullOrEmpty(version))
                {
                    source = string.Format(CultureInfo.InvariantCulture, "{0}?versionId={1}", source, AmazonS3Util.UrlEncode(version, true));
                }
            }
            else
            {
                source = AmazonS3Util.UrlEncode(bucket, true);
            }

            return(source);
        }