记一次ElasticSearch 模糊查询引起的终端权限自动化回收异常Troubeshoot 2024-09-03 11:39:23 Steven Xeldax 某个工作日,突然IT问到了这样一个问题  自动化终端Root/管理员权限分发剧本一般而言只有1-30天的有效期,从剧本上线到现在不应该还有300多个Root管理员权限遗留在组里啊,这明显就是root权限自动化回收BUG了,完全没有移除权限过期的用户。 为了看到底应该有多少人还有权限重新将历史所有工单的数据进行历史演算。 ``` import csv import json from datetime import datetime, timedelta import dateutil.parser file_path = 'XXXX.csv' # 打开 CSV 文件 data = [] new_data = {} with open(file_path, newline='') as csvfile: csvreader = csv.reader(csvfile) for row in csvreader: occur_time = row[8] j = row[10] print(j) if j == 'payload' or j == '\n' or len(j) <= 2: continue jj = json.loads(j) occur_time = dateutil.parser.parse(occur_time) end_date = occur_time tmp = None if jj.get("apply_effect_day") == '一天': end_date = occur_time + timedelta(days=1) tmp = timedelta(days=1) elif jj.get("apply_effect_day") == '三天': end_date = occur_time + timedelta(days=3) tmp = timedelta(days=1) elif jj.get("apply_effect_day") == '七天': end_date = occur_time + timedelta(days=7) tmp = timedelta(days=1) elif jj.get("apply_effect_day") == '三十天': end_date = occur_time + timedelta(days=30) tmp = timedelta(days=1) if not new_data.get(jj.get("apply_user")): new_data[jj.get("apply_user")] = end_date else: new_data[jj.get("apply_user")] = new_data[jj.get("apply_user")] + tmp if jj.get("apply_policy") == "Root权限": data.append({ 'occur_time': occur_time.isoformat(), 'ETA': end_date.isoformat(), "username": jj.get("apply_user"), "apply_policy": jj.get("apply_policy"), "revoke": False }) # print(data) sorted_data = sorted(data, key=lambda x: x['occur_time']) # print(new_data) for i in new_data: print(i, new_data[i]) ``` 经过测算应该只有30个人还有权限,但现在有300个人,肯定逻辑有问题。 看了一边分发权限的逻辑: 1.工单传输到SOAR提取邮箱和分发的权限内容以及有效期时间 2.前往ElasticSearch中查询用户之前是否有申请过的权限 3.如果有就标记权限过期,重新add一个新的有效期的权限 4.将用户添加到root组分发权限 那回收权限的逻辑则是: 1.ElasitcSearch查询ETA有效期小于当前时间,并且revoke 标记没有被设置为已经移除权限的结果 2.将用户邮箱提取出来remove掉权限组 3.ElasticSearch对上面查询出来的结果重新打标记设置已经移除 逻辑上应该没有问题啊,这个只有是ES查询上有问题了。经过定位确定了,在《前往ElasticSearch中查询用户之前是否有申请过的权限》这步骤搜索时候由于分片模糊所搜,导致搜索出了多余的数据。 BUG的搜索为: ``` { "query": { "bool": { "must": [{ "match": { "user_email": "A@test.com" } }, { "match": { "privilege": "Root权限" } }, { "match": { "is_revoke": false } } ] } } } ``` 因为match的关系会搜索出test.com 的数据结果,而我的本意是希望精确搜索,即: ``` user_email = "A@test.com" privilege = "Root权限" is_revoke = false ``` 优化后的结果为: ``` { "query": { "bool": { "must": [{ "term": { "user_email.keyword": "${payload.apply_user}" } }, { "term": { "privilege.keyword": "${payload.apply_policy}" } }, { "term": { "is_revoke": false } } ] } } } ``` 这里面还有一个肯定,user_email和privilege都是经过处理器处理的,所有term直接搜不到,已经要加keywork。 ``` 如果使用"term"查询无法搜索到结果,可能是因为字段被分析器处理过,导致无法精确匹配。在这种情况下,你可以尝试使用"keyword"字段类型进行精确匹配。"keyword"字段类型不会被分析器处理,可以确保精确匹配。 ```