️ Support for automatic CVE handling (#164)

* 支持自动处理 CVE
This commit is contained in:
Xtao_dada 2022-01-18 16:25:30 +08:00 committed by GitHub
parent 7618fa75f4
commit 15d07ee621
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 102 deletions

View File

@ -500,6 +500,8 @@ update_failed: update failed
update_auto_upgrade_git_failed_ubuntu: It is detected that your system is Ubuntu or Debain. Try to upgrade git automatically but failed. Please upgrade manually.
update_auto_upgrade_git_failed_cent: It is detected that your system is CentOS, try to upgrade git automatically but failed, please upgrade manually.
update_auto_upgrade_git_hint: Your git version is too low and has tried to automatically upgrade for you. If you are reminded of this error again, please upgrade manually.
update_master: Received a known CVE and is forcing an update to the PagerMaid-Modify instance
update_plugins: Received a known CVE and is forcing an update to the relevant plugin
# sb
sb_des: Ban a user in the common group of administrator privileges.

View File

@ -516,6 +516,8 @@ update_failed: 更新失败
update_auto_upgrade_git_failed_ubuntu: 检测到您的系统是Ubuntu或Debain尝试自动升级git但失败,请手动升级.
update_auto_upgrade_git_failed_cent: 检测到您的系统是CentOS尝试自动升级git但失败,请手动升级.
update_auto_upgrade_git_hint: 您的git版本过低,已尝试为您自动升级. 如再次提醒此错误,请手动升级.
update_master: 收到已知的 CVE ,正在强制更新 PagerMaid-Modify 实例
update_plugins: 收到已知的 CVE ,正在强制更新相关插件
# sb
sb_des: 在自己拥有管理员权限的共同群组中封禁一位用户。

View File

@ -500,6 +500,8 @@ update_failed: 更新失敗
update_auto_upgrade_git_failed_ubuntu: 檢測到您的系統為Ubuntu/Debian嘗試自動升級Git失敗請手動。
update_auto_upgrade_git_failed_cent: 檢測到您的系統為CentOS/RedHat Linux嘗試自動升級Git失敗請手動。
update_auto_upgrade_git_hint: 檢測到您Git版本過低已嘗試自動升級。若此錯誤持續發生請手動。
update_master: 收到已知的 CVE ,正在強制更新 PagerMaid-Modify 實例
update_plugins: 收到已知的 CVE ,正在強制更新相關插件
# sb
sb_des: 在自己擁有管理員權限的共同群組中封禁一位用戶。

View File

@ -6,7 +6,6 @@ from concurrent.futures import CancelledError
import sentry_sdk
from sentry_sdk.integrations.redis import RedisIntegration
from asyncio import CancelledError as CancelError
from subprocess import run, PIPE
from datetime import datetime
from time import time
@ -20,6 +19,7 @@ from redis import StrictRedis
from logging import getLogger, INFO, DEBUG, ERROR, StreamHandler, basicConfig
from distutils.util import strtobool
from coloredlogs import ColoredFormatter
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from telethon import TelegramClient
from telethon.sessions import StringSession
@ -32,6 +32,9 @@ from telethon.errors.rpcerrorlist import MessageNotModifiedError, MessageIdInval
from telethon.errors.common import AlreadyInConversationError
from requests.exceptions import ChunkedEncodingError
from requests.exceptions import ConnectionError as ConnectedError
from asyncio import CancelledError as CancelError
from asyncio import TimeoutError as AsyncTimeoutError
from aiohttp.client_exceptions import ServerDisconnectedError
from sqlite3 import OperationalError
from http.client import RemoteDisconnected
from urllib.error import URLError
@ -43,6 +46,11 @@ module_dir = __path__[0]
working_dir = getcwd()
config = None
help_messages = {}
scheduler = AsyncIOScheduler()
if not scheduler.running:
scheduler.configure(timezone="Asia/ShangHai")
scheduler.start()
version = 0.1
logs = getLogger(__name__)
logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s"
logging_handler = StreamHandler()
@ -274,7 +282,7 @@ def before_send(event, hint):
OSError, AuthKeyDuplicatedError, ResponseError, SlowModeWaitError,
PeerFloodError, MessageEditTimeExpiredError, PeerIdInvalidError,
AuthKeyUnregisteredError, UserBannedInChannelError, AuthKeyError,
CancelError)):
CancelError, AsyncTimeoutError, ServerDisconnectedError)):
return
elif exc_info and isinstance(exc_info[1], UserDeactivatedBanError):
# The user has been deleted/deactivated
@ -295,7 +303,7 @@ report_time = time()
start_time = datetime.utcnow()
git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode()
sentry_sdk.init(
"https://88b676b38216473db3eb3dd5e1da0133@o416616.ingest.sentry.io/5312335",
"https://58c6c9990d5c4d3784aec0aecb7509d3@o416616.ingest.sentry.io/5312335",
traces_sample_rate=1.0,
release=git_hash,
before_send=before_send,

View File

@ -1,124 +1,70 @@
""" Pulls in the new version of PagerMaid from the git server. """
import platform
import time
from datetime import datetime
from distutils.util import strtobool
from json import JSONDecodeError
from json import JSONDecodeError, loads, load
from os import remove
from os.path import exists
from subprocess import run, PIPE
from sys import executable
from git import Repo
from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError
from pagermaid import log, config, silent
from telethon.tl.functions.channels import GetFullChannelRequest
from pagermaid import log, config, silent, scheduler, bot, version, working_dir, logs
from pagermaid.listener import listener
from pagermaid.utils import execute, lang, alias_command, get
from pagermaid.modules.plugin import remove_plugin, update_version, download
from pagermaid.utils import execute, lang, alias_command
try:
git_api = config['git_api']
git_ssh = config['git_ssh']
git_ssh = config["git_ssh"]
need_update_check = strtobool(config['update_check'])
update_time = config['update_time']
update_username = config['update_username']
update_delete = strtobool(config['update_delete'])
except KeyError:
git_api = "https://api.github.com/repos/Xtao-Labs/PagerMaid-Modify/commits/master"
git_ssh = 'https://github.com/Xtao-Labs/PagerMaid-Modify.git'
git_ssh = "https://github.com/Xtao-Labs/PagerMaid-Modify.git"
need_update_check = True
update_time = 86400
update_username = 'PagerMaid_Modify_bot'
update_delete = True
try:
update_time = int(update_time)
except ValueError:
update_time = 86400
try:
update_username = int(update_username)
except ValueError:
pass
async def update_get():
try:
data = (await get(git_api)).json()
except JSONDecodeError as e:
raise e
return data
update_get_time = 0
update_id = 0
@listener(incoming=True, ignore_edited=True)
async def update_refresher(context):
global update_get_time, update_id
@scheduler.scheduled_job("cron", minute="*/30", id="0")
async def run_every_30_minute():
if not need_update_check:
return
if time.time() - update_get_time > update_time:
update_get_time = time.time()
changelog = None
try:
repo = Repo()
active_branch = repo.active_branch.name
if not await branch_check(active_branch):
return
repo.create_remote('upstream', git_ssh)
upstream_remote = repo.remote('upstream')
upstream_remote.fetch(active_branch)
changelog = await changelog_gen(repo, f'HEAD..upstream/{active_branch}')
if not changelog:
return
else:
if update_username == 'self':
user = await context.client.get_me(input_peer=True)
else:
try:
user = await context.client.get_input_entity(update_username)
except ValueError:
user = await context.client.get_me(input_peer=True)
if not update_id == 0 and update_delete:
try:
await context.client.delete_messages(user, update_id)
except:
pass
try:
msg = await context.client.send_message(user,
f'**{lang("update_found_update_in_branch")} '
f'{active_branch}.\n\n'
f'{lang("update_change_log")}:**\n`{changelog}`')
update_id = msg.id
except:
pass
except:
result = await bot(GetFullChannelRequest("UGFnZXJNYWlk")) # noqa
async for msg in bot.iter_messages("UGFnZXJNYWlk"):
if msg.text:
try:
data = await update_get()
git_hash = run("git rev-parse HEAD", stdout=PIPE, shell=True).stdout.decode().strip()
if not data['sha'] == git_hash:
if update_username == 'self':
user = await context.client.get_me(input_peer=True)
else:
try:
user = await context.client.get_input_entity(update_username)
except ValueError:
user = await context.client.get_me(input_peer=True)
changelog = data['commit']['message']
if not update_id == 0 and update_delete:
try:
await context.client.delete_messages(user, update_id)
except:
pass
data_ = loads(msg.text.strip("`"))
except JSONDecodeError:
continue
need_restart = False
for data in data_["data"]:
if data["mode"] == "master":
if version < data["version"]:
logs.info(lang('update_master'))
await execute("git reset --hard")
await execute("git pull")
await execute(f"{executable} -m pip install -r requirements.txt --upgrade")
await execute(f"{executable} -m pip install -r requirements.txt")
need_restart = True
elif data["mode"] == "plugins":
if not exists(f"{working_dir}/plugins/version.json"):
return
with open(f"{working_dir}/plugins/version.json", 'r', encoding="utf-8") as f:
version_json = load(f)
try:
msg = await context.client.send_message(user, f'**{lang("update_found_update_in_branch")} '
f'master.\n\n'
f'{lang("update_change_log")}:**\n`{changelog}`')
update_id = msg.id
except:
pass
except Exception as e:
await log(f"Warning: module update failed to refresh git commit data.\n{e}")
plugin_version = version_json[data["name"]]
except KeyError:
return
if (float(data["version"]) - float(plugin_version)) > 0:
logs.info(lang('update_plugins'))
remove_plugin(data["name"])
await download(data["name"])
update_version(data["name"], data["version"])
need_restart = True
if need_restart:
await bot.disconnect()
@listener(is_plugin=False, outgoing=True, command=alias_command("update"),

View File

@ -301,6 +301,7 @@ async def request(method: str,
config_["proxy"] = f"http://{http_addr}:{http_port}"
session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout))
resp = await session.request(**config_)
await session.close()
# 返回请求
try:
resp_data = await resp.text()
@ -308,7 +309,6 @@ async def request(method: str,
resp_data = await resp.read()
content = await resp.content.read()
status_code = resp.status
await session.close()
return AiohttpResp(resp_data, content, status_code)

View File

@ -35,6 +35,7 @@ cheroot>=8.5.2
python-socks[asyncio]>=1.2.4
certifi>=2021.5.30
magic_google>=0.2.9
sentry-sdk>=1.5.1
sentry-sdk>=1.5.2
analytics-python>=1.4.0
beautifulsoup4>=4.9.3
apscheduler>=3.8.1