1.support and_conditions and or_conditions in rule

2.all test case success except MaatCmd.* in maat_framework_gtest
This commit is contained in:
root
2024-10-12 07:28:26 +00:00
parent 02a2acf051
commit 586f1c11b2
7 changed files with 355 additions and 300 deletions

View File

@@ -2,7 +2,7 @@ variables:
GIT_STRATEGY: "clone"
BUILD_IMAGE_CENTOS8: "git.mesalab.cn:7443/mesa_platform/build-env:rockylinux"
BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/
INSTALL_DEPENDENCY_LIBRARY: framework_env openssl-devel libasan libfieldstat4-devel libuuid
INSTALL_DEPENDENCY_LIBRARY: framework_env openssl-devel libasan libfieldstat4-devel libuuid-devel
stages:
- build

View File

@@ -214,6 +214,72 @@ static void object_info_free(struct object_info *object_name_map)
}
}
static void convert_condition(struct object_info *object_name_map, cJSON *condition, cJSON *top_items, int *object_gen_id, int *item_gen_id)
{
cJSON *object_uuid_array = cJSON_CreateArray();
cJSON *object_name = cJSON_GetObjectItem(condition, "object_name");
cJSON *object_uuid = cJSON_GetObjectItem(condition, "object_uuid");
if (object_name && object_uuid) {
object_info_add(object_name_map, object_name->valuestring, object_uuid->valuestring);
}
if (object_uuid) {
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(object_uuid->valuestring));
} else if (object_name) {
struct object_info *object_info = object_info_find(object_name_map, object_name->valuestring);
if (object_info) {
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(object_info->object_uuid));
}
}
cJSON *object_array = cJSON_GetObjectItem(condition, "objects");
cJSON *tmp_object = NULL;
cJSON_ArrayForEach(tmp_object, object_array) {//convert objects in condition
//find items, generate item_id and object_id
cJSON *object_id_obj = cJSON_GetObjectItem(tmp_object, "uuid");
cJSON *object_name_obj = cJSON_GetObjectItem(tmp_object, "object_name");
cJSON *items = cJSON_GetObjectItem(tmp_object, "items");
cJSON *item = NULL;
char obj_uuid_str[UUID_STR_LEN];
memset(obj_uuid_str, 0, sizeof(obj_uuid_str));
if (object_id_obj != NULL) {
snprintf(obj_uuid_str, sizeof(obj_uuid_str), "%s", object_id_obj->valuestring);
} else {
snprintf(obj_uuid_str, sizeof(obj_uuid_str), "00000000-0000-0000-0000-00000000%d", (*object_gen_id)++);
}
if (object_name_obj) {
object_info_add(object_name_map, object_name_obj->valuestring, obj_uuid_str);
}
cJSON_ArrayForEach(item, items) {
cJSON *table_name = cJSON_GetObjectItem(item, "table_name");
cJSON *tmp_item = cJSON_CreateObject();
cJSON_AddItemToObject(tmp_item, "table_name", cJSON_CreateString(table_name->valuestring));
cJSON *dup = cJSON_Duplicate(cJSON_GetObjectItem(item, "table_content"), 1);
if (cJSON_GetObjectItem(dup, "uuid") == NULL) {
char uuid_str[UUID_STR_LEN];
snprintf(uuid_str, sizeof(uuid_str), "00000000-0000-0000-0000-00000000%d", (*item_gen_id)++);
cJSON_AddStringToObject(dup, "uuid", uuid_str);
}
cJSON_AddStringToObject(dup, "object_uuid", obj_uuid_str);
cJSON_AddItemToObject(tmp_item, "table_content", dup);
cJSON_AddItemToArray(top_items, tmp_item);
}
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(obj_uuid_str));
}
//replace object content with object_id
cJSON_DeleteItemFromObject(condition, "objects");
cJSON_AddItemToObject(condition, "object_uuids", object_uuid_array);
return;
}
void convert_maat_json_rule(cJSON **json_root, unsigned char *json_buff)
{
*json_root = cJSON_Parse((const char *)json_buff);
@@ -307,74 +373,29 @@ void convert_maat_json_rule(cJSON **json_root, unsigned char *json_buff)
*/
cJSON *tmp_rule = NULL;
cJSON_ArrayForEach(tmp_rule, rules) {
cJSON *tmp_condition = NULL;
cJSON *condition_array = cJSON_GetObjectItem(tmp_rule, "conditions");
cJSON_ArrayForEach(tmp_condition, condition_array) {
cJSON *tmp_object = NULL;
cJSON *object_uuid_array = cJSON_CreateArray();
cJSON *tmp_and_condition = NULL;
cJSON *condition_array = cJSON_GetObjectItem(tmp_rule, "and_conditions");
cJSON_ArrayForEach(tmp_and_condition, condition_array) {
cJSON *negate_option = cJSON_GetObjectItem(tmp_condition, "negate_option");
cJSON *negate_option = cJSON_GetObjectItem(tmp_and_condition, "negate_option");
if (negate_option == NULL) {
cJSON_AddBoolToObject(tmp_condition, "negate_option", 0);
cJSON_AddBoolToObject(tmp_and_condition, "negate_option", 0);
}
cJSON *object_name = cJSON_GetObjectItem(tmp_condition, "object_name");
cJSON *object_uuid = cJSON_GetObjectItem(tmp_condition, "object_uuid");
if (object_name && object_uuid) {
object_info_add(object_name_map, object_name->valuestring, object_uuid->valuestring);
cJSON *or_conditions = cJSON_GetObjectItem(tmp_and_condition, "or_conditions");
if (or_conditions) {
cJSON *tmp_or_condition = NULL;
cJSON_ArrayForEach(tmp_or_condition, or_conditions) {
convert_condition(object_name_map, tmp_or_condition, top_items, &object_gen_id, &item_gen_id);
}
} else {
cJSON *tmp_or_condition = cJSON_Duplicate(tmp_and_condition, 1);
convert_condition(object_name_map, tmp_or_condition, top_items, &object_gen_id, &item_gen_id);
or_conditions = cJSON_CreateArray();
cJSON_AddItemToArray(or_conditions, tmp_or_condition);
cJSON_AddItemToObject(tmp_and_condition, "or_conditions", or_conditions);
}
if (object_uuid) {
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(object_uuid->valuestring));
} else if (object_name) {
struct object_info *object_info = object_info_find(object_name_map, object_name->valuestring);
if (object_info) {
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(object_info->object_uuid));
}
}
cJSON *object_array = cJSON_GetObjectItem(tmp_condition, "objects");
cJSON_ArrayForEach(tmp_object, object_array) {//convert objects in rule
//find items, generate item_id and object_id
cJSON *object_id_obj = cJSON_GetObjectItem(tmp_object, "uuid");
cJSON *object_name_obj = cJSON_GetObjectItem(tmp_object, "object_name");
cJSON *items = cJSON_GetObjectItem(tmp_object, "items");
cJSON *item = NULL;
char obj_uuid_str[UUID_STR_LEN];
memset(obj_uuid_str, 0, sizeof(obj_uuid_str));
if (object_id_obj != NULL) {
snprintf(obj_uuid_str, sizeof(obj_uuid_str), "%s", object_id_obj->valuestring);
} else {
snprintf(obj_uuid_str, sizeof(obj_uuid_str), "00000000-0000-0000-0000-00000000%d", object_gen_id++);
}
if (object_name_obj) {
object_info_add(object_name_map, object_name_obj->valuestring, obj_uuid_str);
}
cJSON_ArrayForEach(item, items) {
cJSON *table_name = cJSON_GetObjectItem(item, "table_name");
cJSON *tmp_item = cJSON_CreateObject();
cJSON_AddItemToObject(tmp_item, "table_name", cJSON_CreateString(table_name->valuestring));
cJSON *dup = cJSON_Duplicate(cJSON_GetObjectItem(item, "table_content"), 1);
if (cJSON_GetObjectItem(dup, "uuid") == NULL) {
char uuid_str[UUID_STR_LEN];
snprintf(uuid_str, sizeof(uuid_str), "00000000-0000-0000-0000-00000000%d", item_gen_id++);
cJSON_AddStringToObject(dup, "uuid", uuid_str);
}
cJSON_AddStringToObject(dup, "object_uuid", obj_uuid_str);
cJSON_AddItemToObject(tmp_item, "table_content", dup);
cJSON_AddItemToArray(top_items, tmp_item);
}
cJSON_AddItemToArray(object_uuid_array, cJSON_CreateString(obj_uuid_str));
}
//replace object content with object_id
cJSON_DeleteItemFromObject(tmp_condition, "objects");
cJSON_AddItemToObject(tmp_condition, "object_uuids", object_uuid_array);
}
}

View File

@@ -99,9 +99,7 @@ struct condition_literal {
struct rule_condition {
long long condition_id;
uuid_t object_uuids[MAX_OBJECT_CNT];
int object_cnt;
char attribute_name[MAX_ATTR_NAME_LEN];
UT_array *literals;
char negate_option; // 1 byte
char in_use; // 1 byte
char pad[6]; // for 8 bytes alignment
@@ -153,6 +151,7 @@ struct rule_compile_state {
};
UT_icd ut_condition_id_icd = {sizeof(long long), NULL, NULL, NULL};
UT_icd ut_condition_literal_icd = {sizeof(struct condition_literal), NULL, NULL, NULL};
UT_icd ut_rule_object_uuid_icd = {sizeof(uuid_t), NULL, NULL, NULL};
UT_icd ut_maat_hit_object_icd = {sizeof(struct maat_hit_object), NULL, NULL, NULL};
UT_icd ut_hit_path_icd = {sizeof(struct internal_hit_path), NULL, NULL, NULL};
@@ -181,6 +180,11 @@ static void maat_rule_free(struct maat_rule *rule)
for (int i = 0; i < MAX_ITEMS_PER_BOOL_EXPR; i++) {
condition = rule->conditions + i;
if (condition->literals != NULL) {
utarray_free(condition->literals);
condition->literals = NULL;
}
condition->in_use = 0;
condition->condition_id = 0;
}
@@ -231,7 +235,7 @@ static struct maat_rule *maat_rule_new(struct rule_runtime *rule_rt, struct rule
struct maat_rule *rule = ALLOC(struct maat_rule, 1);
struct log_handle *logger = rule_rt->logger;
cJSON *tmp_obj = NULL;
cJSON *conditions = NULL;
cJSON *conditions_obj = NULL;
cJSON *table_json = cJSON_Parse(table_line);
int table_id = table_manager_get_table_id(schema->ref_tbl_mgr, table_name);
@@ -247,19 +251,20 @@ static struct maat_rule *maat_rule_new(struct rule_runtime *rule_rt, struct rule
uuid_copy(rule->rule_uuid, rule_uuid);
for(int i = 0; i < MAX_ITEMS_PER_BOOL_EXPR; i++) {
utarray_new(rule->conditions[i].literals, &ut_condition_literal_icd);
rule->conditions[i].in_use = 0;
rule->conditions[i].condition_id = 0;
}
conditions = cJSON_GetObjectItem(table_json, "conditions");
if (conditions == NULL || conditions->type != cJSON_Array) {
conditions_obj = cJSON_GetObjectItem(table_json, "and_conditions");
if (conditions_obj == NULL || conditions_obj->type != cJSON_Array) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> has no conditions or not array format",
"[%s:%d] table: <%s> has no and_conditions or not array format",
__FUNCTION__, __LINE__, table_name);
goto error;
}
rule->condition_num = cJSON_GetArraySize(conditions);
rule->condition_num = cJSON_GetArraySize(conditions_obj);
if (rule->condition_num > MAX_ITEMS_PER_BOOL_EXPR) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> condition_num:%d exceed maximum:%d",
@@ -268,25 +273,9 @@ static struct maat_rule *maat_rule_new(struct rule_runtime *rule_rt, struct rule
}
for (int i = 0; i < rule->condition_num; i++) {
cJSON *condition_obj = cJSON_GetArrayItem(conditions, i);
cJSON *condition_obj = cJSON_GetArrayItem(conditions_obj, i);
struct rule_condition *condition = rule->conditions + i;
tmp_obj = cJSON_GetObjectItem(condition_obj, "attribute_name");
if (tmp_obj == NULL || tmp_obj->type != cJSON_String) {
log_fatal(rule_rt->logger, MODULE_RULE,
"[%s:%d] table: <%s> has no attribute_name or not string format",
__FUNCTION__, __LINE__, table_name);
goto error;
}
if (strlen(tmp_obj->valuestring) >= sizeof(condition->attribute_name)) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> attribute_name:%s length exceed maximum:%d",
__FUNCTION__, __LINE__, table_name, tmp_obj->valuestring, sizeof(condition->attribute_name));
goto error;
}
snprintf(condition->attribute_name, sizeof(condition->attribute_name), "%s", tmp_obj->valuestring);
tmp_obj = cJSON_GetObjectItem(condition_obj, "negate_option");
if (tmp_obj) {
if (tmp_obj->type == cJSON_True) {
@@ -299,30 +288,55 @@ static struct maat_rule *maat_rule_new(struct rule_runtime *rule_rt, struct rule
__FUNCTION__, __LINE__, table_name, tmp_obj->valuestring);
goto error;
}
}
if (condition->negate_option == CONDITION_NEGATE_OPTION_SET) {
int ret = validate_table_not_condition(rule_rt, schema->ref_tbl_mgr, condition->attribute_name, MAAT_OP_ADD, logger);
if (ret < 0) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> validate negate_option failed, line: %s",
__FUNCTION__, __LINE__, table_name, table_line);
goto error;
}
}
tmp_obj = cJSON_GetObjectItem(condition_obj, "object_uuids");
if (tmp_obj && tmp_obj->type == cJSON_Array) {
int n_object_ids = cJSON_GetArraySize(tmp_obj);
cJSON *or_conditions_obj = cJSON_GetObjectItem(condition_obj, "or_conditions");
cJSON *literal_obj = NULL;
cJSON_ArrayForEach(literal_obj, or_conditions_obj) {
struct condition_literal tmp_literal;
memset(&tmp_literal, 0, sizeof(tmp_literal));
condition->object_cnt = n_object_ids;
tmp_obj = cJSON_GetObjectItem(literal_obj, "attribute_name");
if (tmp_obj == NULL || tmp_obj->type != cJSON_String) {
log_fatal(rule_rt->logger, MODULE_RULE,
"[%s:%d] table: <%s> has no attribute_name or not string format",
__FUNCTION__, __LINE__, table_name);
goto error;
}
for (int j = 0; j < n_object_ids; j++) {
cJSON *object_id_obj = cJSON_GetArrayItem(tmp_obj, j);
if (object_id_obj && object_id_obj->type == cJSON_String) {
uuid_parse(object_id_obj->valuestring, condition->object_uuids[j]);
if (strlen(tmp_obj->valuestring) >= sizeof(tmp_literal.attribute_name)) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> attribute_name:%s length exceed maximum:%d",
__FUNCTION__, __LINE__, table_name, tmp_obj->valuestring, sizeof(tmp_literal.attribute_name));
goto error;
}
snprintf(tmp_literal.attribute_name, sizeof(tmp_literal.attribute_name), "%s", tmp_obj->valuestring);
if (condition->negate_option == CONDITION_NEGATE_OPTION_SET) {
int ret = validate_table_not_condition(rule_rt, schema->ref_tbl_mgr, tmp_literal.attribute_name, MAAT_OP_ADD, logger);
if (ret < 0) {
log_fatal(logger, MODULE_RULE,
"[%s:%d] table: <%s> validate negate_option failed, line: %s",
__FUNCTION__, __LINE__, table_name, table_line);
goto error;
}
}
tmp_obj = cJSON_GetObjectItem(literal_obj, "object_uuids");
if (tmp_obj && tmp_obj->type == cJSON_Array) {
int n_object_ids = cJSON_GetArraySize(tmp_obj);
tmp_literal.object_cnt = n_object_ids;
for (int j = 0; j < n_object_ids; j++) {
cJSON *object_id_obj = cJSON_GetArrayItem(tmp_obj, j);
if (object_id_obj && object_id_obj->type == cJSON_String) {
uuid_parse(object_id_obj->valuestring, tmp_literal.object_uuids[j]);
}
}
}
utarray_push_back(condition->literals, &tmp_literal);
}
condition->in_use = 1;
@@ -676,32 +690,37 @@ build_condition_id_kv_hash(struct rule_runtime *rule_rt, int negate_option)
}
}
for (size_t k = 0; k < condition->object_cnt; k++) {
struct condition_query_key key;
struct condition_id_kv *condition_id_kv = NULL;
struct condition_literal *tmp_literal = NULL;
for (size_t j = 0; j < utarray_len(condition->literals); j++) {
tmp_literal = (struct condition_literal *)utarray_eltptr(condition->literals, j);
memset(&key, 0, sizeof(key));
for (size_t k = 0; k < tmp_literal->object_cnt; k++) {
struct condition_query_key key;
struct condition_id_kv *condition_id_kv = NULL;
memcpy(key.attribute_name, condition->attribute_name, sizeof(key.attribute_name));
key.negate_option = condition->negate_option;
uuid_copy(key.object_uuid, condition->object_uuids[k]);
HASH_FIND(hh, condition_id_kv_hash, &key, sizeof(struct condition_query_key),
condition_id_kv);
if (NULL == condition_id_kv) {
condition_id_kv = ALLOC(struct condition_id_kv, 1);
condition_id_kv->key = key;
utarray_new(condition_id_kv->condition_ids, &ut_condition_id_icd);
HASH_ADD_KEYPTR(hh, condition_id_kv_hash, &condition_id_kv->key,
sizeof(condition_id_kv->key), condition_id_kv);
memset(&key, 0, sizeof(key));
memcpy(key.attribute_name, tmp_literal->attribute_name, sizeof(key.attribute_name));
key.negate_option = condition->negate_option;
uuid_copy(key.object_uuid, tmp_literal->object_uuids[k]);
HASH_FIND(hh, condition_id_kv_hash, &key, sizeof(struct condition_query_key),
condition_id_kv);
if (NULL == condition_id_kv) {
condition_id_kv = ALLOC(struct condition_id_kv, 1);
condition_id_kv->key = key;
utarray_new(condition_id_kv->condition_ids, &ut_condition_id_icd);
HASH_ADD_KEYPTR(hh, condition_id_kv_hash, &condition_id_kv->key,
sizeof(condition_id_kv->key), condition_id_kv);
}
if (utarray_find(condition_id_kv->condition_ids, &(condition->condition_id),
compare_condition_id)) {
continue;
}
utarray_push_back(condition_id_kv->condition_ids, &(condition->condition_id));
utarray_sort(condition_id_kv->condition_ids, compare_condition_id);
}
if (utarray_find(condition_id_kv->condition_ids, &(condition->condition_id),
compare_condition_id)) {
continue;
}
utarray_push_back(condition_id_kv->condition_ids, &(condition->condition_id));
utarray_sort(condition_id_kv->condition_ids, compare_condition_id);
}
}
}
@@ -1001,20 +1020,24 @@ static int maat_rule_has_condition_query_key(struct maat_rule *rule,
continue;
}
struct condition_literal *tmp_literal = NULL;
for (size_t j = 0; j < utarray_len(condition->literals); j++) {
tmp_literal = (struct condition_literal *)utarray_eltptr(condition->literals, j);
if (strncmp(condition->attribute_name, key->attribute_name, sizeof(key->attribute_name)) != 0) {
continue;
}
if (strncmp(tmp_literal->attribute_name, key->attribute_name, sizeof(key->attribute_name)) != 0) {
continue;
}
if (condition->negate_option != key->negate_option) {
continue;
}
if (condition->negate_option != key->negate_option) {
continue;
}
uuid_t *tmp_object_uuid = bsearch(&(key->object_uuid), condition->object_uuids,
condition->object_cnt, sizeof(uuid_t),
compare_object_uuid);
if (tmp_object_uuid != NULL) {
return 1;
uuid_t *tmp_object_uuid = bsearch(&(key->object_uuid), tmp_literal->object_uuids,
tmp_literal->object_cnt, sizeof(uuid_t),
compare_object_uuid);
if (tmp_object_uuid != NULL) {
return 1;
}
}
}
@@ -1035,16 +1058,21 @@ maat_rule_get_hit_condition_index(struct maat_rule *rule,
continue;
}
struct condition_literal *tmp_literal = NULL;
for (size_t j = 0; j < utarray_len(tmp_condition->literals); j++) {
tmp_literal = (struct condition_literal *)utarray_eltptr(tmp_condition->literals, j);
if (strncmp(tmp_literal->attribute_name, attribute_name, sizeof(tmp_literal->attribute_name)) != 0) {
continue;
}
if (strncmp(tmp_condition->attribute_name, attribute_name, sizeof(tmp_condition->attribute_name)) != 0) {
continue;
}
uuid_t *tmp_object_uuid = bsearch(hit_object_uuid, tmp_condition->object_uuids,
tmp_condition->object_cnt, sizeof(uuid_t),
compare_object_uuid);
if (tmp_object_uuid != NULL) {
condition_idx_array[hit_condition_cnt++] = i;
uuid_t *tmp_object_uuid = bsearch(hit_object_uuid, tmp_literal->object_uuids,
tmp_literal->object_cnt, sizeof(uuid_t),
compare_object_uuid);
if (tmp_object_uuid != NULL) {
condition_idx_array[hit_condition_cnt++] = i;
break;
}
}
}
@@ -1457,7 +1485,10 @@ static void rule_runtime_del_rule(struct rule_runtime *rule_rt,
for (int i = 0; i < rule->condition_num; i++) {
struct rule_condition *condition = rule->conditions + i;
if (condition->in_use && condition->negate_option == CONDITION_NEGATE_OPTION_SET) {
validate_table_not_condition(rule_rt, schema->ref_tbl_mgr, condition->attribute_name, MAAT_OP_DEL, logger);
for (size_t j = 0; j < utarray_len(condition->literals); j++) {
struct condition_literal *literal = (struct condition_literal *)utarray_eltptr(condition->literals, j);
validate_table_not_condition(rule_rt, schema->ref_tbl_mgr, literal->attribute_name, MAAT_OP_DEL, logger);
}
}
}

View File

@@ -10,7 +10,7 @@
"do_log": 1,
"user_region": "anything",
"is_valid": "yes",
"conditions": [
"and_conditions": [
{
"object_name": "Untitled",
"attribute_name": "HTTP_URL",

View File

@@ -10,7 +10,7 @@
"do_log": 1,
"user_region": "anything",
"is_valid": "yes",
"conditions": [
"and_conditions": [
{
"attribute_name": "HTTP_URL",
"objects": [

View File

@@ -10,7 +10,7 @@
"do_log": 1,
"user_region": "anything",
"is_valid": "yes",
"conditions": [
"and_conditions": [
{
"attribute_name": "HTTP_URL",
"objects": [

File diff suppressed because one or more lines are too long