首页 > 其他分享 >jumpserver V2自动同步、更新阿里云资产

jumpserver V2自动同步、更新阿里云资产

时间:2024-09-25 18:55:59浏览次数:10  
标签:assets ip self list jumpserver V2 阿里 ecs

一、注意事项

1.1  注意替换资产模板中nodes值,可以通过数据库assets_node表中获取,或者使用jumpserver 脚本获取资产信息查看

jumpserver V2自动同步、更新阿里云资产_json

1.2 requirements.txt

aliyun-python-sdk-core==2.13.36
aliyun-python-sdk-ecs==4.24.30
aliyunsdkcore==1.0.3
requests==2.28.2
urllib3==1.26.14
PyMySQL~=1.0.2

二、相关脚本文件

aliyun_ecs.py

# -*- coding: utf-8 -*-

"""
@Time : 2023/2/27
@Author : Bowen
@File : aliyun_ecs
@Description : 
"""
# pip install requests drf-httpsig
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkecs.request.v20140526.DescribeInstancesRequest import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526.DescribeDisksRequest import DescribeDisksRequest


class ecs_api(object):
    def __init__(self, region="cn-hangzhou"):
        self.region = region
        # 设置阿里云的AccessKeyID和AccessKeySecret
        self.AK = "xxxxxxx"
        self.AS = "xxxxxxx"
        self.client = AcsClient(self.AK, self.AS, self.region)

    def get_ecs_all(self):
        """
        获取所有ECS实例信息
        :return: list,包含当前AK用户当前地域下所有可查询ECS实例信息列表
        """
        request = DescribeInstancesRequest()
        request.set_accept_format('json')
        # 设置参数,每页返回的数量为10
        request.set_PageSize(10)
        # 设置页码,从第一页开始
        page_number = 1
        ecs_list = []
        while True:
            # 设置当前页码
            request.set_PageNumber(page_number)

            # 发送请求,获取响应
            response = self.client.do_action_with_exception(request)
            res = json.loads(str(response, encoding='utf-8'))
            res = res['Instances']['Instance']
            # 如果返回的数据为空,则退出循环
            if not res: break

            # 处理响应数据
            for ecs in res:
                ecs_list.append(ecs)
            # 增加页码
            page_number += 1
        return ecs_list

    def get_ecs_disk_size(self, instance_id):
        """
        阿里云ECS相关操作
        :param instance_id: ECS实例ID
        :return: int,返回当前实例系统盘容量大小,主要由于jumpserver 磁盘仅有容量字段,无法区分磁盘
        """
        system_disk_size = 0
        request = DescribeDisksRequest()
        request.set_accept_format('json')

        request.set_InstanceId('i-bp1bjhiosovwnd16u2tf')

        response = self.client.do_action_with_exception(request)
        res = json.loads(str(response, encoding='utf-8'))
        for disk in res['Disks']['Disk']:
            if disk['Device'] == "/dev/xvda":
                system_disk_size = disk['Size']

        return system_disk_size


if __name__ == '__main__':
    obj = ecs_api()
    obj.get_ecs_all()

jms_api.py

# -*- coding: utf-8 -*-

"""
@Time : 2023/2/27
@Author : Bowen
@File : jumpserver
@Description : 
"""
import requests
import json
from jms_mysql import get_asset_id
from aliyun_ecs import ecs_api


