add exp date

This commit is contained in:
StarsL.cn 2022-07-01 07:58:29 +08:00
parent e7d423fa0d
commit fd5a2abdaf
16 changed files with 349 additions and 13 deletions

View File

@ -6,7 +6,7 @@ skey_path = 'ConsulManager/assets/secret/skey'
if consul_kv.get_kv_dict(skey_path) == {}:
consul_kv.put_kv(skey_path,{'sk':''.join(str(uuid.uuid4()).split('-'))})
from views import login, blackbox, consul, jobs, nodes, selfnode, avd
from views import login, blackbox, consul, jobs, nodes, selfnode, avd, exp
from units.cloud import huaweicloud,alicloud,tencent_cloud
from units.avd import avd_list
app = Flask(__name__)
@ -17,12 +17,14 @@ app.register_blueprint(jobs.blueprint)
app.register_blueprint(nodes.blueprint)
app.register_blueprint(selfnode.blueprint)
app.register_blueprint(avd.blueprint)
app.register_blueprint(exp.blueprint)
class Config(object):
JOBS = []
SCHEDULER_API_ENABLED = True
init_jobs = consul_kv.get_kv_dict('ConsulManager/jobs')
ecs_jobs = consul_kv.get_kv_dict('ConsulManager/jobs')
avd_jobs = consul_kv.get_kv_dict('ConsulManager/avd/jobs')
init_jobs.update(avd_jobs)
exp_jobs = consul_kv.get_kv_dict('ConsulManager/exp/jobs')
init_jobs = { **ecs_jobs, **avd_jobs, **exp_jobs }
if init_jobs is not None:
for k,v in init_jobs.items():

View File

@ -13,8 +13,11 @@ beautifulsoup4==4.11.1
huaweicloudsdkcore==3.0.78
huaweicloudsdkecs==3.0.78
huaweicloudsdkeps==3.0.78
huaweicloudsdkbss==3.0.95
alibabacloud_resourcemanager20200331==2.1.0
alibabacloud_ecs20140526==2.1.0
alibabacloud_bssopenapi20171214==2.0.5
tencentcloud-sdk-python-common==3.0.607
tencentcloud-sdk-python-cvm==3.0.607
tencentcloud-sdk-python-dcdb==3.0.607
tencentcloud-sdk-python-billing==3.0.607

View File

@ -41,9 +41,9 @@ def get_avd():
f"- 状态:<font color=\"#ff0000\">{avd_dict['avd_stat']}</font>({avd_dict['avd_collect']})\n"
if avd_dict['avd_id'] == last_avd.get('avd_id'):
content = content + '(已披露漏洞,今日推送为状态或类型有更新。)\n'
if avd_switch['switch'] and avd_switch['wecom'] and wecomwh.startswith('https://qyapi.weixin.qq.com'):
if avd_switch['switch'] and avd_switch.get('wecom',False) and wecomwh.startswith('https://qyapi.weixin.qq.com'):
wecom(wecomwh,content)
if avd_switch['switch'] and avd_switch['dingding'] and dingdingwh.startswith('https://oapi.dingtalk.com'):
if avd_switch['switch'] and avd_switch.get('dingding',False) and dingdingwh.startswith('https://oapi.dingtalk.com'):
dingding(dingdingwh,content)
if avd_switch['switch'] and avd_switch.get('feishu',False) and feishuwh.startswith('https://open.feishu.cn'):
title = '漏洞告警:' + avd_dict['avd_name']

View File

