Is there a way to programmatically handle S3 RequestTimeTooSkewed without changing the local clock

I have read all about this issue on the internet. I understand that the verification is being performed by Amazon and I have no control over it.

The problem is that my program can be installed on hundreds of desktops. I won't get a chance to fix clocks for all these desktops.

I can get the correct time from the server call and calculate the time skews. Is there any time to pass fixed time to Amazon via AWS.NET SDK to avoid timing error?

I've already tried passing request headers - it doesn't work.

putRequest.Headers["Date"] = time;
putRequest.Headers["x-amz-date"] = time;

      

+3


source to share


2 answers


After extensive research, I found the answer. There is a bug in the latest AWS package that will prevent the dates you specified from actually going to S3. So the current API is:

  • Ignores time values ​​passed through API headers. x-amz-date

    Definitely overridden anyway .

  • Creates a signature for the authorizer using the default time from a skewed local clock.

To work around the issue, download the latest AWS SDK source from Amazon. I did the following to ensure that the date is both the x-amz-date

same and taking the values ​​passed to the API:

AWS-sdk-net-master \ AWSSDK_DotNet35 \ Amazon.Runtime \ Pipeline \ HttpHandler \ HttpHandler.cs:

public override void InvokeSync(IExecutionContext executionContext)

      

  • If x-amz-date

    both the date is within the range wrappedRequest.Headers

    and they are not equal, set x-amz-date

    from date.

AWS-SDK-Net-Master \ AWSSDK_DotNet35 \ Amazon.Runtime \ Internal \ Auth \ AWS3Signer.cs:

private static void SignHttp(IRequest request, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey)
private static void SignHttps(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey)

      

  • If it request.Headers

    contains a header x-amz-date

    , set it to the local variable date, otherwise set it to the value passed in the date header.

AWS-SDK-net-master \ AWSSDK_DotNet35 \ Amazon.Runtime \ Internal \ Auth \ S3Signer.cs:



internal void SignRequest(IRequest request, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey)

      

  • If request.Headers

    does not contain a title x-amz-date

    and does contain a date title, set the value from the date title, otherwise just do what it currently does.

AWS-SDK-Net-Master \ AWSSDK_DotNet35 \ Amazon.Runtime \ Internal \ Auth \ CloudFrontSigner.cs:

public override void Sign(IRequest request, ClientConfig clientConfig, RequestMetrics metrics, string awsAccessKeyId, string awsSecretAccessKey)

      

  • If it request.Headers

    contains a header x-amz-date

    , set it to the local variable dateTime, otherwise set it to the value passed in the date header.

IMPORTANT:

After compiling with these code changes, pass the time to the request from the API call using:

//DATE TIME HAS TO BE IN THIS FORMAT
string time = AWSSDKUtils.GetFormattedTimestampRFC822(<time skew in minutes>); 
request.Headers[HeaderKeys.DateHeader] = time;
request.Headers[HeaderKeys.XAmzDateHeader] = time;

      

Time skew can be detected by getting the date from any server and subtracting the local time. Note, however, that the temporary skew changes, especially in virtual machines, and sometimes it gets worse, sometimes it fixes on its own.

+1


source


You can send a request to the completion and response handler, it can set the skew time, then you can send the request. if your time is more than 5-6 months, the Amazon server won't let us do anything, so it doesn't help when the time is more than 5-6 months.



//403 code have clockskew error but 403 also used for some other kind errors
//if error is not skewerror than nothing going to disturb over method**

++ (void)updateTimeSkew:(AmazonServiceRequest *)request withReponse:(AmazonServiceResponse *)response
{

    if (response.httpStatusCode == 403)
    {
        //Getting DateTime from Request
        NSString * requestDateTimeString = [NSString stringWithFormat:@"%@",request.urlRequest.allHTTPHeaderFields[@"Date"]];

        //Converting Datestring into Date Format
        NSDateFormatter * requestDateFormat= [[NSDateFormatter alloc] init];
        requestDateFormat.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss z";
        requestDateFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];

        //Assigning date from dateFormatter
        NSDate *requestDate =[requestDateFormat dateFromString:requestDateTimeString];

        //Converting Datestring into Date Format
        NSDateFormatter *serverTimeformat = [[NSDateFormatter alloc] init];
        serverTimeformat.dateFormat = @"EEE, dd MMM yyyy HH:mm:ss z";
        serverTimeformat.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];

        //Getting Date from amazon response
        NSString *responseDate = [NSString stringWithFormat:@"%@",response.responseHeader[@"Date"]];
        NSDate *serverTime = [requestDateFormat dateFromString:responseDate];

        //Calculating Time differnce
        NSTimeInterval time =  [requestDate timeIntervalSinceDate:serverTime];

        //Setting clockSkew
        [AmazonSDKUtil setRuntimeClockSkew:time];
    }
}

      

0


source







All Articles