class jumpserver(object):

    def __init__(self):
        self.jms_url = 'http://192.168.1.136'
        self.token = '012cddf58f6f89f32631c9a7d49e8991b34a8c71'
        self.headers = {
            "Authorization": 'Token ' + self.token,
            'X-JMS-ORG': '00000000-0000-0000-0000-000000000002',
            'accept': 'application/json'
        }
        self.assets_url = self.jms_url + '/api/v1/assets/assets/'
        self.ecs_api = ecs_api()

    def get_assets_all(self):
        """
        获取jumpserver所有资产信息
        :return: List 包含jumpserver所有资产信息列表
        """
        req = requests.get(url=self.assets_url, headers=self.headers)
        assets_list = json.loads(req.content.decode())
        return assets_list

    @staticmethod
    def judge_ecs_in_jms(assets_list, ecs_list):
        """
        判断哪些阿里云ECS实例存在jumpserver中
        :param assets_list: List,jumpserver所有资产信息
        :param ecs_list: 阿里云所有ECS实例信息
        :return: List,List 分别返回阿里云实例已经存在和不存在jumpserver资产中的实例列表
        """
        jms_ip_set = set()
        ecs_ip_set = set()

        for assets in assets_list:
            jms_ip_set.add(assets['ip'])

        for ecs in ecs_list:
            ecs_ip = ecs['NetworkInterfaces']['NetworkInterface'][0]['PrimaryIpAddress']
            ecs_ip_set.add(ecs_ip)

        in_jmp_for_ecs = ecs_ip_set & jms_ip_set
        not_in_jump_for_ecs = ecs_ip_set - jms_ip_set
        not_in_ecs_for_jms = jms_ip_set - ecs_ip_set

        return in_jmp_for_ecs, not_in_jump_for_ecs, not_in_ecs_for_jms

    def create_assets(self, ecs_list, ip_list):
        """
        判断阿里云主机是否存在jumpserver中,不存在则创建jumpserver资产
        :param ecs_list: 所有ECS实例列表
        :param ip_list: 不存在jumpserver资产中的ECS实例ip
        :return: None  应当返回则创建的资产条目及摘要信息,懒得写了
        """
        assets_temp = {'id': '', 'hostname': '', 'ip': '', 'platform': 'Linux', 'protocols': ['ssh/34518'],
                       'is_active': True,
                       'public_ip': None, 'number': None, 'comment': '', 'vendor': None, 'model': None, 'sn': None,
                       'cpu_model': None, 'cpu_count': None, 'cpu_cores': None, 'cpu_vcpus': None, 'memory': None,
                       'disk_total': None, 'disk_info': None, 'os': None, 'os_version': None, 'os_arch': None,
                       'hostname_raw': None, 'cpu_info': '', 'hardware_info': '', 'domain': None, 'admin_user': None,
                       'admin_user_display': '', 'nodes': ['b0506981-d3e0-4e28-ba83-968c2521df6b'], 'nodes_display': ['/Default'], 'labels': [],
                       'labels_display': [],
                       'connectivity': 'failed', 'date_verified': '', 'created_by': '', 'date_created': '',
                       'org_id': '00000000-0000-0000-0000-000000000002', 'org_name': 'Default'}
        add_assets_list = []

        for ecs in ecs_list:
            ecs_ip = ecs['NetworkInterfaces']['NetworkInterface'][0]['PrimaryIpAddress']
            # 如果当前ECS实例IP不在jumpserver当前的资产中,则为该ECS创建对应的jumpserver资产
            if ecs_ip in ip_list:
                assets_temp['hostname'] = ecs['InstanceName'] + '-' + ecs_ip
                assets_temp['ip'] = ecs_ip
                assets_temp['memory'] = str(ecs['Memory'] / 1024) + 'GB'
                assets_temp['cpu_vcpus'] = ecs['Cpu']
                assets_temp['platform'] = ecs['OSType'].capitalize()
                assets_temp['os'] = ecs['OSName']
                assets_temp['cpu_count'] = ecs['CpuOptions']['ThreadsPerCore']
                assets_temp['cpu_cores'] = ecs['CpuOptions']['CoreCount']
                assets_temp['disk_total'] = str(self.ecs_api.get_ecs_disk_size(ecs['InstanceId'])) + 'GB'
                response = requests.post(self.assets_url, headers=self.headers, data=assets_temp)
                if response.status_code != 201:
                    print("新增资产失败")
                    print("失败资产信息:%s" % assets_temp)
                    print("失败原因:%s" % response.text)
                    break
                else:
                    add_assets_list.append(ecs_ip)
        if add_assets_list:
            print("新增资产条目:%s" % len(add_assets_list))
            print("新增资产IP:" + ' '.join(add_assets_list))
        else:
            print("无新增资产")

    def patch_assets(self, ecs_list, assets_list, exist_ip_list):
        """
        同步ECS信息到jumpserver
        :param ecs_list: 所有ECS实例列表
        :param assets_list: 所有jumpserver资产信息列表
        :param exist_ip_list: 已存在jumpserver中的ECS IP
        :return: None  应当返回发生变更的资产条目个数及具体信息,懒得写了
        """
        patch_list = []
        patch_ip_list = []

        # 循环jumpserver和阿里云并集的IP
        for exist_ip in exist_ip_list:
            flag = False

            # 找到jumpserver和阿里云相同的条目,获取相关条目信息,并对比相关条目信息,如主机名称 内存 磁盘等
            for ecs in ecs_list:
                if ecs['NetworkInterfaces']['NetworkInterface'][0]['PrimaryIpAddress'] == exist_ip:
                    ecs_info = ecs
                    break

            for assets in assets_list:
                if assets['ip'] == exist_ip:
                    assets_info = assets
                    break

            if assets_info['hostname'] != (ecs_info['InstanceName'] + '-' + exist_ip):
                assets_info['hostname'] = ecs_info['InstanceName'] + '-' + exist_ip
                flag = True

            if assets_info['memory'] != (str(ecs_info['Memory'] / 1024) + 'GB'):
                assets_info['memory'] = (str(ecs_info['Memory'] / 1024) + 'GB')
                flag = True

            if assets_info['cpu_vcpus'] != ecs_info['Cpu']:
                assets_info['cpu_vcpus'] = ecs_info['Cpu']
                flag = True

            if assets_info['cpu_count'] != ecs_info['CpuOptions']['ThreadsPerCore']:
                assets_info['cpu_count'] = ecs_info['CpuOptions']['ThreadsPerCore']
                flag = True

            if assets_info['cpu_cores'] != ecs_info['CpuOptions']['CoreCount']:
                assets_info['cpu_cores'] = ecs_info['CpuOptions']['CoreCount']
                flag = True

            if assets_info['disk_total'] != str(self.ecs_api.get_ecs_disk_size(ecs_info['InstanceId'])) + 'GB':
                assets_info['disk_total'] = str(self.ecs_api.get_ecs_disk_size(ecs_info['InstanceId'])) + 'GB'
                flag = True

            if flag:
                patch_list.append(assets_info)
                patch_ip_list.append(exist_ip)

        if patch_list:
            response = requests.put(self.assets_url, headers=self.headers, json=patch_list)
            if response.status_code != 200:
                print("更新资产失败")
                print("失败资产信息:%s" % assets_info)
                print("失败原因:%s" % response.text)
            else:
                print("更新资产条目:%s" % len(patch_list))
                print("更新资产IP:" + ' '.join(patch_ip_list))
        else:
            print("没有需要变更的资产")

    def delete_asset(self, ip_list):
        delete_ip_list = []
        for ip in ip_list:
            asset_id = get_asset_id(ip)
            url = self.assets_url + asset_id + '/'
            response = requests.delete(url, headers=self.headers)
            if response.status_code == 204:
                delete_ip_list.append(ip)
            else:
                print("删除资产失败")
                print("失败资产ip:%s" % ip)
                print("失败原因:%s" % response.text)

        if delete_ip_list:
            print("删除 %s 个条目" % len(delete_ip_list))
            print("删除资产IP:" + ' '.join(delete_ip_list))
        else:
            print("没有需要删除的资产")

