flask 定时监控阿里云 ECS 安全组授权对象为公网的规则并进行钉钉报警
目录结构

创建 conf.py 文件,配置区分生产环境和开发环境
# 生产环境
class ProductionConfig:
IGNORE_PORTS_LIST = ['80/80', '443/443', '22/22', '8080/8080', '8899/8899', '43999/43999', '8011/8011', '3333/3333'] # 定义排除的端口
DINGTALK_URL = 'https://oapi.dingtalk.com/robot/send?access_token=8888888888888888888888888888888888888888888888888888888888888888' # 运维组
# 开发环境
class DevelopmentConfig:
IGNORE_PORTS_LIST = ['80/80', '443/443', '22/22']
DINGTALK_URL = 'https://oapi.dingtalk.com/robot/send?access_token=8888888888888888888888888888888888888888888888888888888888888888' # 运维组
在 operate 包下,创建 dingtalk.py 文件,用来发送钉钉告警信息
import json
import requests
# 定义环境
from conf import ProductionConfig as Config
url = Config.DINGTALK_URL
def send_msg(msg):
parameter = {
"msgtype": "text",
"text": {
"content": "告警 -- 阿里云正式环境 安全组 有对公网开放的端口,详情为:%s ,请及时查看~" % msg
},
}
headers = {
'Content-Type': 'application/json'
}
requests.post(url, data=json.dumps(parameter), headers=headers)
在 operate 包下,创建 check_securegroup.py 文件,用来检查阿里云ECS安全组的规则
# __author__: "klvchen"
# date: 2020/10/12
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkecs.request.v20140526.DescribeSecurityGroupAttributeRequest import DescribeSecurityGroupAttributeRequest
import json
from operate import dingtalk
# 定义环境
from conf import ProductionConfig as Config
# 定义忽略的端口号
ignore_ports_list = Config.IGNORE_PORTS_LIST
client = AcsClient('xxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxx', 'cn-shenzhen')
request = DescribeSecurityGroupAttributeRequest()
request.set_accept_format('json')
request.set_SecurityGroupId("sg-xxxxxxxxxxxxxx")
def check_ports():
response = client.do_action_with_exception(request)
result_json = json.loads((str(response, encoding='utf-8')))
# 定义可能有问题的端口
ports_list = []
for p in range(len(result_json['Permissions']['Permission'])):
# 获取对全部公网开放的端口
if result_json['Permissions']['Permission'][p]['SourceCidrIp'] == '0.0.0.0/0' and result_json['Permissions']['Permission'][p]["PortRange"] not in ignore_ports_list:
# 排除 ICMP 协议
if result_json['Permissions']['Permission'][p]["IpProtocol"] != 'ICMP':
ports_list.append(result_json['Permissions']['Permission'][p]["PortRange"])
return ports_list
# 控制报警次数
alarm_num = 1
# 重设报警次数
def reset_alarm_num():
global alarm_num
alarm_num = 1
def main():
result = check_ports()
# 使用全局变量 alarm_num
global alarm_num
if result and alarm_num > 0:
# 发送钉钉报警
dingtalk.send_msg(result)
alarm_num = alarm_num - 1
编写 app.py 文件
from flask import Flask
from flask_apscheduler import APScheduler
from operate import check_securegroup
import logging
app = Flask(__name__)
@app.route('/')
def hello_world():
app.logger.warning('warning log: It works!') # 访问输出 warning 日志
return 'Hello World!'
class SchedulerConfig(object):
JOBS = [
{
'id': 'check_mysql1', # 任务id
'func': '__main__:check_securegroup.main', # 任务执行程序
'args': None, # 执行程序参数
'trigger': 'interval', # 任务执行类型,定时器
'seconds': 300 # 任务执行时间,单位秒 (每5分钟调用一次)
},
{
'id': 'reset_alarm_num',
'func': '__main__:check_securegroup.reset_alarm_num', # 重设 alarm_num
'args': None,
'trigger': 'interval',
'hours': 6 # 每 6 个小时重设一次报警次数
}
]
if __name__ == '__main__':
handler = logging.FileHandler('flask.log', encoding='UTF-8') # 设置日志字符集和存储路径名字
logging_format = logging.Formatter( # 设置日志格式
'%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s')
handler.setFormatter(logging_format)
app.logger.addHandler(handler)
app.config.from_object(SchedulerConfig()) # 为实例化的flask引入定时任务配置
scheduler = APScheduler() # 实例化APScheduler
scheduler.init_app(app) # 把任务列表载入实例flask
scheduler.start() # 启动任务计划
app.run()
运行, 进入 app.py 所在的目录
python app.py
附上依赖
aliyun-python-sdk-acs==0.0.3
aliyun-python-sdk-core==2.13.26
aliyun-python-sdk-core-v3==2.13.11
aliyun-python-sdk-ecs==4.19.12
APScheduler==3.6.3
certifi==2020.6.20
chardet==3.0.4
click==7.1.2
Flask==1.1.2
Flask-APScheduler==1.11.0
idna==2.10
itsdangerous==1.1.0
Jinja2==2.11.2
jmespath==0.10.0
MarkupSafe==1.1.1
python-dateutil==2.8.1
pytz==2020.1
requests==2.24.0
six==1.15.0
tzlocal==2.1
urllib3==1.25.10
Werkzeug==1.0.1
参考:https://help.aliyun.com/document_detail/25555.html?spm=a2c4g.11186623.6.1374.23ad27afN2xh8s

浙公网安备 33010602011771号