aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--interface/index.html5
-rw-r--r--interface/js/app/upload.js10
-rw-r--r--lualib/lua_cfg_transform.lua20
-rw-r--r--src/plugins/fuzzy_check.c124
-rw-r--r--src/rspamd_proxy.c12
-rw-r--r--test/functional/cases/120_fuzzy/lib.robot23
-rw-r--r--test/functional/cases/120_fuzzy/read-only.robot14
-rw-r--r--test/functional/cases/120_fuzzy/split-servers.robot18
-rw-r--r--test/functional/cases/120_fuzzy/write-only.robot14
-rw-r--r--test/functional/configs/fuzzy-split-servers.conf97
10 files changed, 297 insertions, 40 deletions
diff --git a/interface/index.html b/interface/index.html
index a759ac48f..8329a74dd 100644
--- a/interface/index.html
+++ b/interface/index.html
@@ -488,7 +488,7 @@
</div>
<div class="col-lg-6">
<div class="card bg-light shadow card-body card p-2">
- <p>Learn Fuzzy storage:</p>
+ <p>Fuzzy hash storage management:</p>
<form class="d-flex">
<div class="d-flex align-items-center">
<label for="fuzzyFlagText">Flag:</label>
@@ -498,7 +498,8 @@
<label for="fuzzyWeightText">Weight:</label>
<input name="fuzzyWeightText" id="fuzzyWeightText" class="form-control ms-1" type="number" value="1"/>
</div>
- <button class="btn btn-warning ms-2 d-flex align-items-center" data-upload="fuzzy" disabled><i class="fas fa-upload me-2"></i>Upload FUZZY</button>
+ <button class="btn btn-warning ms-2 d-flex align-items-center" data-upload="fuzzyadd" disabled><i class="fas fa-circle-plus me-2"></i>Add hash</button>
+ <button class="btn btn-danger ms-2 d-flex align-items-center" data-upload="fuzzydel" disabled><i class="fas fa-trash-can me-2"></i>Delete hash</button>
</form>
</div>
</div>
diff --git a/interface/js/app/upload.js b/interface/js/app/upload.js
index a484a41aa..d85196296 100644
--- a/interface/js/app/upload.js
+++ b/interface/js/app/upload.js
@@ -42,8 +42,10 @@ define(["jquery", "app/common", "app/libft"],
url = "learnspam";
} else if (source === "ham") {
url = "learnham";
- } else if (source === "fuzzy") {
+ } else if (source === "fuzzyadd") {
url = "fuzzyadd";
+ } else if (source === "fuzzydel") {
+ url = "fuzzydel";
} else if (source === "scan") {
url = "checkv2";
}
@@ -245,11 +247,15 @@ define(["jquery", "app/common", "app/libft"],
getFuzzyHashes(data);
} else {
let headers = {};
- if (source === "fuzzy") {
+ if (source === "fuzzyadd") {
headers = {
flag: $("#fuzzyFlagText").val(),
weight: $("#fuzzyWeightText").val()
};
+ } else if (source === "fuzzydel") {
+ headers = {
+ flag: $("#fuzzyFlagText").val(),
+ };
}
uploadText(data, source, headers);
}
diff --git a/lualib/lua_cfg_transform.lua b/lualib/lua_cfg_transform.lua
index 265ca34c0..aaa0c7390 100644
--- a/lualib/lua_cfg_transform.lua
+++ b/lualib/lua_cfg_transform.lua
@@ -198,20 +198,22 @@ end
local function symbol_transform(cfg, k, v)
local groups = cfg:at('group')
- -- first try to find any group where there is a definition of this symbol
- for gr_n, gr in groups:pairs() do
- local symbols = gr:at('symbols')
- if symbols and symbols:at(k) then
- -- We override group symbol with ungrouped symbol
- logger.infox("overriding group symbol %s in the group %s", k, gr_n)
- symbols[k] = lua_util.override_defaults(symbols:at(k):unwrap(), v:unwrap())
- return
+ if groups then
+ -- first try to find any group where there is a definition of this symbol
+ for gr_n, gr in groups:pairs() do
+ local symbols = gr:at('symbols')
+ if symbols and symbols:at(k) then
+ -- We override group symbol with ungrouped symbol
+ logger.infox("overriding group symbol %s in the group %s", k, gr_n)
+ symbols[k] = lua_util.override_defaults(symbols:at(k):unwrap(), v:unwrap())
+ return
+ end
end
end
-- Now check what Rspamd knows about this symbol
local sym = rspamd_config:get_symbol(k)
- if not sym or not sym.group then
+ if groups and (not sym or not sym.group) then
-- Otherwise we just use group 'ungrouped'
if not groups:at('ungrouped') then
groups.ungrouped = {
diff --git a/src/plugins/fuzzy_check.c b/src/plugins/fuzzy_check.c
index 4ed94a141..85ea3b00c 100644
--- a/src/plugins/fuzzy_check.c
+++ b/src/plugins/fuzzy_check.c
@@ -78,7 +78,8 @@ enum fuzzy_rule_mode {
};
struct fuzzy_rule {
- struct upstream_list *servers;
+ struct upstream_list *read_servers; /* Servers for read operations */
+ struct upstream_list *write_servers; /* Servers for write operations */
const char *symbol;
const char *algorithm_str;
const char *name;
@@ -543,22 +544,68 @@ fuzzy_parse_rule(struct rspamd_config *cfg, const ucl_object_t *obj,
}
if ((value = ucl_object_lookup(obj, "servers")) != NULL) {
- rule->servers = rspamd_upstreams_create(cfg->ups_ctx);
- /* pass max_error and revive_time configuration in upstream for fuzzy storage
- * it allows to configure error_rate threshold and upstream dead timer
- */
- rspamd_upstreams_set_limits(rule->servers,
+ rule->read_servers = rspamd_upstreams_create(cfg->ups_ctx);
+ rspamd_upstreams_set_limits(rule->read_servers,
(double) fuzzy_module_ctx->revive_time, NAN, NAN, NAN,
(unsigned int) fuzzy_module_ctx->max_errors, 0);
rspamd_mempool_add_destructor(cfg->cfg_pool,
(rspamd_mempool_destruct_t) rspamd_upstreams_destroy,
- rule->servers);
- if (!rspamd_upstreams_from_ucl(rule->servers, value, DEFAULT_PORT, NULL)) {
+ rule->read_servers);
+ if (!rspamd_upstreams_from_ucl(rule->read_servers, value, DEFAULT_PORT, NULL)) {
msg_err_config("cannot read servers definition");
return -1;
}
+
+ rule->write_servers = rule->read_servers;
+ }
+ else {
+ /* Check for read_servers and write_servers */
+ gboolean has_read = FALSE, has_write = FALSE;
+
+ if ((value = ucl_object_lookup(obj, "read_servers")) != NULL) {
+ rule->read_servers = rspamd_upstreams_create(cfg->ups_ctx);
+ rspamd_upstreams_set_limits(rule->read_servers,
+ (double) fuzzy_module_ctx->revive_time, NAN, NAN, NAN,
+ (unsigned int) fuzzy_module_ctx->max_errors, 0);
+
+ rspamd_mempool_add_destructor(cfg->cfg_pool,
+ (rspamd_mempool_destruct_t) rspamd_upstreams_destroy,
+ rule->read_servers);
+ if (!rspamd_upstreams_from_ucl(rule->read_servers, value, DEFAULT_PORT, NULL)) {
+ msg_err_config("cannot read read_servers definition");
+ return -1;
+ }
+ has_read = TRUE;
+ }
+
+ if ((value = ucl_object_lookup(obj, "write_servers")) != NULL) {
+ rule->write_servers = rspamd_upstreams_create(cfg->ups_ctx);
+ rspamd_upstreams_set_limits(rule->write_servers,
+ (double) fuzzy_module_ctx->revive_time, NAN, NAN, NAN,
+ (unsigned int) fuzzy_module_ctx->max_errors, 0);
+
+ rspamd_mempool_add_destructor(cfg->cfg_pool,
+ (rspamd_mempool_destruct_t) rspamd_upstreams_destroy,
+ rule->write_servers);
+ if (!rspamd_upstreams_from_ucl(rule->write_servers, value, DEFAULT_PORT, NULL)) {
+ msg_err_config("cannot read write_servers definition");
+ return -1;
+ }
+ has_write = TRUE;
+ }
+
+ /* If we have both read and write servers, we don't need the common servers list */
+ if (has_read && !has_write) {
+ /* Use read_servers for all operations */
+ rule->write_servers = rule->read_servers;
+ }
+ else if (has_write && !has_read) {
+ /* Use write_servers for all operations */
+ rule->read_servers = rule->write_servers;
+ }
}
+
if ((value = ucl_object_lookup(obj, "fuzzy_map")) != NULL) {
it = NULL;
while ((cur = ucl_object_iterate(value, &it, true)) != NULL) {
@@ -636,7 +683,7 @@ fuzzy_parse_rule(struct rspamd_config *cfg, const ucl_object_t *obj,
strlen(shingles_key_str), NULL, 0);
rule->shingles_key->len = 16;
- if (rspamd_upstreams_count(rule->servers) == 0) {
+ if (rspamd_upstreams_count(rule->read_servers) == 0) {
msg_err_config("no servers defined for fuzzy rule with name: %s",
rule->name);
return -1;
@@ -898,6 +945,24 @@ int fuzzy_check_module_init(struct rspamd_config *cfg, struct module_ctx **ctx)
0);
rspamd_rcl_add_doc_by_path(cfg,
"fuzzy_check.rule",
+ "List of servers to check (read-only operations)",
+ "read_servers",
+ UCL_STRING,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ rspamd_rcl_add_doc_by_path(cfg,
+ "fuzzy_check.rule",
+ "List of servers to learn (write operations)",
+ "write_servers",
+ UCL_STRING,
+ NULL,
+ 0,
+ NULL,
+ 0);
+ rspamd_rcl_add_doc_by_path(cfg,
+ "fuzzy_check.rule",
"If true then never try to learn this fuzzy storage",
"read_only",
UCL_BOOLEAN,
@@ -1249,7 +1314,7 @@ int fuzzy_check_module_config(struct rspamd_config *cfg, bool validate)
LL_FOREACH(value, cur)
{
- if (ucl_object_lookup(cur, "servers")) {
+ if (ucl_object_lookup_any(cur, "servers", "read_servers", "write_servers", NULL) != NULL) {
/* Unnamed rule */
fuzzy_parse_rule(cfg, cur, NULL, cb_id);
nrules++;
@@ -3398,8 +3463,8 @@ register_fuzzy_client_call(struct rspamd_task *task,
int sock;
if (!rspamd_session_blocked(task->s)) {
- /* Get upstream */
- selected = rspamd_upstream_get(rule->servers, RSPAMD_UPSTREAM_ROUND_ROBIN,
+ /* Get upstream - use read_servers for check operations */
+ selected = rspamd_upstream_get(rule->read_servers, RSPAMD_UPSTREAM_ROUND_ROBIN,
NULL, 0);
if (selected) {
addr = rspamd_upstream_addr_next(selected);
@@ -3526,9 +3591,8 @@ register_fuzzy_controller_call(struct rspamd_http_connection_entry *entry,
int sock;
int ret = -1;
- /* Get upstream */
-
- while ((selected = rspamd_upstream_get_forced(rule->servers,
+ /* Get upstream - use write_servers for learn/unlearn operations */
+ while ((selected = rspamd_upstream_get_forced(rule->write_servers,
RSPAMD_UPSTREAM_SEQUENTIAL, NULL, 0))) {
/* Create UDP socket */
addr = rspamd_upstream_addr_next(selected);
@@ -3542,6 +3606,9 @@ register_fuzzy_controller_call(struct rspamd_http_connection_entry *entry,
rspamd_upstream_fail(selected, TRUE, strerror(errno));
}
else {
+ msg_info_task("fuzzy storage %s (%s rule) is used for write",
+ rspamd_inet_address_to_string_pretty(addr),
+ rule->name);
s =
rspamd_mempool_alloc0(session->pool,
sizeof(struct fuzzy_learn_session));
@@ -3624,6 +3691,7 @@ fuzzy_modify_handler(struct rspamd_http_connection_entry *conn_ent,
PTR_ARRAY_FOREACH(fuzzy_module_ctx->fuzzy_rules, i, rule)
{
if (rule->mode == fuzzy_rule_read_only) {
+ msg_debug_task("skip rule %s as it is read-only", rule->name);
continue;
}
@@ -3733,6 +3801,8 @@ fuzzy_modify_handler(struct rspamd_http_connection_entry *conn_ent,
else {
commands = fuzzy_generate_commands(task, rule, cmd, flag, value,
flags);
+ msg_debug_task("fuzzy command %d for rule %s, flag %d, value %d",
+ cmd, rule->name, flag, value);
if (commands != NULL) {
res = register_fuzzy_controller_call(conn_ent,
rule,
@@ -3898,7 +3968,7 @@ fuzzy_check_send_lua_learn(struct fuzzy_rule *rule,
/* Get upstream */
if (!rspamd_session_blocked(task->s)) {
- while ((selected = rspamd_upstream_get(rule->servers,
+ while ((selected = rspamd_upstream_get(rule->write_servers,
RSPAMD_UPSTREAM_SEQUENTIAL, NULL, 0))) {
/* Create UDP socket */
addr = rspamd_upstream_addr_next(selected);
@@ -4495,9 +4565,21 @@ fuzzy_lua_list_storages(lua_State *L)
lua_setfield(L, -2, "read_only");
/* Push servers */
- lua_createtable(L, rspamd_upstreams_count(rule->servers), 0);
- rspamd_upstreams_foreach(rule->servers, lua_upstream_str_inserter, L);
- lua_setfield(L, -2, "servers");
+ if (rule->read_servers == rule->write_servers) {
+ /* Same servers for both operations */
+ lua_createtable(L, rspamd_upstreams_count(rule->read_servers), 0);
+ rspamd_upstreams_foreach(rule->read_servers, lua_upstream_str_inserter, L);
+ lua_setfield(L, -2, "servers");
+ }
+ else {
+ /* Different servers for read and write */
+ lua_createtable(L, rspamd_upstreams_count(rule->read_servers), 0);
+ rspamd_upstreams_foreach(rule->read_servers, lua_upstream_str_inserter, L);
+ lua_setfield(L, -2, "read_servers");
+ lua_createtable(L, rspamd_upstreams_count(rule->write_servers), 0);
+ rspamd_upstreams_foreach(rule->write_servers, lua_upstream_str_inserter, L);
+ lua_setfield(L, -2, "write_servers");
+ }
/* Push flags */
GHashTableIter it;
@@ -4784,7 +4866,7 @@ fuzzy_lua_ping_storage(lua_State *L)
rspamd_ptr_array_free_hard, addrs);
}
else {
- struct upstream *selected = rspamd_upstream_get(rule_found->servers,
+ struct upstream *selected = rspamd_upstream_get(rule_found->read_servers,
RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0);
addr = rspamd_upstream_addr_next(selected);
}
@@ -4828,4 +4910,4 @@ fuzzy_lua_ping_storage(lua_State *L)
lua_pushboolean(L, TRUE);
return 1;
-} \ No newline at end of file
+}
diff --git a/src/rspamd_proxy.c b/src/rspamd_proxy.c
index 694e87c12..b7decbbcc 100644
--- a/src/rspamd_proxy.c
+++ b/src/rspamd_proxy.c
@@ -1600,8 +1600,8 @@ proxy_backend_master_error_handler(struct rspamd_http_connection *conn, GError *
session->retries++;
msg_info_session("abnormally closing connection from backend: %s, error: %e,"
" retries left: %d",
- rspamd_inet_address_to_string_pretty(
- rspamd_upstream_addr_cur(session->master_conn->up)),
+ session->master_conn->up ? rspamd_inet_address_to_string_pretty(
+ rspamd_upstream_addr_cur(session->master_conn->up)) : "self-scan",
err,
session->ctx->max_retries - session->retries);
rspamd_upstream_fail(bk_conn->up, FALSE, err ? err->message : "unknown");
@@ -1632,8 +1632,8 @@ proxy_backend_master_error_handler(struct rspamd_http_connection *conn, GError *
else {
msg_info_session("retry connection to: %s"
" retries left: %d",
- rspamd_inet_address_to_string(
- rspamd_upstream_addr_cur(session->master_conn->up)),
+ session->master_conn->up ? rspamd_inet_address_to_string(
+ rspamd_upstream_addr_cur(session->master_conn->up)) : "self-scan",
session->ctx->max_retries - session->retries);
}
}
@@ -2216,8 +2216,8 @@ proxy_client_finish_handler(struct rspamd_http_connection *conn,
}
else {
msg_info_session("finished master connection to %s; HTTP code: %d",
- rspamd_inet_address_to_string_pretty(
- rspamd_upstream_addr_cur(session->master_conn->up)),
+ session->master_conn->up ? rspamd_inet_address_to_string_pretty(
+ rspamd_upstream_addr_cur(session->master_conn->up)) : "self-scan",
msg->code);
proxy_backend_close_connection(session->master_conn);
REF_RELEASE(session);
diff --git a/test/functional/cases/120_fuzzy/lib.robot b/test/functional/cases/120_fuzzy/lib.robot
index fda0af54a..a57ecc742 100644
--- a/test/functional/cases/120_fuzzy/lib.robot
+++ b/test/functional/cases/120_fuzzy/lib.robot
@@ -16,6 +16,7 @@ ${RSPAMD_FUZZY_ENCRYPTED_ONLY} false
${RSPAMD_FUZZY_ENCRYPTION_KEY} null
${RSPAMD_FUZZY_INCLUDE} ${RSPAMD_TESTDIR}/configs/empty.conf
${RSPAMD_FUZZY_KEY} null
+${RSPAMD_FUZZY_SERVER_MODE} servers
${RSPAMD_FUZZY_SHINGLES_KEY} null
${RSPAMD_SCOPE} Suite
${SETTINGS_FUZZY_CHECK} ${EMPTY}
@@ -109,6 +110,7 @@ Fuzzy Setup Encrypted
Set Suite Variable ${RSPAMD_FUZZY_ENCRYPTION_KEY} ${RSPAMD_KEY_PUB1}
Set Suite Variable ${RSPAMD_FUZZY_CLIENT_ENCRYPTION_KEY} ${RSPAMD_KEY_PUB1}
Set Suite Variable ${RSPAMD_FUZZY_INCLUDE} ${RSPAMD_TESTDIR}/configs/fuzzy-encryption-key.conf
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} servers
Rspamd Redis Setup
Fuzzy Setup Encrypted Dyn1
@@ -142,6 +144,8 @@ Fuzzy Setup Encrypted Keyed
Fuzzy Setup Plain
[Arguments] ${algorithm}
Set Suite Variable ${RSPAMD_FUZZY_ALGORITHM} ${algorithm}
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} servers
+ Set Suite Variable ${SETTINGS_FUZZY_CHECK} servers = "${RSPAMD_LOCAL_ADDR}:${RSPAMD_PORT_FUZZY}";
Rspamd Redis Setup
Fuzzy Setup Keyed
@@ -149,6 +153,7 @@ Fuzzy Setup Keyed
Set Suite Variable ${RSPAMD_FUZZY_ALGORITHM} ${algorithm}
Set Suite Variable ${RSPAMD_FUZZY_KEY} mYN888sydwLTfE32g2hN
Set Suite Variable ${RSPAMD_FUZZY_SHINGLES_KEY} hXUCgul9yYY3Zlk1QIT2
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} servers
Rspamd Redis Setup
Fuzzy Setup Plain Fasthash
@@ -218,3 +223,21 @@ Fuzzy Multimessage Overwrite Test
FOR ${i} IN @{MESSAGES}
Fuzzy Overwrite Test ${i}
END
+
+Fuzzy Setup Split Servers
+ Set Suite Variable ${RSPAMD_FUZZY_ALGORITHM} siphash
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} split
+ Set Suite Variable ${SETTINGS_FUZZY_CHECK} read_servers = "${RSPAMD_LOCAL_ADDR}:${RSPAMD_PORT_FUZZY}"; write_servers = "${RSPAMD_LOCAL_ADDR}:${RSPAMD_PORT_FUZZY}";
+ Rspamd Redis Setup
+
+Fuzzy Setup Read Only
+ Set Suite Variable ${RSPAMD_FUZZY_ALGORITHM} siphash
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} read_only
+ Set Suite Variable ${SETTINGS_FUZZY_CHECK} read_only = true;
+ Rspamd Redis Setup
+
+Fuzzy Setup Write Only
+ Set Suite Variable ${RSPAMD_FUZZY_ALGORITHM} siphash
+ Set Suite Variable ${RSPAMD_FUZZY_SERVER_MODE} write_only
+ Set Suite Variable ${SETTINGS_FUZZY_CHECK} mode = "write_only";
+ Rspamd Redis Setup
diff --git a/test/functional/cases/120_fuzzy/read-only.robot b/test/functional/cases/120_fuzzy/read-only.robot
new file mode 100644
index 000000000..0c3be7fec
--- /dev/null
+++ b/test/functional/cases/120_fuzzy/read-only.robot
@@ -0,0 +1,14 @@
+*** Settings ***
+Suite Setup Fuzzy Setup Read Only
+Suite Teardown Rspamd Redis Teardown
+Resource lib.robot
+
+*** Test Cases ***
+Fuzzy Add
+ Fuzzy Multimessage Add Test
+
+Fuzzy Fuzzy
+ Fuzzy Multimessage Fuzzy Test
+
+Fuzzy Miss
+ Fuzzy Multimessage Miss Test
diff --git a/test/functional/cases/120_fuzzy/split-servers.robot b/test/functional/cases/120_fuzzy/split-servers.robot
new file mode 100644
index 000000000..41acb23ff
--- /dev/null
+++ b/test/functional/cases/120_fuzzy/split-servers.robot
@@ -0,0 +1,18 @@
+*** Settings ***
+Suite Setup Fuzzy Setup Split Servers
+Suite Teardown Rspamd Redis Teardown
+Resource lib.robot
+Variables ${RSPAMD_TESTDIR}/lib/vars.py
+
+*** Variables ***
+${CONFIG} ${RSPAMD_TESTDIR}/configs/fuzzy-split-servers.conf
+
+*** Test Cases ***
+Fuzzy Add
+ Fuzzy Multimessage Add Test
+
+Fuzzy Fuzzy
+ Fuzzy Multimessage Fuzzy Test
+
+Fuzzy Miss
+ Fuzzy Multimessage Miss Test
diff --git a/test/functional/cases/120_fuzzy/write-only.robot b/test/functional/cases/120_fuzzy/write-only.robot
new file mode 100644
index 000000000..ee017a1d3
--- /dev/null
+++ b/test/functional/cases/120_fuzzy/write-only.robot
@@ -0,0 +1,14 @@
+*** Settings ***
+Suite Setup Fuzzy Setup Write Only
+Suite Teardown Rspamd Redis Teardown
+Resource lib.robot
+
+*** Test Cases ***
+Fuzzy Add
+ Fuzzy Multimessage Add Test
+
+Fuzzy Fuzzy
+ Fuzzy Multimessage Fuzzy Test
+
+Fuzzy Miss
+ Fuzzy Multimessage Miss Test
diff --git a/test/functional/configs/fuzzy-split-servers.conf b/test/functional/configs/fuzzy-split-servers.conf
new file mode 100644
index 000000000..e7c3bb922
--- /dev/null
+++ b/test/functional/configs/fuzzy-split-servers.conf
@@ -0,0 +1,97 @@
+redis {
+ servers = "{= env.REDIS_ADDR =}:{= env.REDIS_PORT =}";
+}
+lua = "{= env.TESTDIR =}/lua/test_coverage.lua";
+options = {
+ filters = "fuzzy_check";
+ pidfile = "{= env.TMPDIR =}/rspamd.pid";
+ control_socket = "{= env.TMPDIR =}/rspamd.sock mode=0600";
+ url_tld = "{= env.TESTDIR =}/../lua/unit/test_tld.dat";
+ dns {
+ retransmits = 10;
+ timeout = 2s;
+ }
+}
+logging = {
+ type = "file",
+ level = "debug"
+ filename = "{= env.TMPDIR =}/rspamd.log"
+}
+metric = {
+ name = "default",
+ actions = {
+ reject = 100500,
+ }
+ unknown_weight = 1
+ symbol {
+ weight = 10.0;
+ name = "{= env.FLAG1_SYMBOL =}";
+ }
+ symbol {
+ weight = -1.0;
+ name = "{= env.FLAG2_SYMBOL =}";
+ }
+}
+
+worker {
+ type = normal
+ bind_socket = "{= env.LOCAL_ADDR =}:{= env.PORT_NORMAL =}";
+ count = 1
+ task_timeout = 60s;
+}
+
+worker {
+ type = controller
+ bind_socket = "{= env.LOCAL_ADDR =}:{= env.PORT_CONTROLLER =}";
+ count = 1
+ secure_ip = ["{= env.LOCAL_ADDR =}"];
+ stats_path = "{= env.TMPDIR =}/stats.ucl";
+}
+
+worker {
+ count = 1;
+ backend = "{= env.FUZZY_BACKEND =}";
+ bind_socket = "{= env.LOCAL_ADDR =}:{= env.PORT_FUZZY =}";
+ type = "fuzzy";
+ hashfile = "{= env.TMPDIR =}/fuzzy.db";
+ allow_update = ["{= env.LOCAL_ADDR =}"];
+ encrypted_only = {= env.FUZZY_ENCRYPTED_ONLY =};
+ keypair {
+ privkey = "{= env.KEY_PVT1 =}";
+ pubkey = "{= env.KEY_PUB1 =}";
+ }
+ dynamic_keys_map = "{= env.TESTDIR =}/configs/maps/fuzzy_keymap.map";
+}
+
+fuzzy_check {
+ min_bytes = 100;
+ timeout = 1s;
+ retransmits = 10;
+
+ rule {
+ min_bytes = 0;
+ min_length = 0;
+ algorithm = "{= env.FUZZY_ALGORITHM =}";
+ read_servers = "{= env.LOCAL_ADDR =}:{= env.PORT_FUZZY =}";
+ write_servers = "{= env.LOCAL_ADDR =}:{= env.PORT_FUZZY =}";
+ symbol = "R_TEST_FUZZY";
+ max_score = 10.0;
+ mime_types = ["application/*"];
+ read_only = false;
+ skip_unknown = true;
+ skip_hashes = "{= env.TMPDIR =}/skip_hash.map";
+ fuzzy_key = {= env.FUZZY_KEY =};
+ fuzzy_shingles_key = {= env.FUZZY_SHINGLES_KEY =};
+.include "{= env.FUZZY_INCLUDE =}";
+ fuzzy_map = {
+ R_TEST_FUZZY_DENIED {
+ max_score = 10.0;
+ flag = {= env.FLAG1_NUMBER =};
+ }
+ R_TEST_FUZZY_WHITE {
+ max_score = 1.0;
+ flag = {= env.FLAG2_NUMBER =};
+ }
+ }
+ }
+}