Cant connect to S3 with nginx

im trying to serve static and media files from amazon S3 bucket but nginx cant connect to it

Here is the error i get

<Error>
<Code>AccessDenied</Code>
<Message>
AWS authentication requires a valid Date or x-amz-date header
</Message>
<RequestId></RequestId>
<HostId></HostId>
</Error>

and my Nginx configuration

server {
listen          80;
server_name     my_elastic_ip;

location = /favicon.ico { access_log off; log_not_found off; }

location / {
    try_files $uri @s3;
}

location @s3 {
    set $s3_bucket          'my_bucket.s3.amazonaws.com';
    set $url_full           '$1';
    set $aws_access_key     'my_access_key';
    set $aws_secret_key     'my_secret_key';

    proxy_http_version      1.1;
    proxy_set_header        Host $s3_bucket;
    proxy_set_header        x-amz-date $date_gmt;
    proxy_set_header        Authorization 'AWS $aws_access_key:$aws_secret_key';
    proxy_hide_header       x-amz-id-2;
    proxy_hide_header       x-amz-request-id;
    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    "Set-Cookie";
    proxy_buffering         off;
    proxy_intercept_errors  on;

    resolver                8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout        10s;
    proxy_pass              http://$s3_bucket/$url_full;
}
}

Edit 1 :

I have solved the probleme replacing the x-amz-date by :

set_by_lua $now         "return ngx.cookie_time(ngx.time())";
proxy_set_header        x-amz-date $now;

You need extra nginx packages, install it with :

sudo apt-get install nginx-extras

now i get this error :

<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>
The request signature we calculated does not match the signature you provided. Check your key and signing method.
</Message>

Edit 2:

To create signature i have added set-misc-nginx-module (https://github.com/openresty/set-misc-nginx-module#installation) to nginx (install nginx optional module)

Then update my nginx configuration to :

server {
listen          80;
server_name     my_ip;

location = /favicon.ico { access_log off; log_not_found off; }

location / {
    try_files $uri @s3;
}

location @s3 {
    set $s3_bucket          'my_bucket';
    set $key                'my_file';
    set $aws_access_key     'my_access_key';
    set $aws_secret_key     'my_secret_key';

    set_by_lua $now         "return ngx.cookie_time(ngx.time())";
    set $aws_signature      '';
    set $string_to_sign     "$request_method\n\n\n\nx-amz-date:$now\n/$s3_bucket/$key";
    set_hmac_sha1           $aws_signature $aws_secret_key $string_to_sign;
    set_encode_base64       $aws_signature $aws_signature;

    proxy_http_version      1.1;
    proxy_set_header        x-amz-date $now;
    proxy_set_header        Authorization 'AWS $aws_access_key:$aws_signature';
    proxy_set_header        Host $s3_bucket.s3.amazonaws.com;
    proxy_hide_header       x-amz-id-2;
    proxy_hide_header       x-amz-request-id;
    proxy_hide_header       Set-Cookie;
    proxy_ignore_headers    "Set-Cookie";
    proxy_buffering         off;
    proxy_intercept_errors  on;

    resolver                8.8.4.4 8.8.8.8 valid=300s;
    resolver_timeout        10s;
    proxy_pass              http://s3.amazonaws.com;
}

}

getting this error :

Status: HTTP/1.1 403 Forbidden

<Code>AccessDenied</Code>
<Message>Access Denied</Message>

Solution 1:

Consider temporarily setting the proxy_pass backend service to either a local service or an HTTP echo service so you can review the full HTTP request being sent to Amazon. (If you use an HTTP echo web service, remove your sensitive bits from the request first!).

Then you debug what's wrong with the Amazon request directly. Once you figure that out, you can make the appropriate changes to Nginx so it sends a valid request header for you.