jms_mysql.py

# -*- coding: utf-8 -*-

"""
@Time : 2023/2/28
@Author : Bowen
@File : jms_mysql
@Description : 
"""
import pymysql


def get_asset_id(ip):
    conn = pymysql.connect(
        host='192.168.1.135',  # 数据库地址
        port=3306,  # 数据库端口
        user='root',  # 数据库用户名
        password='Qwer@123',  # 数据库密码
        database='jumpserver'  # 数据库名称
    )

    # 创建游标对象
    cursor = conn.cursor()

    # 执行查询操作
    sql = "SELECT id FROM assets_asset WHERE ip = '%s'" % ip

    cursor.execute(sql)

    # 获取查询结果
    result = cursor.fetchone()[0]

    # 关闭游标和连接
    cursor.close()
    conn.close()

    return result

main.py

# -*- coding: utf-8 -*-

"""
@Time : 2023/2/8
@Author : Bowen
@File : main
@Description :
"""
from aliyun_ecs import ecs_api
from jms_api import jumpserver

if __name__ == '__main__':
    # 实例化aliyun及jumpserver对象
    aliyun_obj = ecs_api()
    jms_obj = jumpserver()

    # 获取所有ECS及jumpserver对象
    ecs_all = aliyun_obj.get_ecs_all()
    assets_all = jms_obj.get_assets_all()

    # 分别获取存在jumpserver及不存在jumpserver中的阿里云ECS机器列表
    exist_jms_list, not_exist_jms_list, not_exist_ecs_list = jumpserver.judge_ecs_in_jms(assets_list=assets_all, ecs_list=ecs_all)

    # 如果不存在jumpserver中,则在jumpserver中创建该资产
    if not_exist_jms_list:
        jms_obj.create_assets(ecs_all, not_exist_jms_list)

    # 如果存在jumpserver中,则校验ECS当前信息与jumpserver信息是否一致,如果不一致则参考ECS进行修改
    if exist_jms_list:
        jms_obj.patch_assets(ecs_list=ecs_all, assets_list=assets_all, exist_ip_list=exist_jms_list)

    # 如果jumpserver中的资产不存在阿里云上,则删除
    if not_exist_ecs_list:
        jms_obj.delete_asset(not_exist_ecs_list)

