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

feat(module): add a new directive for content validation #34

Merged
merged 71 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
95a43c3
validation_tag
chronolaw May 10, 2023
8d916de
ngx_lua_resty_lmdb_validate
chronolaw May 10, 2023
63a00af
ngx_lua_resty_lmdb_validate
chronolaw May 10, 2023
c581ddb
clean
chronolaw May 10, 2023
e789763
ngx_lua_resty_lmdb_assert
chronolaw May 10, 2023
f6c178d
fix crash in cipher
chronolaw May 10, 2023
02a107e
ngx_lua_resty_lmdb_ngx_cycle
chronolaw May 10, 2023
d788efd
clear init_cycle
chronolaw May 10, 2023
a2e3a4e
remove some redundant code
chronolaw May 10, 2023
43394bc
MDB_CRYPTO_FAIL
chronolaw May 11, 2023
6aff59d
t/10-validation-tag.t
chronolaw May 11, 2023
8828ab2
10-validation-tag-cipher.t
chronolaw May 11, 2023
0eb88fb
more tests
chronolaw May 11, 2023
d5db7fa
clean
chronolaw May 11, 2023
50524ec
typo fix
chronolaw May 11, 2023
e464e6b
remove cipher related code
chronolaw May 22, 2023
de0a2a7
debug log
chronolaw May 23, 2023
641cac0
add assert
chronolaw May 30, 2023
abcb5a9
ngx_lua_resty_lmdb_write_tag
chronolaw Jul 4, 2023
f7847d0
remove if validation failed
chronolaw Jul 4, 2023
41a1eae
style lint
chronolaw Jul 14, 2023
9759cd7
change ngx_lua_resty_lmdb_remove_files
chronolaw Aug 24, 2023
fe98715
compare value.mv_size
chronolaw Sep 3, 2023
3ae4cf3
readme
chronolaw Sep 13, 2023
02f1eed
typo fix
chronolaw Sep 13, 2023
db76a57
validation_tag
chronolaw May 10, 2023
d64ab66
ngx_lua_resty_lmdb_validate
chronolaw May 10, 2023
abc9d2f
ngx_lua_resty_lmdb_validate
chronolaw May 10, 2023
27154eb
clean
chronolaw May 10, 2023
e43364e
ngx_lua_resty_lmdb_assert
chronolaw May 10, 2023
20e8076
fix crash in cipher
chronolaw May 10, 2023
a643bda
ngx_lua_resty_lmdb_ngx_cycle
chronolaw May 10, 2023
45a9565
clear init_cycle
chronolaw May 10, 2023
7c60621
remove some redundant code
chronolaw May 10, 2023
03e21dd
MDB_CRYPTO_FAIL
chronolaw May 11, 2023
83af2af
t/10-validation-tag.t
chronolaw May 11, 2023
c4fce31
10-validation-tag-cipher.t
chronolaw May 11, 2023
5c70fa6
more tests
chronolaw May 11, 2023
99a3ee7
clean
chronolaw May 11, 2023
f05a587
typo fix
chronolaw May 11, 2023
fdaed44
remove cipher related code
chronolaw May 22, 2023
47a2f57
debug log
chronolaw May 23, 2023
43bdcf9
add assert
chronolaw May 30, 2023
471e8d3
ngx_lua_resty_lmdb_write_tag
chronolaw Jul 4, 2023
6cf82c2
remove if validation failed
chronolaw Jul 4, 2023
a648a51
style lint
chronolaw Jul 14, 2023
c250d0c
change ngx_lua_resty_lmdb_remove_files
chronolaw Aug 24, 2023
39064f3
compare value.mv_size
chronolaw Sep 3, 2023
84fb156
readme
chronolaw Sep 13, 2023
5426fca
typo fix
chronolaw Sep 13, 2023
f934bab
print validation_tag when enabled
chronolaw Nov 13, 2023
0116474
change log messages
chronolaw Nov 13, 2023
9dfddbf
fix tests
chronolaw Nov 13, 2023
6d46cc9
Merge branch 'feat/version_detect' of github.com:Kong/lua-resty-lmdb …
chronolaw Nov 13, 2023
56e68b3
tests
chronolaw Nov 13, 2023
47f6ff3
clean temp var
chronolaw Nov 13, 2023
ad29229
key string
chronolaw Nov 13, 2023
d34470b
unnamed db
chronolaw Nov 13, 2023
55f4595
remove validation_key
chronolaw Nov 13, 2023
b3288c4
test clean
chronolaw Nov 13, 2023
38cf3a6
readme
chronolaw Nov 13, 2023
11f3713
debug log
chronolaw Nov 13, 2023
46a64bc
tests
chronolaw Nov 13, 2023
fc3f90c
README.md
chronolaw Nov 13, 2023
c5308d4
readme
chronolaw Nov 14, 2023
33a56a9
unamed db null
chronolaw Nov 14, 2023
5eba04a
remove disabled log
chronolaw Nov 14, 2023
4f3e176
fix goto failed error
chronolaw Nov 14, 2023
45a4e5a
log message
chronolaw Nov 14, 2023
53c4a69
Update README.md
dndx Nov 14, 2023
e7519cf
Update src/ngx_lua_resty_lmdb_module.c
dndx Nov 14, 2023
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
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Table of Contents
* [lmdb_environment_path](#lmdb_environment_path)
* [lmdb_max_databases](#lmdb_max_databases)
* [lmdb_map_size](#lmdb_map_size)
* [lmdb_validation_tag](#lmdb_validation_tag)
* [Copyright and license](#copyright-and-license)

## APIs
Expand Down Expand Up @@ -228,6 +229,23 @@ Set the size of the memory map, the default value is `1048576`(1MB).

[Back to TOC](#table-of-contents)

### lmdb_validation_tag

**syntax:** *lmdb_validation_tag value;*

chronolaw marked this conversation as resolved.
Show resolved Hide resolved
**default:** *none*

**context:** *main*

Set a content validation tag into LMDB.
When LMDB starts, it will check the tag value,
if the value is different from the directive value,
the content of LMDB will be cleaned up.

When this directive is not set, tag validation is disabled.

[Back to TOC](#table-of-contents)

## Copyright and license

Copyright (c) 2021-2022 Kong, Inc.
Expand Down
189 changes: 184 additions & 5 deletions src/ngx_lua_resty_lmdb_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#define NGX_LUA_RESTY_LMDB_DIR_MODE 0700


#define NGX_LUA_RESTY_LMDB_VALIDATION_KEY "validation_tag"


static ngx_str_t ngx_lua_resty_lmdb_file_names[] = {
ngx_string("/data.mdb"),
ngx_string("/lock.mdb"),
Expand Down Expand Up @@ -42,6 +45,13 @@ static ngx_command_t ngx_lua_resty_lmdb_commands[] = {
offsetof(ngx_lua_resty_lmdb_conf_t, map_size),
NULL },

{ ngx_string("lmdb_validation_tag"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
0,
offsetof(ngx_lua_resty_lmdb_conf_t, validation_tag),
NULL },

ngx_null_command
};

Expand Down Expand Up @@ -150,16 +160,14 @@ ngx_lua_resty_lmdb_create_env(ngx_cycle_t *cycle,


static ngx_int_t
ngx_lua_resty_lmdb_remove_files(ngx_cycle_t *cycle, ngx_path_t *path)
ngx_lua_resty_lmdb_remove_files(ngx_cycle_t *cycle, ngx_lua_resty_lmdb_conf_t *lcf)
{
ngx_file_info_t fi;

u_char name_buf[NGX_MAX_PATH];
ngx_str_t *names = ngx_lua_resty_lmdb_file_names;
ngx_str_t *name;

ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"LMDB database is corrupted or incompatible, removing");
ngx_path_t *path = lcf->env_path;

if (ngx_file_info(path->name.data, &fi) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_errno,
Expand Down Expand Up @@ -233,7 +241,10 @@ ngx_lua_resty_lmdb_open_file(ngx_cycle_t *cycle,
mdb_env_close(lcf->env);
lcf->env = NULL;

if (ngx_lua_resty_lmdb_remove_files(cycle, lcf->env_path) != NGX_OK) {
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"LMDB database is corrupted or incompatible, removing");

if (ngx_lua_resty_lmdb_remove_files(cycle, lcf) != NGX_OK) {
return NGX_ERROR;
}

Expand Down Expand Up @@ -363,6 +374,149 @@ ngx_lua_resty_lmdb_verify_file_status(ngx_cycle_t *cycle,
}


static ngx_int_t
ngx_lua_resty_lmdb_validate(ngx_cycle_t *cycle,
ngx_lua_resty_lmdb_conf_t *lcf)
{
int rc;
MDB_dbi dbi;
MDB_val key;
MDB_val value;
MDB_txn *txn = NULL;

/* check tag value in lmdb */

if (lcf->validation_tag.data == NULL) {
return NGX_OK;
}

ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"LMDB validation enabled, using validation tag: \"%V\"",
&lcf->validation_tag);

ngx_lua_resty_lmdb_assert(lcf->validation_tag.data);

rc = mdb_txn_begin(lcf->env, NULL, 0, &txn);
if (rc != 0) {
ngx_log_error(NGX_LOG_CRIT, cycle->log, 0,
"unable to open LMDB transaction: %s",
mdb_strerror(rc));
return NGX_ERROR;
}

ngx_lua_resty_lmdb_assert(txn);

rc = mdb_dbi_open(txn, NULL, MDB_CREATE, &dbi);
if (rc != 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unable to open LMDB database: %s",
mdb_strerror(rc));
goto failed;
}

key.mv_size = sizeof(NGX_LUA_RESTY_LMDB_VALIDATION_KEY) - 1;
key.mv_data = NGX_LUA_RESTY_LMDB_VALIDATION_KEY;

rc = mdb_get(txn, dbi, &key, &value);
if (rc == 0) {
/* key found, compare with validation_tag value */
if (lcf->validation_tag.len == value.mv_size &&
ngx_strncmp(lcf->validation_tag.data,
value.mv_data, value.mv_size) == 0) {

mdb_txn_abort(txn);
return NGX_OK;
}

ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"LMDB validation tag \"%*s\" did not match configured tag \"%V\"",
value.mv_size, value.mv_data,
&lcf->validation_tag);

} else if (rc == MDB_NOTFOUND) {
ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"LMDB validation tag does not exist");

} else {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unable to get LMDB validation tag: %s",
mdb_strerror(rc));
}

failed:

mdb_txn_abort(txn);
return NGX_ERROR;
}


static ngx_int_t
ngx_lua_resty_lmdb_write_tag(ngx_cycle_t *cycle,
ngx_lua_resty_lmdb_conf_t *lcf)
{
int rc;
MDB_dbi dbi;
MDB_val key;
MDB_val value;
MDB_txn *txn = NULL;

ngx_lua_resty_lmdb_assert(lcf->validation_tag.data);

rc = mdb_txn_begin(lcf->env, NULL, 0, &txn);
if (rc != 0) {
ngx_log_error(NGX_LOG_CRIT, cycle->log, 0,
"unable to open LMDB transaction: %s",
mdb_strerror(rc));
return NGX_ERROR;
}

ngx_lua_resty_lmdb_assert(txn);

rc = mdb_dbi_open(txn, NULL, MDB_CREATE, &dbi);
if (rc != 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unable to open LMDB database: %s",
mdb_strerror(rc));
goto failed;
}

/* set tag value to lmdb db */

key.mv_size = sizeof(NGX_LUA_RESTY_LMDB_VALIDATION_KEY) - 1;
key.mv_data = NGX_LUA_RESTY_LMDB_VALIDATION_KEY;

value.mv_size = lcf->validation_tag.len;
value.mv_data = lcf->validation_tag.data;

rc = mdb_put(txn, dbi, &key, &value, 0);
if (rc != 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unable to set LMDB validation tag: %s",
mdb_strerror(rc));
goto failed;
}

rc = mdb_txn_commit(txn);
if (rc != 0) {
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"unable to commit validation tag into LMDB: %s",
mdb_strerror(rc));
return NGX_ERROR;
}

ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"set LMDB validation tag: \"%V\"",
&lcf->validation_tag);

return NGX_OK;

failed:

mdb_txn_abort(txn);
return NGX_ERROR;
}


static ngx_int_t ngx_lua_resty_lmdb_init(ngx_cycle_t *cycle)
{
ngx_lua_resty_lmdb_conf_t *lcf;
Expand All @@ -380,6 +534,31 @@ static ngx_int_t ngx_lua_resty_lmdb_init(ngx_cycle_t *cycle)
return NGX_ERROR;
}

/* check lmdb validation tag */

if (ngx_lua_resty_lmdb_validate(cycle, lcf) != NGX_OK) {
ngx_lua_resty_lmdb_close_file(cycle, lcf);
chronolaw marked this conversation as resolved.
Show resolved Hide resolved

ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"LMDB validation tag mismatch, wiping the database");

/* remove lmdb files to clean data */
if (ngx_lua_resty_lmdb_remove_files(cycle, lcf) != NGX_OK) {
return NGX_ERROR;
}

/* open lmdb file again */
if (ngx_lua_resty_lmdb_open_file(cycle, lcf, 1) != NGX_OK) {
return NGX_ERROR;
}

/* write tag into lmdb */
if (ngx_lua_resty_lmdb_write_tag(cycle, lcf) != NGX_OK) {
ngx_lua_resty_lmdb_close_file(cycle, lcf);
return NGX_ERROR;
}
}

if (ngx_lua_resty_lmdb_close_file(cycle, lcf) != NGX_OK) {
return NGX_ERROR;
}
Expand Down
2 changes: 2 additions & 0 deletions src/ngx_lua_resty_lmdb_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct ngx_lua_resty_lmdb_conf_s {
size_t map_size;
MDB_env *env;
MDB_txn *ro_txn;

ngx_str_t validation_tag;
};


Expand Down
Loading
Loading