Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sign_encode_uri flag and get from dynamic variables for key and secret #9

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 84 additions & 52 deletions ngx_http_aws_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,32 @@ static const EVP_MD* evp_md = NULL;
static void* ngx_http_aws_auth_create_loc_conf(ngx_conf_t *cf);
static char* ngx_http_aws_auth_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
static ngx_int_t register_variable(ngx_conf_t *cf);
static char *
ngx_http_aws_auth_set_s3_bucket(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *
ngx_http_aws_auth_set_chop_prefix(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

typedef struct {
ngx_array_t *lengths;
ngx_array_t *values;
} ngx_http_aws_auth_script_t;

static char *
ngx_http_aws_auth_set_dynamic_variable(ngx_conf_t *cf, ngx_command_t *cmd, ngx_str_t *val, ngx_http_aws_auth_script_t **script);
static char *
ngx_http_aws_auth_set_access_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *
ngx_http_aws_auth_set_secret(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *
ngx_http_aws_auth_set_s3_bucket(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static char *
ngx_http_aws_auth_set_chop_prefix(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

typedef struct {
ngx_str_t access_key;
ngx_str_t secret;
ngx_str_t s3_bucket;
ngx_str_t chop_prefix;
ngx_uint_t add_date;
ngx_flag_t encode_uri;
ngx_http_aws_auth_script_t *access_key_script;
ngx_http_aws_auth_script_t *secret_script;
ngx_http_aws_auth_script_t *s3_bucket_script;
ngx_http_aws_auth_script_t *chop_prefix_script;
} ngx_http_aws_auth_conf_t;
Expand Down Expand Up @@ -65,14 +75,14 @@ static const char *signed_subresources[] = {
static ngx_command_t ngx_http_aws_auth_commands[] = {
{ ngx_string("aws_access_key"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
ngx_http_aws_auth_set_access_key,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_aws_auth_conf_t, access_key),
NULL },

{ ngx_string("aws_secret_key"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
ngx_http_aws_auth_set_secret,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_aws_auth_conf_t, secret),
NULL },
Expand All @@ -91,6 +101,13 @@ static ngx_command_t ngx_http_aws_auth_commands[] = {
offsetof(ngx_http_aws_auth_conf_t, chop_prefix),
NULL },

{ ngx_string("sign_encode_uri"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_aws_auth_conf_t, encode_uri),
NULL },

ngx_null_command
};

Expand Down Expand Up @@ -125,32 +142,31 @@ ngx_module_t ngx_http_aws_auth_module = {
};

static char *
ngx_http_aws_auth_set_s3_bucket(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_aws_auth_set_dynamic_variable(ngx_conf_t *cf, ngx_command_t *cmd, ngx_str_t *retval, ngx_http_aws_auth_script_t **val_script)
{
ngx_http_aws_auth_conf_t *aws_conf = conf;
ngx_http_script_compile_t sc;
ngx_str_t *value;
ngx_uint_t n;
value = cf->args->elts;
n = ngx_http_script_variables_count(&value[1]);

if (n == 0) {
// set s3_bucket as string
aws_conf->s3_bucket.data = value[1].data;
aws_conf->s3_bucket.len = value[1].len;
// set as string
retval->data = value[1].data;
retval->len = value[1].len;
} else {
//add script to compile
aws_conf->s3_bucket_script = ngx_pcalloc(cf->pool, sizeof(ngx_http_aws_auth_script_t));
if (aws_conf->s3_bucket_script == NULL) {
(*val_script) = ngx_pcalloc(cf->pool, sizeof(ngx_http_aws_auth_script_t));
if (val_script == NULL) {
return NGX_CONF_ERROR;
}

ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

sc.cf = cf;
sc.source = &value[1];
sc.lengths = &aws_conf->s3_bucket_script->lengths;
sc.values = &aws_conf->s3_bucket_script->values;
sc.lengths = &((*val_script)->lengths);
sc.values = &((*val_script)->values);
sc.variables = n;
sc.complete_lengths = 1;
sc.complete_values = 1;
Expand All @@ -163,41 +179,33 @@ ngx_http_aws_auth_set_s3_bucket(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}

static char *
ngx_http_aws_auth_set_chop_prefix(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_aws_auth_set_access_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_aws_auth_conf_t *aws_conf = conf;
ngx_http_script_compile_t sc;
ngx_str_t *value;
ngx_uint_t n;
value = cf->args->elts;
n = ngx_http_script_variables_count(&value[1]);
return ngx_http_aws_auth_set_dynamic_variable(cf, cmd, &(aws_conf->access_key), &aws_conf->access_key_script);
}

if (n == 0) {
// set chop_prefix as string
aws_conf->chop_prefix.data = value[1].data;
aws_conf->chop_prefix.len = value[1].len;
} else {
//add script to compile
aws_conf->chop_prefix_script = ngx_pcalloc(cf->pool, sizeof(ngx_http_aws_auth_script_t));
if (aws_conf->chop_prefix_script == NULL) {
return NGX_CONF_ERROR;
}
static char *
ngx_http_aws_auth_set_secret(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_aws_auth_conf_t *aws_conf = conf;
return ngx_http_aws_auth_set_dynamic_variable(cf, cmd, &(aws_conf->secret), &aws_conf->secret_script);
}

ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

sc.cf = cf;
sc.source = &value[1];
sc.lengths = &aws_conf->chop_prefix_script->lengths;
sc.values = &aws_conf->chop_prefix_script->values;
sc.variables = n;
sc.complete_lengths = 1;
sc.complete_values = 1;

if (ngx_http_script_compile(&sc) != NGX_OK) {
return NGX_CONF_ERROR;
}
}
return NGX_CONF_OK;
static char *
ngx_http_aws_auth_set_s3_bucket(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_aws_auth_conf_t *aws_conf = conf;
return ngx_http_aws_auth_set_dynamic_variable(cf, cmd, &(aws_conf->s3_bucket), &aws_conf->s3_bucket_script);
}

static char *
ngx_http_aws_auth_set_chop_prefix(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_aws_auth_conf_t *aws_conf = conf;
return ngx_http_aws_auth_set_dynamic_variable(cf, cmd, &(aws_conf->chop_prefix), &aws_conf->chop_prefix_script);
}


Expand All @@ -210,7 +218,7 @@ ngx_http_aws_auth_create_loc_conf(ngx_conf_t *cf)
if (conf == NULL) {
return NGX_CONF_ERROR;
}

conf->encode_uri = NGX_CONF_UNSET;
return conf;
}

Expand All @@ -226,6 +234,7 @@ ngx_http_aws_auth_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->secret, prev->secret, "");
ngx_conf_merge_str_value(conf->chop_prefix, prev->chop_prefix, "");
ngx_conf_merge_uint_value(conf->add_date, prev->add_date, 0);
ngx_conf_merge_value(conf->encode_uri, prev->encode_uri, 1);

return NGX_CONF_OK;
}
Expand Down Expand Up @@ -351,7 +360,7 @@ ngx_http_arg2(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)
if (ngx_strncasecmp(p, name, len) != 0) {
continue;
}
if (p == r->args.data || *(p - 1) == '&' || (p + len) == last || *(p + len) == '&' || *(p + len) == '=') {
if ((p == r->args.data || *(p - 1) == '&') && ((p + len) == last || *(p + len) == '&' || *(p + len) == '=')) {
if ((p + len) < last && *(p + len) == '=') {
value->data = p + len + 1;
p = ngx_strlchr(p, last, '&');
Expand All @@ -374,9 +383,18 @@ ngx_http_aws_auth_get_canon_resource(ngx_http_request_t *r, ngx_str_t *retstr) {
ngx_http_aws_auth_conf_t *aws_conf;
int uri_len;
aws_conf = ngx_http_get_module_loc_conf(r, ngx_http_aws_auth_module);
u_char *uri = ngx_palloc(r->pool, r->uri.len * 3 + 1); // allow room for escaping
u_char *uri_end = (u_char*) ngx_escape_uri(uri,r->uri.data, r->uri.len, NGX_ESCAPE_URI);
*uri_end = '\0'; // null terminate
u_char *uri, *uri_end;
if (aws_conf->encode_uri) {
ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "sign_encode_uri on: %d", aws_conf->encode_uri);
uri = ngx_palloc(r->pool, r->uri.len * 3 + 1); // allow room for escaping
uri_end = (u_char*) ngx_escape_uri(uri,r->uri.data, r->uri.len, NGX_ESCAPE_URI);
*uri_end = '\0'; // null terminate
} else {
ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, "sign_encode_uri off: %d", aws_conf->encode_uri);
uri = ngx_palloc(r->pool, r->uri.len + 1);
ngx_memcpy(uri, r->uri.data, r->uri.len);
*(uri+r->uri.len) = '\0'; // null terminate
}

if (aws_conf->chop_prefix.len > 0) {
if (!ngx_strncmp(r->uri.data, aws_conf->chop_prefix.data, aws_conf->chop_prefix.len)) {
Expand Down Expand Up @@ -440,10 +458,24 @@ ngx_http_aws_auth_get_canon_resource(ngx_http_request_t *r, ngx_str_t *retstr) {
static ngx_int_t
ngx_http_aws_auth_get_dynamic_variables(ngx_http_request_t *r){
/*
* Get value for s3_bucket and chop_prefix
* Get value for access_key, secret, s3_bucket and chop_prefix
*/
ngx_http_aws_auth_conf_t *aws_conf;
aws_conf = ngx_http_get_module_loc_conf(r, ngx_http_aws_auth_module);
if (aws_conf->access_key_script != NULL){
if (ngx_http_script_run(r, &aws_conf->access_key, aws_conf->access_key_script->lengths->elts, 1,
aws_conf->access_key_script->values->elts) == NULL) {
return NGX_ERROR;
}
aws_conf->access_key.len = aws_conf->access_key.len -1;
}
if (aws_conf->secret_script != NULL){
if (ngx_http_script_run(r, &aws_conf->secret, aws_conf->secret_script->lengths->elts, 1,
aws_conf->secret_script->values->elts) == NULL) {
return NGX_ERROR;
}
aws_conf->secret.len = aws_conf->secret.len -1;
}
if (aws_conf->s3_bucket_script != NULL){
if (ngx_http_script_run(r, &aws_conf->s3_bucket, aws_conf->s3_bucket_script->lengths->elts, 1,
aws_conf->s3_bucket_script->values->elts) == NULL) {
Expand Down Expand Up @@ -618,7 +650,7 @@ ngx_http_aws_auth_variable_s3(ngx_http_request_t *r, ngx_http_variable_value_t *
v->len = ngx_strlen(signature);
v->data = signature;
v->valid = 1;
v->no_cacheable = 0;
v->no_cacheable = 1;
v->not_found = 0;
return NGX_OK;
}
Expand All @@ -631,7 +663,7 @@ ngx_http_aws_auth_variable_date(ngx_http_request_t *r, ngx_http_variable_value_t
v->len = ngx_cached_http_time.len;
v->data = ngx_cached_http_time.data;
v->valid = 1;
v->no_cacheable = 0;
v->no_cacheable = 1;
v->not_found = 0;
aws_conf = ngx_http_get_module_loc_conf(r, ngx_http_aws_auth_module);
//get this varialbe enable add x-amz-date to sign
Expand Down
24 changes: 11 additions & 13 deletions tests/nginx_sampleconf
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
server {
listen 8000;

#location ~ /rewrite/(.*)$ {
# rewrite .* /test1/$1 last;
#}
set $key 4WLAD43EZZ64EPK1CIRO;
set $secret uGA3yy/NJqITgERIVmr9AgUZRBqUjPADvfQoxpKL;
location /test1 {
proxy_pass http://precise64;
aws_access_key 4WLAD43EZZ64EPK1CIRO;
aws_secret_key uGA3yy/NJqITgERIVmr9AgUZRBqUjPADvfQoxpKL;
s3_bucket test1;
chop_prefix /test1;
proxy_set_header Authorization $s3_auth_token;
}
location / {
proxy_pass http://precise64/test1/;
aws_access_key 4WLAD43EZZ64EPK1CIRO;
aws_secret_key uGA3yy/NJqITgERIVmr9AgUZRBqUjPADvfQoxpKL;
aws_access_key $key;
#aws_access_key 4WLAD43EZZ64EPK1CIRO;
aws_secret_key $secret;
#sign_encode_uri off;
s3_bucket test1;
chop_prefix /test1;
proxy_set_header Authorization $s3_auth_token;
proxy_set_header x-amz-date $aws_date;
proxy_pass http://precise64;
}

}

6 changes: 4 additions & 2 deletions tests/test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-

import unittest
from unittest import TestCase
Expand All @@ -12,6 +12,7 @@
#'port': 80,
'access_key':'4WLAD43EZZ64EPK1CIRO',
'secret_key':'uGA3yy/NJqITgERIVmr9AgUZRBqUjPADvfQoxpKL',
#'bucket': 'rewrite',
'bucket': 'test1',
}

Expand Down Expand Up @@ -157,7 +158,8 @@ def test_multipart_upload(self):
class BotoTest(TestCase):
def setUp(self):
self.boto_tester = Tester(s3_cred['host'], s3_cred['port'], s3_cred['access_key'],
s3_cred['secret_key'], s3_cred['bucket'], 'filename.txt', 'filecontentttttt', 'text/html', U_M_LIMIT + 100)
s3_cred['secret_key'], s3_cred['bucket'], "filenamefile.txt", 'filecontentttttt', 'text/html', U_M_LIMIT + 100)
#s3_cred['secret_key'], s3_cred['bucket'], "filename_ żźćŻŹĆŁÓĄaą.txt", 'filecontentttttt', 'text/html', U_M_LIMIT + 100)

#def test_create_bucket(self):
# self.assertEquals(self.boto_tester.create_bucket(), True)
Expand Down