public static void ProcessRequestHandlers(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var config = executionContext.RequestContext.ClientConfig; string accountId; request.Headers.TryGetValue(HeaderKeys.XAmzAccountId, out accountId); if (accountId != null) { if (!IsValidAccountId(accountId)) { throw new AmazonClientException("AccountId can only contain alphanumeric characters and dashes and must be between 1 and 63 characters long."); } request.Headers.Remove(HeaderKeys.XAmzAccountId); var ub = new UriBuilder(EndpointResolver.DetermineEndpoint(config, request)); // Add account id to host ub.Host = string.Concat(accountId, ".", ub.Host); request.Endpoint = ub.Uri; } }
/// /// If the STS regional endpoints environment variable is set to /// regional, then the endpoint created by DetermineEndpoint /// should always be specific to the customer's region /// If it is set to legacy, it should be the default sts /// endpoint for legacy global regions /// public void TestDetermineEndpointStsFlag(StsRegionalEndpointsValue stsRegionalFlag, string region, string expected) { var endpointResolver = new EndpointResolver(); var executionContext = CreateExecutionContextSTS(SetupSTSConfig(RegionEndpoint.GetBySystemName(region), stsRegionalFlag)); Uri endpoint = endpointResolver.DetermineEndpoint(executionContext.RequestContext); Assert.AreEqual(expected, endpoint.ToString()); }
public void TestSuccessfulCall() { var endpointResolver = new EndpointResolver(); var executionContext = CreateExecutionContext(SetupConfig()); Uri endpoint = endpointResolver.DetermineEndpoint(executionContext.RequestContext); Assert.AreEqual(@"https://testprefix.test123-s3.amazonaws.com/", endpoint.ToString()); }
public static void ProcessRequestHandlers(IExecutionContext executionContext) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) IRequest request = executionContext.get_RequestContext().get_Request(); IClientConfig clientConfig = executionContext.get_RequestContext().get_ClientConfig(); if (request.get_Headers().TryGetValue("x-amz-server-side-encryption", out string value) && string.Equals(value, ServerSideEncryptionMethod.AWSKMS.get_Value(), StringComparison.Ordinal)) { request.set_UseSigV4(true); } string bucketName = GetBucketName(request.get_ResourcePath()); if (!string.IsNullOrEmpty(bucketName)) { AmazonS3Config amazonS3Config = clientConfig as AmazonS3Config; if (amazonS3Config == null) { throw new AmazonClientException("Current config object is not of type AmazonS3Config"); } bool flag = IsDnsCompatibleBucketName(bucketName); UriBuilder uriBuilder = new UriBuilder(EndpointResolver.DetermineEndpoint(amazonS3Config, request)); bool flag2 = string.Equals(uriBuilder.Scheme, "http", StringComparison.OrdinalIgnoreCase); if (!amazonS3Config.ForcePathStyle && flag && (flag2 || bucketName.IndexOf('.') < 0)) { uriBuilder.Host = bucketName + "." + uriBuilder.Host; request.set_Endpoint(uriBuilder.Uri); string text = request.get_ResourcePath(); string text2 = "/" + bucketName; if (text.IndexOf(text2, StringComparison.Ordinal) == 0) { text = text.Substring(text2.Length); } request.set_ResourcePath(text); request.set_CanonicalResourcePrefix(text2); } if (amazonS3Config.UseAccelerateEndpoint) { if (!flag || BucketNameContainsPeriod(bucketName)) { 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."); } AmazonWebServiceRequest originalRequest = request.get_OriginalRequest(); if (!UnsupportedAccelerateRequestTypes.Contains(((object)originalRequest).GetType())) { request.set_Endpoint(GetAccelerateEndpoint(bucketName, amazonS3Config)); if (request.get_UseSigV4() && amazonS3Config.get_RegionEndpoint() != null) { request.set_AlternateEndpoint(amazonS3Config.get_RegionEndpoint()); } } } if (flag2) { ValidateHttpsOnlyHeaders(request); } } }
public static void ProcessRequestHandlers(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var config = executionContext.RequestContext.ClientConfig; // If the marshalled request has the SSE header and it is set to KMS, // force SigV4 for this request. // Current operations that may set this header: // CopyObject, CopyPart, InitiateMultipart, PutObject string sseHeaderValue; if (request.Headers.TryGetValue(HeaderKeys.XAmzServerSideEncryptionHeader, out sseHeaderValue) && string.Equals(sseHeaderValue, ServerSideEncryptionMethod.AWSKMS.Value, StringComparison.Ordinal)) { request.UseSigV4 = true; } var bucketName = GetBucketName(request.ResourcePath); if (string.IsNullOrEmpty(bucketName)) return; var s3Config = config as AmazonS3Config; // 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(bucketName); var ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); var isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); if (!s3Config.ForcePathStyle && bucketIsDnsCompatible) { // If using HTTPS, bucketName cannot contain a period if (isHttp || bucketName.IndexOf('.') < 0) { // Add bucket to host ub.Host = string.Concat(bucketName, ".", ub.Host); request.Endpoint = ub.Uri; // 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("/", bucketName); 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); } }
public void TestDisableHostPrefixInjection() { var config = SetupConfig(); config.DisableHostPrefixInjection = true; var endpointResolver = new EndpointResolver(); var executionContext = CreateExecutionContext(config); Uri endpoint = endpointResolver.DetermineEndpoint(executionContext.RequestContext); Assert.AreEqual(@"https://s3.amazonaws.com/", endpoint.ToString()); }
public void TestSignerScope(IClientConfig config, string expectedAuthRegion, string expectedAuthService, string expectedEndpoint) { var signer = new AWS4Signer(); var mock = new Moq.Mock <IRequest>().SetupAllProperties(); var request = mock.Object; mock.SetupGet(x => x.Headers).Returns(new Dictionary <string, string>()); request.Endpoint = EndpointResolver.DetermineEndpoint(config, request); var result = signer.SignRequest(request, config, null, "accessKey", "secretKey"); var scopePieces = result.Scope.Split('/'); // expected to be date/region/service/aws4_request Assert.AreEqual(expectedAuthRegion, scopePieces[1]); Assert.AreEqual(expectedAuthService, scopePieces[2]); Assert.AreEqual(expectedEndpoint, request.Endpoint.Host); }
public void ProcessRequestHandlers(IExecutionContext executionContext) { var request = executionContext.RequestContext.Request; var config = executionContext.RequestContext.ClientConfig; var bucketName = GetBucketName(request.ResourcePath); if (string.IsNullOrEmpty(bucketName)) { return; } var s3Config = config as AmazonS3Config; // 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(bucketName); var ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); if (!s3Config.ForcePathStyle && bucketIsDnsCompatible) { // If using HTTPS, bucketName cannot contain a period if (string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase) || bucketName.IndexOf('.') < 0) { // Add bucket to host ub.Host = string.Concat(bucketName, ".", ub.Host); request.Endpoint = ub.Uri; // 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("/", bucketName); if (resourcePath.IndexOf(canonicalBucketName, StringComparison.Ordinal) == 0) { resourcePath = resourcePath.Substring(canonicalBucketName.Length); } request.ResourcePath = resourcePath; request.CanonicalResourcePrefix = canonicalBucketName; } } }
/// <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); }
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); } }
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 bucketName = GetBucketName(request.ResourcePath); if (string.IsNullOrEmpty(bucketName)) { return; } var s3Config = config as AmazonS3Config; if (s3Config == null) { throw new AmazonClientException("Current config object is not of type AmazonS3Config"); } // 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(bucketName); var ub = new UriBuilder(EndpointResolver.DetermineEndpoint(s3Config, request)); var isHttp = string.Equals(ub.Scheme, "http", StringComparison.OrdinalIgnoreCase); if (!s3Config.ForcePathStyle && bucketIsDnsCompatible) { // If using HTTPS, bucketName cannot contain a period if (isHttp || bucketName.IndexOf('.') < 0) { // Add bucket to host ub.Host = string.Concat(bucketName, ".", ub.Host); request.Endpoint = ub.Uri; // 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("/", bucketName); if (resourcePath.IndexOf(canonicalBucketName, StringComparison.Ordinal) == 0) { resourcePath = resourcePath.Substring(canonicalBucketName.Length); } request.ResourcePath = resourcePath; request.CanonicalResourcePrefix = canonicalBucketName; } } if (s3Config.UseAccelerateEndpoint) { // Validate if bucket name is accelerate compatible and enable acceleration by using // Accelerate endpoint for this request if (!bucketIsDnsCompatible || BucketNameContainsPeriod(bucketName)) { 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(bucketName, s3Config); if (request.UseSigV4 && s3Config.RegionEndpoint != null) { request.AlternateEndpoint = s3Config.RegionEndpoint; } } } // Some parameters should not be sent over HTTP, just HTTPS if (isHttp) { ValidateHttpsOnlyHeaders(request); } }
/// <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); }
protected virtual void PreInvoke(IExecutionContext executionContext) { var originalRequest = executionContext.RequestContext.OriginalRequest; var request = executionContext.RequestContext.Request; var copySnapshotRequest = originalRequest as CopySnapshotRequest; if (copySnapshotRequest != null) { request.AlternateEndpoint = RegionEndpoint.GetBySystemName(copySnapshotRequest.DestinationRegion); request.Endpoint = EndpointResolver.DetermineEndpoint(executionContext.RequestContext.ClientConfig, request); return; } var requestSpotInstancesRequest = originalRequest as RequestSpotInstancesRequest; if (requestSpotInstancesRequest != null) { if (requestSpotInstancesRequest.LaunchSpecification != null) { if (requestSpotInstancesRequest.LaunchSpecification.AllSecurityGroups != null) { int count = 1; foreach (var group in requestSpotInstancesRequest.LaunchSpecification.AllSecurityGroups) { if (group != null && group.GroupId != null) { var key = "LaunchSpecification.SecurityGroupId." + count++; request.Parameters[key] = group.GroupId; } } } if (requestSpotInstancesRequest.LaunchSpecification.SecurityGroups != null) { int count = 1; foreach (var group in requestSpotInstancesRequest.LaunchSpecification.SecurityGroups) { var key = "LaunchSpecification.SecurityGroup." + count++; request.Parameters[key] = group; } } } if (request.Parameters.ContainsKey("LaunchSpecification.Monitoring")) { var val = request.Parameters["LaunchSpecification.Monitoring"]; request.Parameters.Remove("LaunchSpecification.Monitoring"); request.Parameters.Add("LaunchSpecification.Monitoring.Enabled", val); } var keysToRemove = new List <string>(); foreach (var parameter in request.Parameters.Keys) { if (parameter.StartsWith("LaunchSpecification.GroupSet.", StringComparison.Ordinal)) { keysToRemove.Add(parameter); } } foreach (var key in keysToRemove) { request.Parameters.Remove(key); } } }
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); } }