@ -4,10 +4,77 @@ from alibabacloud_resourcemanager20200331 import models as resource_manager_2020
from alibabacloud_ecs20140526.client import Client as Ecs20140526Client
from alibabacloud_ecs20140526 import models as ecs_20140526_models
from Tea.exceptions import TeaException
from alibabacloud_bssopenapi20171214.client import Client as BssOpenApi20171214Client
from alibabacloud_bssopenapi20171214 import models as bss_open_api_20171214_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
import sys,datetime
from units import consul_kv
from units.cloud import sync_ecs
from units.cloud import notify
def exp(account,collect_days,notify_days,notify_amount):
ak,sk = consul_kv.get_aksk('alicloud',account)
now = datetime.datetime.utcnow().strftime('%Y-%m-%dT16:00:00Z')
collect = (datetime.datetime.utcnow() + datetime.timedelta(days=collect_days+1)).strftime('%Y-%m-%dT16:00:00Z')
config = open_api_models.Config(access_key_id=ak,access_key_secret=sk)
config.endpoint = f'business.aliyuncs.com'
client = BssOpenApi20171214Client(config)
query_available_instances_request = bss_open_api_20171214_models.QueryAvailableInstancesRequest(
renew_status='ManualRenewal',
end_time_start=now,
end_time_end=collect)
runtime = util_models.RuntimeOptions()
amount_response = client.query_account_balance()
try:
exp = client.query_available_instances_with_options(query_available_instances_request, runtime)
exp_list = exp.body.to_map()['Data']['InstanceList']
exp_dict = {}
notify_dict = {}
amount_dict = {}
for i in exp_list:
endtime = datetime.datetime.strptime(i['EndTime'],'%Y-%m-%dT%H:%M:%SZ') + datetime.timedelta(hours=8)
endtime_str = endtime.strftime('%Y-%m-%d')
exp_dict[i['InstanceID']] = {'Region':i['Region'],'Product':i['ProductCode'],
'EndTime':endtime_str,'Ptype':i.get('ProductType',i['ProductCode'])}
if (endtime - datetime.datetime.now()).days < notify_days:
notify_dict[i['InstanceID']] = exp_dict[i['InstanceID']]
consul_kv.put_kv(f'ConsulManager/exp/lists/alicloud/{account}/exp', exp_dict)
amount = float(amount_response.body.data.available_amount.replace(',',''))
consul_kv.put_kv(f'ConsulManager/exp/lists/alicloud/{account}/amount',{'amount':amount})
if amount < notify_amount:
amount_dict = {'amount':amount}
exp_config = consul_kv.get_value('ConsulManager/exp/config')
wecomwh = exp_config.get('wecomwh','')
dingdingwh = exp_config.get('dingdingwh','')
feishuwh = exp_config.get('feishuwh','')
if notify_dict != {}:
msg = [f'### 阿里云账号 {account}\n### 以下资源到期日小于 {notify_days} 天:']
for k,v in notify_dict.items():
msg.append(f"- {v['Region']}{v['Product']}{k}<font color=\"#ff0000\">{v['EndTime']}</font>")
content = '\n'.join(msg)
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '阿里云资源到期通知'
md = content
notify.feishu(feishuwh,title,md)
if amount_dict != {}:
content = f'### 阿里云账号 {account}\n### 可用余额:<font color=\"#ff0000\">{amount}</font> 元'
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '阿里云余额不足通知'
md = content
notify.feishu(feishuwh,title,md)
except Exception as error:
UtilClient.assert_as_string(error.message)
def group(account):
ak,sk = consul_kv.get_aksk('alicloud',account)

View File

@ -0,0 +1,27 @@
#!/usr/bin/python3
import json
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.billing.v20180709 import billing_client, models
try:
cred = credential.Credential("AKIDWqwnOjpgHchX7SYP1NUMyKQGrCI8j40g", "TgdLn0xe5HDtJUQ6WgMqCKEuNdfS1LRJ")
httpProfile = HttpProfile()
httpProfile.endpoint = "billing.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = billing_client.BillingClient(cred, "", clientProfile)
req = models.DescribeAccountBalanceRequest()
params = {
}
req.from_json_string(json.dumps(params))
resp = client.DescribeAccountBalance(req).RealBalance
print(resp/100)
except TencentCloudSDKException as err:
print(err)

View File

