protected override void PreInvoke(IExecutionContext executionContext) { var request = executionContext.RequestContext.OriginalRequest; var config = executionContext.RequestContext.ClientConfig; var copySnapshotRequest = request as CopySnapshotRequest; if (copySnapshotRequest != null) { if (string.IsNullOrEmpty(copySnapshotRequest.DestinationRegion)) { copySnapshotRequest.DestinationRegion = AWS4Signer.DetermineSigningRegion(config, "ec2", alternateEndpoint: null); } if (string.IsNullOrEmpty(copySnapshotRequest.SourceRegion)) { throw new AmazonEC2Exception("SourceRegion is required to perform the copy snapshot."); } var endpoint = RegionEndpoint.GetBySystemName(copySnapshotRequest.SourceRegion); if (endpoint == null) { throw new AmazonEC2Exception(string.Format(CultureInfo.InvariantCulture, "No endpoint for region {0}.", copySnapshotRequest.SourceRegion)); } // Make sure the presigned URL is currently null so we don't attempt to generate // a presigned URL with a presigned URL. copySnapshotRequest.PresignedUrl = null; // Marshall this request but switch to the source region and make it a GET request. var marshaller = new CopySnapshotRequestMarshaller(); var irequest = marshaller.Marshall(copySnapshotRequest); irequest.UseQueryString = true; irequest.HttpMethod = "GET"; irequest.Parameters.Add("X-Amz-Expires", AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry.ToString(CultureInfo.InvariantCulture)); irequest.Endpoint = new Uri("https://" + endpoint.GetEndpointForService(config.RegionEndpointServiceName).Hostname); // Create presigned URL. var metrics = new RequestMetrics(); var immutableCredentials = _credentials.GetCredentials(); if (immutableCredentials.UseToken) { irequest.Parameters["X-Amz-Security-Token"] = immutableCredentials.Token; } var signingResult = AWS4PreSignedUrlSigner.SignRequest(irequest, config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey, "ec2", copySnapshotRequest.SourceRegion); var authorization = "&" + signingResult.ForQueryParameters; var url = AmazonServiceClient.ComposeUrl(irequest); copySnapshotRequest.PresignedUrl = url.AbsoluteUri + authorization; } }
protected override void ProcessPreRequestHandlers(AmazonWebServiceRequest request) { base.ProcessPreRequestHandlers(request); var requestCopySnapshot = request as CopySnapshotRequest; if (requestCopySnapshot != null) { if (string.IsNullOrEmpty(requestCopySnapshot.DestinationRegion)) { requestCopySnapshot.DestinationRegion = AWS4Signer.DetermineSigningRegion(this.Config, "ec2"); } if (string.IsNullOrEmpty(requestCopySnapshot.SourceRegion)) { throw new AmazonEC2Exception("SourceRegion is required to perform the copy snapshot."); } var endpoint = RegionEndpoint.GetBySystemName(requestCopySnapshot.SourceRegion); if (endpoint == null) { throw new AmazonEC2Exception(string.Format(CultureInfo.InvariantCulture, "No endpoint for region {0}.", requestCopySnapshot.SourceRegion)); } // Make sure the presigned URL is currently null so we don't attempt to generate // a presigned URL with a presigned URL. requestCopySnapshot.PresignedUrl = null; // Marshall this request but switch to the source region and make it a GET request. CopySnapshotRequestMarshaller marshaller = new CopySnapshotRequestMarshaller(); var irequest = marshaller.Marshall(requestCopySnapshot); irequest.UseQueryString = true; irequest.HttpMethod = "GET"; irequest.Parameters.Add("X-Amz-Expires", AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry.ToString(CultureInfo.InvariantCulture)); irequest.Endpoint = new Uri("https://" + endpoint.GetEndpointForService(this.Config.RegionEndpointServiceName).Hostname); // Create presigned URL. var metrics = new RequestMetrics(); var immutableCredentials = Credentials.GetCredentials(); var signingResult = AWS4PreSignedUrlSigner.SignRequest(irequest, this.Config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey, "ec2", requestCopySnapshot.SourceRegion); var authorization = "&" + signingResult.ForQueryParameters; Uri url = ComposeUrl(irequest, irequest.Endpoint); requestCopySnapshot.PresignedUrl = url.AbsoluteUri + authorization; } }
/// /// <summary> /// Calculates the signature for the specified request using the Asymmetric SigV4 /// signing protocol in preparation for generating a presigned URL. /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the /// SigV4a protocol will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics">Metrics for the request</param> /// <param name="credentials">The AWS credentials for the account making the service call</param> /// <param name="service">Service to sign the request for</param> /// <param name="overrideSigningRegion">Region to sign the request for</param> /// <returns>AWS4aSigningResult for the given request</returns> public AWS4aSigningResult Presign4a(IRequest request, IClientConfig clientConfig, RequestMetrics metrics, ImmutableCredentials credentials, string service, string overrideSigningRegion) { var signedAt = AWS4Signer.InitializeHeaders(request.Headers, request.Endpoint); var regionSet = overrideSigningRegion ?? AWS4Signer.DetermineSigningRegion(clientConfig, service, request.AlternateEndpoint, request); var signingConfig = PrepareCRTSigningConfig(AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS, regionSet, service, signedAt, credentials); if (AWS4PreSignedUrlSigner.ServicesUsingUnsignedPayload.Contains(service)) { signingConfig.SignedBodyValue = AWS4Signer.UnsignedPayload; } else { signingConfig.SignedBodyValue = AWS4Signer.EmptyBodySha256; } // The expiration may have already be set in a header when marshalling the GetPreSignedUrlRequest -> IRequest if (request.Parameters != null && request.Parameters.ContainsKey(HeaderKeys.XAmzExpires)) { signingConfig.ExpirationInSeconds = Convert.ToUInt64(request.Parameters[HeaderKeys.XAmzExpires]); } var crtRequest = CrtHttpRequestConverter.ConvertToCrtRequest(request); var signingResult = AwsSigner.SignHttpRequest(crtRequest, signingConfig); string authorizationValue = Encoding.Default.GetString(signingResult.Get().Signature); var dateStamp = AWS4Signer.FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat); var scope = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}", dateStamp, service, AWS4Signer.Terminator); AWS4aSigningResult result = new AWS4aSigningResult( credentials.AccessKey, signedAt, CrtHttpRequestConverter.ExtractSignedHeaders(signingResult.Get().SignedRequest), scope, regionSet, authorizationValue, service, signingResult.Get().SignedRequest.Uri, credentials); return(result); }
/// <summary> /// Calculates the signature for the specified request using the Asymmetric SigV4 signing protocol /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the /// SigV4a protocol will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics">Metrics for the request</param> /// <param name="credentials">The AWS credentials for the account making the service call</param> /// <returns>AWS4aSigningResult for the given request</returns> public AWS4aSigningResult SignRequest(IRequest request, IClientConfig clientConfig, RequestMetrics metrics, ImmutableCredentials credentials) { var signedAt = AWS4Signer.InitializeHeaders(request.Headers, request.Endpoint); var serviceSigningName = !string.IsNullOrEmpty(request.OverrideSigningServiceName) ? request.OverrideSigningServiceName : AWS4Signer.DetermineService(clientConfig); var regionSet = AWS4Signer.DetermineSigningRegion(clientConfig, clientConfig.RegionEndpointServiceName, request.AlternateEndpoint, request); request.DeterminedSigningRegion = regionSet; AWS4Signer.SetXAmzTrailerHeader(request.Headers, request.TrailingHeaders); var signingConfig = PrepareCRTSigningConfig(AwsSignatureType.HTTP_REQUEST_VIA_HEADERS, regionSet, serviceSigningName, signedAt, credentials); // If the request should use a fixed x-amz-content-sha256 header value, determine the appropriate one var fixedBodyHash = request.TrailingHeaders?.Count > 0 ? AWS4Signer.V4aStreamingBodySha256WithTrailer : AWS4Signer.V4aStreamingBodySha256; signingConfig.SignedBodyValue = AWS4Signer.SetRequestBodyHash(request, SignPayload, fixedBodyHash, ChunkedUploadWrapperStream.V4A_SIGNATURE_LENGTH); var crtRequest = CrtHttpRequestConverter.ConvertToCrtRequest(request); var signingResult = AwsSigner.SignHttpRequest(crtRequest, signingConfig); var authorizationValue = Encoding.Default.GetString(signingResult.Get().Signature); var signedCrtRequest = signingResult.Get().SignedRequest; CrtHttpRequestConverter.CopyHeadersFromCrtRequest(request, signedCrtRequest); var dateStamp = AWS4Signer.FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat); var scope = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}", dateStamp, serviceSigningName, AWS4Signer.Terminator); AWS4aSigningResult result = new AWS4aSigningResult( credentials.AccessKey, signedAt, CrtHttpRequestConverter.ExtractSignedHeaders(signedCrtRequest), scope, regionSet, authorizationValue, serviceSigningName, "", credentials); return(result); }
/// <summary> /// Calculates the signature for the specified request using the Asymmetric SigV4 signing protocol /// </summary> /// <param name="request"> /// The request to compute the signature for. Additional headers mandated by the /// SigV4a protocol will be added to the request before signing. /// </param> /// <param name="clientConfig"> /// Client configuration data encompassing the service call (notably authentication /// region, endpoint and service name). /// </param> /// <param name="metrics">Metrics for the request</param> /// <param name="credentials">The AWS credentials for the account making the service call</param> /// <returns>AWS4aSigningResult for the given request</returns> public AWS4aSigningResult SignRequest(IRequest request, IClientConfig clientConfig, RequestMetrics metrics, ImmutableCredentials credentials) { var signedAt = AWS4Signer.InitializeHeaders(request.Headers, request.Endpoint); var service = !string.IsNullOrEmpty(request.OverrideSigningServiceName) ? request.OverrideSigningServiceName : AWS4Signer.DetermineService(clientConfig); var regionSet = AWS4Signer.DetermineSigningRegion(clientConfig, service, request.AlternateEndpoint, request); request.DeterminedSigningRegion = regionSet; var signingConfig = PrepareCRTSigningConfig(AwsSignatureType.HTTP_REQUEST_VIA_HEADERS, regionSet, service, signedAt, credentials); // Compute here rather than CRT to support the fixed value for header of a chunked request signingConfig.SignedBodyValue = AWS4Signer.SetRequestBodyHash(request, SignPayload, AWS4Signer.V4aStreamingBodySha256, ChunkedUploadWrapperStream.V4A_SIGNATURE_LENGTH); var crtRequest = CrtHttpRequestConverter.ConvertToCrtRequest(request); var signingResult = AwsSigner.SignHttpRequest(crtRequest, signingConfig); var authorizationValue = Encoding.Default.GetString(signingResult.Get().Signature); var signedCrtRequest = signingResult.Get().SignedRequest; CrtHttpRequestConverter.CopyHeadersFromCrtRequest(request, signedCrtRequest); var dateStamp = AWS4Signer.FormatDateTime(signedAt, AWSSDKUtils.ISO8601BasicDateFormat); var scope = string.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}", dateStamp, service, AWS4Signer.Terminator); AWS4aSigningResult result = new AWS4aSigningResult( credentials.AccessKey, signedAt, CrtHttpRequestConverter.ExtractSignedHeaders(signedCrtRequest), scope, regionSet, authorizationValue, service, "", credentials); return(result); }
private void RunTestRequest(AmazonWebServiceRequest request, IMarshaller <IRequest, AmazonWebServiceRequest> marshaller, bool isArn, string serviceUrl, Flags flags, string expectedUri, string expectedRegion, string expectedService) { var clientConfig = CreateConfig(serviceUrl, flags); var internalRequest = S3ControlArnTestUtils.RunMockRequest(request, marshaller, clientConfig); Assert.AreEqual(new Uri(expectedUri), internalRequest.Endpoint); if (isArn) { Assert.AreEqual(expectedRegion, internalRequest.AuthenticationRegion); Assert.AreEqual(expectedService, internalRequest.OverrideSigningServiceName); } var service = DetermineService(clientConfig); var signingRegion = AWS4Signer.DetermineSigningRegion(clientConfig, service, internalRequest.AlternateEndpoint, internalRequest); Assert.AreEqual(expectedRegion, signingRegion); Assert.AreEqual(expectedService, internalRequest.OverrideSigningServiceName ?? service); }
/// <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 /// <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; 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" || endpoint.GetEndpointForService("s3").SignatureVersionOverride == 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(request, aws4Signing); if (secondsUntilExpiration > AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry && endpoint.GetEndpointForService("s3").SignatureVersionOverride == "2") { aws4Signing = false; } } 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 { 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> /// Custom pipeline handler /// </summary> /// <param name="executionContext"></param> protected void PreInvoke(IExecutionContext executionContext) { var request = executionContext.RequestContext.OriginalRequest; var config = executionContext.RequestContext.ClientConfig; var runInstancesRequest = request as RunInstancesRequest; if (runInstancesRequest != null) { if (runInstancesRequest.IsSetBlockDeviceMappings()) { var mappings = runInstancesRequest.BlockDeviceMappings; foreach (var mapping in mappings) { if (mapping.IsSetEbs()) { var ebs = mapping.Ebs; if (ebs.IsSetSnapshotId() && ebs.IsSetEncrypted() && ebs.Encrypted == false) { ebs.ClearEncryptedFlag(); } } } } } // replace null Tag.Value with empty string var createTagsRequest = request as CreateTagsRequest; if (createTagsRequest != null) { if (createTagsRequest.IsSetTags()) { var tags = createTagsRequest.Tags; foreach (var tag in tags) { if (tag != null && tag.Value == null) { tag.Value = string.Empty; } } } } var copySnapshotRequest = request as CopySnapshotRequest; if (copySnapshotRequest != null) { if (string.IsNullOrEmpty(copySnapshotRequest.DestinationRegion)) { copySnapshotRequest.DestinationRegion = AWS4Signer.DetermineSigningRegion(config, "ec2", alternateEndpoint: null, request: null); } if (string.IsNullOrEmpty(copySnapshotRequest.SourceRegion)) { throw new AmazonEC2Exception("SourceRegion is required to perform the copy snapshot."); } var endpoint = RegionEndpoint.GetBySystemName(copySnapshotRequest.SourceRegion); if (endpoint == null) { throw new AmazonEC2Exception(string.Format(CultureInfo.InvariantCulture, "No endpoint for region {0}.", copySnapshotRequest.SourceRegion)); } // Make sure the presigned URL is currently null so we don't attempt to generate // a presigned URL with a presigned URL. copySnapshotRequest.PresignedUrl = null; // Marshall this request but switch to the source region and make it a GET request. var marshaller = new CopySnapshotRequestMarshaller(); var irequest = marshaller.Marshall(copySnapshotRequest); irequest.UseQueryString = true; irequest.HttpMethod = "GET"; irequest.Parameters.Add("X-Amz-Expires", AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry.ToString(CultureInfo.InvariantCulture)); irequest.Endpoint = new Uri("https://" + endpoint.GetEndpointForService(config.RegionEndpointServiceName).Hostname); // Create presigned URL. var metrics = new RequestMetrics(); var immutableCredentials = _credentials.GetCredentials(); if (immutableCredentials.UseToken) { irequest.Parameters["X-Amz-Security-Token"] = immutableCredentials.Token; } var signingResult = AWS4PreSignedUrlSigner.SignRequest(irequest, config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey, "ec2", copySnapshotRequest.SourceRegion); var authorization = "&" + signingResult.ForQueryParameters; var url = AmazonServiceClient.ComposeUrl(irequest); copySnapshotRequest.PresignedUrl = url.AbsoluteUri + authorization; } var authorizeSecurityGroupEgressRequest = request as AuthorizeSecurityGroupEgressRequest; if (authorizeSecurityGroupEgressRequest != null) { if (authorizeSecurityGroupEgressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(authorizeSecurityGroupEgressRequest.IpPermissions); } } var authorizeSecurityGroupIngressRequest = request as AuthorizeSecurityGroupIngressRequest; if (authorizeSecurityGroupIngressRequest != null) { if (authorizeSecurityGroupIngressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(authorizeSecurityGroupIngressRequest.IpPermissions); } } var revokeSecurityGroupEgressRequest = request as RevokeSecurityGroupEgressRequest; if (revokeSecurityGroupEgressRequest != null) { if (revokeSecurityGroupEgressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(revokeSecurityGroupEgressRequest.IpPermissions); } } var revokeSecurityGroupIngressRequest = request as RevokeSecurityGroupIngressRequest; if (revokeSecurityGroupIngressRequest != null) { if (revokeSecurityGroupIngressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(revokeSecurityGroupIngressRequest.IpPermissions); } } var updateSecurityGroupRuleDescriptionsEgressRequest = request as UpdateSecurityGroupRuleDescriptionsEgressRequest; if (updateSecurityGroupRuleDescriptionsEgressRequest != null) { if (updateSecurityGroupRuleDescriptionsEgressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(updateSecurityGroupRuleDescriptionsEgressRequest.IpPermissions); } } var updateSecurityGroupRuleDescriptionsIngressRequest = request as UpdateSecurityGroupRuleDescriptionsIngressRequest; if (updateSecurityGroupRuleDescriptionsIngressRequest != null) { if (updateSecurityGroupRuleDescriptionsIngressRequest.IsSetIpPermissions()) { SelectModifiedIpRange(updateSecurityGroupRuleDescriptionsIngressRequest.IpPermissions); } } }
/// <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 signatureVersionToUse = AWSConfigsS3.UseSignatureVersion4 ? SignatureVersion.SigV4 : SignatureVersion.SigV2; Arn arn; string accessPoint; if (Arn.TryParse(request.BucketName, out arn) && (arn.TryParseAccessPoint(out accessPoint) || arn.IsOutpostArn())) { signatureVersionToUse = SignatureVersion.SigV4; if (arn.IsMRAPArn()) { signatureVersionToUse = SignatureVersion.SigV4a; } } else { var region = AWS4Signer.DetermineSigningRegion(Config, "s3", alternateEndpoint: null, request: null); if (signatureVersionToUse == SignatureVersion.SigV4 && 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", Config.ToGetEndpointForServiceOptions()).SignatureVersionOverride; if (s3SignatureVersionOverride == "4" || s3SignatureVersionOverride == null) { signatureVersionToUse = SignatureVersion.SigV4; } var fallbackToSigV2 = useSigV2Fallback && !AWSConfigsS3.UseSigV4SetExplicitly; if (endpoint?.SystemName == RegionEndpoint.USEast1.SystemName && fallbackToSigV2) { signatureVersionToUse = SignatureVersion.SigV2; } // 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 (signatureVersionToUse == SignatureVersion.SigV4) { var secondsUntilExpiration = GetSecondsUntilExpiration(this.Config, request, signatureVersionToUse); if (secondsUntilExpiration > AWS4PreSignedUrlSigner.MaxAWS4PreSignedUrlExpiry && s3SignatureVersionOverride == "2") { signatureVersionToUse = SignatureVersion.SigV2; } } } var immutableCredentials = Credentials.GetCredentials(); var irequest = Marshall(this.Config, request, immutableCredentials.AccessKey, immutableCredentials.Token, signatureVersionToUse); 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 result; string authorization; switch (signatureVersionToUse) { case SignatureVersion.SigV4a: var aws4aSigner = new AWS4aSignerCRTWrapper(); var signingResult4a = aws4aSigner.Presign4a(irequest, Config, metrics, immutableCredentials, "s3", arn.IsMRAPArn() ? "*" : ""); result = signingResult4a.PresignedUri; break; case SignatureVersion.SigV4: var aws4Signer = new AWS4PreSignedUrlSigner(); var signingResult4 = aws4Signer.SignRequest(irequest, Config, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = "&" + signingResult4.ForQueryParameters; result = ComposeUrl(irequest).AbsoluteUri + authorization; break; default: // SigV2 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); result = ComposeUrl(irequest).AbsoluteUri + authorization; break; } 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"); 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."); } if (region.Equals(RegionEndpoint.CNNorth1.SystemName, StringComparison.OrdinalIgnoreCase)) { aws4Signing = true; } var immutableCredentials = Credentials.GetCredentials(); var irequest = Marshall(request, immutableCredentials.AccessKey, immutableCredentials.Token, aws4Signing); irequest.Endpoint = DetermineEndpoint(irequest); ProcessRequestHandlers(irequest); 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 { signer.SignRequest(irequest, metrics, immutableCredentials.AccessKey, immutableCredentials.SecretKey); authorization = irequest.Headers[S3QueryParameter.Authorization.ToString()]; authorization = authorization.Substring(authorization.IndexOf(":", StringComparison.Ordinal) + 1); authorization = "&Signature=" + AmazonS3Util.UrlEncode(authorization, false); } Uri url = ComposeUrl(irequest, irequest.Endpoint); 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); }