/// <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); }
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); }
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); }