@ -1,12 +1,90 @@
from huaweicloudsdkcore.auth.credentials import GlobalCredentials,BasicCredentials
from huaweicloudsdkeps.v1.region.eps_region import EpsRegion
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkbss.v2.region.bss_region import BssRegion
from huaweicloudsdkeps.v1 import *
from huaweicloudsdkecs.v2.region.ecs_region import EcsRegion
from huaweicloudsdkecs.v2 import *
from huaweicloudsdkbss.v2 import *
import sys,datetime
from units import consul_kv
from units.cloud import sync_ecs
from units.cloud import notify
def exp(account,collect_days,notify_days,notify_amount):
ak,sk = consul_kv.get_aksk('huaweicloud',account)
now = datetime.datetime.utcnow().strftime('%Y-%m-%dT16:00:00Z')
collect = (datetime.datetime.utcnow() + datetime.timedelta(days=collect_days+1)).strftime('%Y-%m-%dT16:00:00Z')
credentials = GlobalCredentials(ak, sk)
try:
client = BssClient.new_builder() \
.with_credentials(credentials) \
.with_region(BssRegion.value_of("cn-north-1")) \
.build()
request = ListPayPerUseCustomerResourcesRequest()
listQueryResourcesReqStatusListbody = [2]
request.body = QueryResourcesReq(
expire_time_end=collect,
limit=500,
status_list=listQueryResourcesReqStatusListbody,
only_main_resource=1
)
exp_list = client.list_pay_per_use_customer_resources(request).to_dict()['data']
exp_dict = {}
notify_dict = {}
amount_dict = {}
for i in exp_list:
endtime = datetime.datetime.strptime(i['expire_time'],'%Y-%m-%dT%H:%M:%SZ') + datetime.timedelta(hours=8.1)
endtime_str = endtime.strftime('%Y-%m-%d')
i['service_type_code'].replace('hws.service.type.','')
if i['expire_policy'] not in [1,3,4]:
exp_dict[i['resource_id']] = {'Region':i['region_code'],'Product':i['resource_spec_code'],
'EndTime':endtime_str,'Name':i['resource_name'],'Ptype':i['resource_type_code']}
if (endtime - datetime.datetime.now()).days < notify_days:
notify_dict[i['resource_id']] = exp_dict[i['resource_id']]
consul_kv.put_kv(f'ConsulManager/exp/lists/huaweicloud/{account}/exp', exp_dict)
request = ShowCustomerAccountBalancesRequest()
response = client.show_customer_account_balances(request).to_dict()['account_balances']
amount = [i['amount'] for i in response if i['account_type'] == 1][0]
consul_kv.put_kv(f'ConsulManager/exp/lists/huaweicloud/{account}/amount',{'amount':amount})
if amount < notify_amount:
amount_dict = {'amount':amount}
exp_config = consul_kv.get_value('ConsulManager/exp/config')
wecomwh = exp_config.get('wecomwh','')
dingdingwh = exp_config.get('dingdingwh','')
feishuwh = exp_config.get('feishuwh','')
if notify_dict != {}:
msg = [f'### 华为云账号 {account}\n### 以下资源到期日小于 {notify_days} 天:']
for k,v in notify_dict.items():
msg.append(f"- {v['Region']}{v['Product']}{v['Name']}<font color=\"#ff0000\">{v['EndTime']}</font>")
content = '\n'.join(msg)
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '华为云资源到期通知'
md = content
notify.feishu(feishuwh,title,md)
if amount_dict != {}:
content = f'### 华为云账号 {account}\n### 可用余额:<font color=\"#ff0000\">{amount}</font> 元'
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '华为云余额不足通知'
md = content
notify.feishu(feishuwh,title,md)
except exceptions.ClientRequestException as e:
print(e.status_code)
print(e.request_id)
print(e.error_code)
print(e.error_msg)
def group(account):
ak,sk = consul_kv.get_aksk('huaweicloud',account)
now = datetime.datetime.now().strftime('%m%d/%H:%M')

View File

@ -0,0 +1,23 @@
import requests,json
def wecom(webhook,content):
headers = {'Content-Type': 'application/json'}
params = {'msgtype': 'markdown', 'markdown': {'content' : content}}
data = bytes(json.dumps(params), 'utf-8')
response = requests.post(webhook, headers=headers, data=data)
print('【wecom】',response.json(),flush=True)
def dingding(webhook,content):
headers = {'Content-Type': 'application/json'}
params = {"msgtype":"markdown","markdown":{"title":"资源告警","text":content},"at":{"isAtAll":True}}
data = bytes(json.dumps(params), 'utf-8')
response = requests.post(webhook, headers=headers, data=data)
print('【dingding】',response.json(),flush=True)
def feishu(webhook,title,md):
headers = {'Content-Type': 'application/json'}
params = {"msg_type": "interactive",
"card": {"header": {"title": {"tag": "plain_text","content": title},"template": "red"},
"elements": [{"tag": "markdown","content": f"{md}\n<at id=all></at>",}]}}
data = json.dumps(params)
response = requests.post(webhook, headers=headers, data=data)
print('【feishu】',response.json(),flush=True)

View File