直接运行main文件,执行结果如下,更详细信息懒得写

jumpserver V2自动同步、更新阿里云资产_IP_02

 

 

"一劳永逸" 的话,有是有的,而 "一劳永逸" 的事却极少



标签:assets,ip,self,list,jumpserver,V2,阿里,ecs
From: https://blog.51cto.com/u_8901540/12111435

相关文章

  • jumpserver API调试
    一、获取认证token由于我是docker,这里我只演示docker方式,其他方式类似dockerexec-itjms_core/bin/bash#进入core服务cd/opt/jumpserver/appspythonmanage.pyshellfromusers.modelsimportUseru=User.objects.get(username='admin')u.create_private_token()......
  • 阿里云ECS无法使用25端口发送短信解决方法
    phpmailer发邮件提示SMTP->ERROR:Failedtoconnecttoserver的解决方法写的网站本地测试发送短信成功,但是部署到阿里云ECS服务器上发送短信失败。打开cmd测试下telnetsmtp.163.com25 失败telnetsmtp.163.com465成功则解决方法如下配置的时候设置端口465,并加密SSL$mailer->......
  • 阿里云函数计算 x NVIDIA 加速企业 AI 应用落地
    前言阿里云函数计算(FunctionCompute,FC)是一种无服务器(Serverless)计算服务,允许用户在无需管理底层基础设施的情况下,直接运行代码。与传统的计算架构相比,函数计算具有高灵活性和弹性扩展的特点,用户只需专注于业务逻辑的开发,系统自动处理计算资源的分配、扩展和维护。同时,函数计算......
  • 阿里云点播SDK集成(一)上传篇
    目前项目中用到的就是阿里云的点播包括视频上传及播放,有做短视频的宝子们可以借鉴一下,避免少走弯路 1.省略开通或配置阿里云点播服务的平台配置,直接是iOS移动端部分,podSDK尽量用最新的#阿里云播放器pod'AliPlayerSDK_iOS'#阿里云文件上传pod'VODUpload'2.获取STS服......
  • linux 切换阿里云镜像源
    目录linux切换阿里云镜像源备份原有文件:创建阿里云CentOS仓库文件:清理缓存并更新软件包列表:测试是否成功:linux切换阿里云镜像源centos7安装好后,发现外网可以ping通,但是yum一直报错,看报错内容为镜像源问题于是切换镜像源备份原有文件:在进行任何更改之前,请确保备份原有的仓......
  • 阿里云主力模型直降97%,AI行业起飞
    阿里云主力模型直降97%,AI行业起飞大模型降价潮对AI应用的爆发有哪些意义对AI行业的影响大模型降价潮关于大模型降价潮,阿里云对外宣布通义千问GPT-4级主力模型Qwen-Long,API输入价格从0.02元/千tokens降至0.0005元/千tokens,直降97%,那么为了证实这一点,特意查询了通义千问的......
  • 解决 ModuleNotFoundError: No module named ‘cv2‘?
    前言解决ModuleNotFoundError:Nomodulenamed‘cv2’?ModuleNotFoundError:Nomodulenamed‘cv2’?1.安装opencv-python:pipinstallopencv-python-ihttps://pypi.tuna.tsinghua.edu.cn/simple/2.出现错误ERROR:Couldnotbuildwheelsforopencv-python......
  • 阿里巴巴商品详情API返回值中的商品标签与关键词
    阿里巴巴的商品详情API(通常指的是阿里巴巴开放平台提供的API服务)为开发者提供了访问和获取商品信息的途径。这些API的返回值中会包含商品的详细信息,包括但不限于商品的基本信息、价格、库存、物流信息以及标签和关键词等。然而,关于“商品标签与关键词含代码”的具体描述,可能需要根......
  • 在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.1)
    在不受支持的Mac上安装macOSSequoia(OpenCoreLegacyPatcherv2.0.1)InstallmacOSonunsupportedMacs请访问原文链接:https://sysin.org/blog/install-macos-on-unsupported-mac/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgOpenCoreLegacyPatcher2.0......
  • 阿里云ecs使用nginx部署mqtt服务的tcp转发
    一、什么是MQTT?MQTT(MessageQueuingTelemetryTransport)是一种轻量级、基于发布-订阅模式的消息传输协议,适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境。它在物联网应用中广受欢迎,能够实现传感器、执行器和其它设备之间的高效通信。二、为什么MQTT是适用于物联网的最......