@ -9,6 +9,70 @@ import sys,datetime
#import consul_kv,sync_ecs
from units import consul_kv
from units.cloud import sync_ecs
from units.cloud import notify
def exp(account,collect_days,notify_days,notify_amount):
from tencentcloud.billing.v20180709 import billing_client, models
ak,sk = consul_kv.get_aksk('tencent_cloud',account)
exp_dict = {}
notify_dict = {}
amount_dict = {}
try:
ecs_list = consul_kv.get_services_meta(f'tencent_cloud_{account}_ecs').get('ecs_list',[])
now = datetime.datetime.now()
for i in ecs_list:
exp_day = datetime.datetime.strptime(i['exp'], '%Y-%m-%d')
if (now - exp_day).days <= collect_days:
exp_dict[i['iid']] = {'Region':i['region'],'Product':i['os'],'Name':i['name'],
'EndTime':i['exp'],'Ptype':i['cpu']+i['mem'],'Group':i['group']}
if (now - exp_day).days <= notify_days:
notify_dict[i['iid']] = exp_dict[i['iid']]
consul_kv.put_kv(f'ConsulManager/exp/lists/tencent_cloud/{account}/exp', exp_dict)
cred = credential.Credential(ak, sk)
httpProfile = HttpProfile()
httpProfile.endpoint = "billing.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = billing_client.BillingClient(cred, "", clientProfile)
req = models.DescribeAccountBalanceRequest()
params = {}
req.from_json_string(json.dumps(params))
amount = client.DescribeAccountBalance(req).RealBalance/100
consul_kv.put_kv(f'ConsulManager/exp/lists/tencent_cloud/{account}/amount',{'amount':amount})
if amount < notify_amount:
amount_dict = {'amount':amount}
exp_config = consul_kv.get_value('ConsulManager/exp/config')
wecomwh = exp_config.get('wecomwh','')
dingdingwh = exp_config.get('dingdingwh','')
feishuwh = exp_config.get('feishuwh','')
if notify_dict != {}:
msg = [f'### 腾讯云账号 {account}\n### 以下资源到期日小于 {notify_days} 天:']
for k,v in notify_dict.items():
msg.append(f"- {v['Region']}{v['Product']}{v['Group']}{v['Name']}<font color=\"#ff0000\">{v['EndTime']}</font>")
content = '\n'.join(msg)
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '腾讯云资源到期通知'
md = content
notify.feishu(feishuwh,title,md)
if amount_dict != {}:
content = f'### 腾讯云账号 {account}\n### 可用余额:<font color=\"#ff0000\">{amount}</font> 元'
if exp_config['switch'] and exp_config.get('wecom',False):
notify.wecom(wecomwh,content)
if exp_config['switch'] and exp_config.get('dingding',False):
notify.dingding(dingdingwh,content)
if exp_config['switch'] and exp_config.get('feishu',False):
title = '腾讯云余额不足通知'
md = content
notify.feishu(feishuwh,title,md)
except TencentCloudSDKException as err:
print(err)
def group(account):
from tencentcloud.dcdb.v20180411 import dcdb_client, models

View File

@ -69,7 +69,17 @@ def get_ecs_services(job_id):
return {'code': 20000,'ecs_list': ecs_list}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}
def get_services_meta(services_name):
url = f'{consul_url}/agent/services?filter=Service == "{services_name}"'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
ecs_list = [i['Meta'] for i in info.values()]
return {'code': 20000,'ecs_list': ecs_list}
else:
return {'code': 50000, 'data': f'{response.status_code}:{response.text}'}
def get_aksk(cloud,account):
import myaes
aksk_dict = get_value(f'ConsulManager/assets/{cloud}/aksk/{account}')

61
flask-consul/views/exp.py Normal file
View File

@ -0,0 +1,61 @@
from flask import Blueprint
from flask_restful import reqparse, Resource, Api
from flask_apscheduler import APScheduler
from units import token_auth,consul_kv
import json
from .jobs import deljob,addjob,runjob
blueprint = Blueprint('exp',__name__)
api = Api(blueprint)
parser = reqparse.RequestParser()
parser.add_argument('exp_config_dict',type=dict)
class Exp(Resource):
#decorators = [token_auth.auth.login_required]
def get(self,stype):
if stype == 'list':
exp_dict = consul_kv.get_kv_dict('ConsulManager/exp/list')
exp_list = list(exp_dict.values())
return {'code': 20000, 'exp_list': exp_list}
if stype == 'config':
exp_config = consul_kv.get_value('ConsulManager/exp/switch')
return {'code': 20000, 'exp_config': exp_config}
def post(self,stype):
if stype == 'config':
args = parser.parse_args()
exp_config_dict = args['exp_config_dict']
consul_kv.put_kv('ConsulManager/exp/config',exp_config_dict)
cloud_job_list = consul_kv.get_keys_list('ConsulManager/jobs')
cloud_list = [i for i in cloud_job_list if i.endswith('/group') and 'tencent_cloud' in i]
collect_days = exp_config_dict['collect_days']
notify_days = exp_config_dict['notify_days']
notify_amount = exp_config_dict['notify_amount']
if exp_config_dict['switch']:
for i in cloud_list:
vendor,account = i.split('/')[2:4]
exp_job_id = f'{vendor}/{account}/exp'
exp_job_func = f'__main__:{vendor}.exp'
exp_job_args = [account,collect_days,notify_days,notify_amount]
exp_job_interval = 60
addjob(exp_job_id,exp_job_func,exp_job_args,exp_job_interval)
exp_job_dict = {'id':exp_job_id,'func':exp_job_func,'args':exp_job_args,'minutes':exp_job_interval,'trigger': 'interval','replace_existing': True}
consul_kv.put_kv(f'ConsulManager/exp/jobs/{vendor}/{account}',exp_job_dict)
runjob(exp_job_id)
return {'code': 20000, 'data': '到期日与余额采集功能开启!'}
else:
for i in cloud_list:
vendor,account = i.split('/')[2:4]
exp_job_id = f'{vendor}/{account}/exp'
deljob(exp_job_id)
consul_kv.del_key_all('ConsulManager/exp/jobs/')
consul_kv.del_key_all('ConsulManager/exp/lists/')
return {'code': 20000, 'data': '到期日与余额采集功能关闭!'}
if stype == 'run':
exp_config_dict = consul_kv.get_value('ConsulManager/exp/switch')
if exp_config_dict['switch']:
consul_kv.del_key('ConsulManager/exp/list/0')
runjob('exp_list')
return {'code': 20000, 'data': '漏洞采集通知执行成功!'}
else:
return {'code': 50000, 'data': '漏洞采集功能未开启!'}
api.add_resource(Exp, '/api/exp/<stype>')

View File

@ -5,5 +5,5 @@ RUN npm install --registry=https://registry.npm.taobao.org && npm run build:prod
FROM nginx:stable-alpine
WORKDIR /www
COPY --from=builder /vue/http-ops.conf /etc/nginx/conf.d/
COPY --from=builder /vue/http-ops.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /vue/dist dist/

View File

@ -7,5 +7,5 @@ RUN mv -f src/views/login/index.vue.tensuns src/views/login/index.vue && \
FROM nginx:stable-alpine
WORKDIR /www
COPY --from=builder /vue/http-ops.conf /etc/nginx/conf.d/
COPY --from=builder /vue/http-ops.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /vue/dist dist/

View File

@ -46,6 +46,7 @@ Object.keys(filters).forEach(key => {
})
Vue.config.productionTip = false
Vue.prototype.VER = 'v0.6.5'
new Vue({
el: '#app',

View File

@ -46,7 +46,7 @@
</el-form>
<div align="center" class="title-container">
<span style="font-size:12px" class="title">v0.6.5</span>
<span style="font-size:12px" class="title">{{ VER }}</span>
</div>
</div>
</template>

View File

@ -43,7 +43,7 @@
</el-form>
<div align="center" class="title-container">
<span style="font-size:12px" class="title">v0.6.5</span>
<span style="font-size:12px" class="title">{{ VER }}</span>
</div>
</div>
</template>

View File

@ -23,7 +23,7 @@
导出
</el-button>
<el-upload
style="margin-right: 10px;"
style="margin-right: 9px;"
class="upload-demo"
action="/api/selfnode/upload"
:headers="myHeaders"
@ -35,7 +35,7 @@
:multiple="false"
>
<el-tooltip class="item" effect="light" content="点击【导出】可获取导入模板" placement="top">
<el-button v-waves style="margin-left: 10px;" :loading="downloadLoading" class="filter-item" type="warning" icon="el-icon-upload2">
<el-button v-waves style="margin-left: 9px;" :loading="downloadLoading" class="filter-item" type="warning" icon="el-icon-upload2">
导入
</el-button>
</el-tooltip>
@ -43,7 +43,7 @@
<el-button class="filter-item" type="danger" icon="el-icon-delete" @click="handleDelAll">
批量删除
</el-button>
<div style="float: right;margin-left: 10px;">
<div style="float: right;margin-left: 9px;">
<el-input v-model="iname" prefix-icon="el-icon-search" placeholder="请输入名称或实例进行筛选" clearable style="width:180px" class="filter-item" @input="inameFilter(iname)" />
</div>
</div>