#!/usr/bin/python # -*- coding: UTF-8 -*- import os import sys import time import subprocess import json from alive_progress import alive_bar from InquirerPy import prompt # 全局变量 # 堡垒机安装目录 fort_path = "/usr/local/las" # 数据目录 data_path = "%s/data" % fort_path # 配置目录 config_path = "%s/config" % fort_path # 进程目录 program_path = "%s/program" % fort_path # 日志目录 log_path = "%s/log" % fort_path # 当前工作目录 work_dir = os.path.dirname(os.path.abspath(sys.argv[0])) # 判断租户标识 tenant_flag = '' # print("B当前工作目录为:%s" % work_dir) # 执行系统指令 # cmd: 指令 # bar: 进度条 # return: 执行结果 def run_cmd(cmd, bar): res = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="UTF-8", timeout=600) # 命令执行是否异常,异常则中断安装 if (res.returncode != 0 and res.stderr): print("执行命令: %s 失败" % cmd) print("错误信息: %s" % res.stderr) # sys.exit(1) # 更新进度条 if (bar != None): bar() return res # 检测端口 def check_port(port): res = run_cmd("ss -tln | grep %s" % port, None) if (res.stdout == ""): return False else: return True # 补全标题 def fill_title(title): # 设置统一的字符串长度 width = 16 # 计算字符串当前的长度 title_width = 0 for char in title: # 判断是否为ASCII字符(字母) if ord(char) < 256: title_width += 1 else: title_width += 2 # 计算需要填充的空格数量 space_count = width - title_width # 在字符串右侧添加连字符 `-` filled_title = title.ljust(len(title) + space_count, ' ') return filled_title # 检测安装环境 def install_init(): with alive_bar(2, title=fill_title('检测安装环境'), bar='smooth', spinner='classic') as bar: # 切换到工作目录 os.chdir(work_dir) # 获取当前操作系统信息 system_info = run_cmd("cat /etc/os-release", None).stdout if system_info.find("BigCloud Enterprise Linux") != -1: # 放置 yum 缓存包 run_cmd("rpm -e --nodeps bclinux-license-manager-2.0-3.el7.bclinux.aarch64", bar) run_cmd("tar -xvf ./module/BC-Linux-Arm64-Yum-Cache.tar -C /var/cache/", bar) else: print("不支持当前操作系统: %s" % system_info) exit(1) # 设置时区 def set_time_zone(): with alive_bar(3, title=fill_title('设置系统时区'), bar='smooth', spinner='classic') as bar: # 修改系统语言为中文 run_cmd("localectl set-locale LANG=zh_CN.UTF8", bar) # 修改系统时区为上海 run_cmd("timedatectl set-timezone Asia/Shanghai", bar) # 将系统时间同步到硬件时间 run_cmd("hwclock -w", bar) # 创建初始化目录 def creat_dir(): log_dirs = [ "/cluster", # 集群日志 "/cmp-agent", # 集群管理平台对接agent 日志 "/elasticsearch", # elasticsearch 日志 "/forever", # pm2(仅fort服务) 日志 "/minio", # minio 日志 "/mongodb", # mongodb 日志 "/nginx", # nginx 日志 "/pm2", # pm2(所有node服务) 日志 "/redis", # redis 日志 "/tomcat", # tomcat 日志 ] program_dirs = [ "/java", # java 程序 ] config_dirs = [ "/cluster", # 集群配置 "/licence", # licence 配置 "/mongodb", # mongodb 配置 ] data_dirs = [ "/backup", # 数据备份目录 "/backup/es", # elasticsearch 备份目录 "/elasticsearch", # elasticsearch 数据目录 "/fort", # RDP 共享盘缓存目录 "/fortlog", # guacd 缓存目录 "/minio", # minio 数据目录 "/mongodb/db", # mongodb 数据目录 "/mongodb/arb", # mongodb 仲裁节点数据目录 "/redis", # redis 数据目录 ] # 创建日志目录 with alive_bar(len(log_dirs), title=fill_title('创建日志目录'), bar='smooth', spinner='classic') as bar: for dir in log_dirs: run_cmd("mkdir -p " + log_path + dir, bar) # 创建进程目录 with alive_bar(len(program_dirs), title=fill_title('创建进程目录'), bar='smooth', spinner='classic') as bar: for dir in program_dirs: run_cmd("mkdir -p " + program_path + dir, bar) # 创建配置目录 with alive_bar(len(config_dirs), title=fill_title('创建配置目录'), bar='smooth', spinner='classic') as bar: for dir in config_dirs: run_cmd("mkdir -p " + config_path + dir, bar) # 创建数据目录 with alive_bar(len(data_dirs), title=fill_title('创建数据目录'), bar='smooth', spinner='classic') as bar: for dir in data_dirs: run_cmd("mkdir -p " + data_path + dir, bar) # 设置环境变量 def set_env(): cmds = [ # 记录部署目录 "echo 'export FORT_PATH=%s' >> /etc/profile" % fort_path, # 将 nodejs 目录下的可执行文件添加至环境变量,以便于在任意目录下执行 "echo 'export PATH=$PATH:/root/.nvm/versions/node/v16.20.1/bin/' >> /etc/profile", # 添加 /usr/local/lib 目录至 LD_LIBRARY_PATH 环境变量 "echo 'export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH' >> /etc/profile", # 设置 PM2 日志路径 "echo 'export PM2_HOME=%s/pm2' >> /etc/profile" % log_path, # 重新加载环境变量 "source /etc/profile" ] with alive_bar(len(cmds), title=fill_title('设置环境变量'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装工具 def install_tools(): tools = [ "keepalived", "net-tools", "telnet", "lrzsz", "expect", "wireshark", "samba", "ntp", "net-snmp", "sysstat", "nc", "openssl", "openssl-devel", "java-1.8.0-openjdk", "java-1.8.0-openjdk-devel", ] # 安装工具 with alive_bar(len(tools), title=fill_title('安装系统工具'), bar='smooth', spinner='classic') as bar: for tool in tools: run_cmd("yum -C -y install %s" % tool, bar) # 安装 phantomjs (webkit 内核的无界面浏览器) def install_phantomjs(): cmds = [ # 放置phantomjs主程序 "mv -f ./module/phantomjs/phantomjs /usr/local/bin/", # 放置phantomjs依赖库 "mv -f ./module/phantomjs/*so* /lib64/", ] with alive_bar(len(cmds), title=fill_title('安装 phantomjs'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 watchdog def install_watchdog(): cmds = [ # 放置watchdog主程序 "mv -f ./module/laswatchdog/ %s/" % program_path, ] with alive_bar(len(cmds), title=fill_title('安装 watchdog'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 snmpd def install_snmpd(): cmds = [ # 放置开机自启脚本 "mv -f ./module/net-snmp/snmpd /etc/init.d/", # 放置snmpd主程序 "tar -zxvf ./module/net-snmp/net-snmp.tar.gz -C %s/" % program_path, ] with alive_bar(len(cmds), title=fill_title('安装 snmpd'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 扩充系统字体(单点支持中文) def enrich_fonts(): cmds = [ "mv -f ./module/fonts /usr/share/fonts/", "mkfontscale", "mkfontdir", "fc-cache -fv" ] with alive_bar(len(cmds), title=fill_title('扩充系统字体'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 放置全局脚本 def install_scripts(): with alive_bar(1, title=fill_title('放置全局脚本'), bar='smooth', spinner='classic') as bar: run_cmd("mv -f ./module/shell/ %s/" % program_path, bar) # 安装 guacd def install_guacd(): cmds = [ "mv -n ./module/guacd/usr_lib64/* /usr/lib64/", "mv -n ./module/guacd/guacd/lib/* /usr/local/lib/", "mv -f ./module/guacd/c_server /usr/local/", "mv -f ./module/guacd/guacd/sbin/guacd /usr/local/sbin/guacd", "echo '/usr/lib64' >> /etc/ld.so.conf", "echo '/usr/local/lib' >> /etc/ld.so.conf", "echo '/usr/local/lib/freerdp' >> /etc/ld.so.conf", "echo '/usr/local/lib64/freerdp' >> /etc/ld.so.conf", "ldconfig", ] with alive_bar(len(cmds), title=fill_title('安装 guacd'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 tomcat def install_tomcat(): cmds = [ "tar -xzvf ./module/tomcat/tomcat7.tar.gz -C %s/" % program_path, "mv %s/tomcat*/ %s/tomcat/" % (program_path, program_path), ] with alive_bar(len(cmds), title=fill_title('安装 tomcat'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 mongodb def install_mongodb(): cmds = [ "tar -zxvf ./module/mongodb/mongodb.tar.gz -C %s/" % program_path, # 放置缺少的依赖 "rm -f /lib64/libstdc++.so.6.0.27", "rm -f /lib64/libstdc++.so.6", "ln -sv /usr/local/las/program/mongodb/lib/libstdc++.so.6.0.27 /lib64/libstdc++.so.6.0.27", "ln -sv /lib64/libstdc++.so.6.0.27 /lib64/libstdc++.so.6", "mv -f ./module/mongodb/libcrypto.so.10 /lib64/", # 放置 mongo 配置文件/启动脚本 "mv -f ./module/mongodb/mongodb.conf %s/mongodb/" % config_path, "mv -f ./module/mongodb/cluster/key %s/mongodb/" % config_path, "chmod 600 %s/mongodb/key" % config_path, "mv -f ./module/mongodb/mongodb /etc/init.d/", # 放置 arb 配置文件/启动脚本 "mv -f ./module/mongodb/arb.conf %s/mongodb/" % config_path, "mv -f ./module/mongodb/arb /etc/init.d/", "/etc/init.d/mongodb start", # 导入 admin 数据库的用户名密码 "%s/mongodb/bin/mongorestore -d admin ./module/mongodb/admin/ --drop" % program_path, # 开启认证 "sed -i s/#auth=true/auth=true/g %s/mongodb/mongodb.conf" % config_path, ] with alive_bar(len(cmds), title=fill_title('安装 mongodb'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 elasticSearch def install_elastic(): cmds = [ # 创建es专属用户(elasticsearch 不允许 root 启动) "groupadd elasticsearch", # 设置用户不可登录 "useradd elasticsearch -g elasticsearch -s /sbin/nologin", # 安装 elasticsearch "tar -xvf ./module/elasticsearch/elasticsearch.tar -C %s/" % program_path, # 放置 elasticsearch 启动脚本 "mv -f ./module/elasticsearch/elasticsearch /etc/init.d/", # 设置权限(elasticsearch 不允许 root 启动) "chown -R elasticsearch:elasticsearch %s/elasticsearch/" % program_path, "chown -R elasticsearch:elasticsearch %s/elasticsearch/" % data_path, "chown -R elasticsearch:elasticsearch %s/elasticsearch/" % log_path, "chown -R elasticsearch:elasticsearch %s/backup/es" % data_path, # 设置普通用户和 root 用户, 进程的最大数量没有限制 "echo '* soft nproc unlimited' >> /etc/security/limits.conf", "echo 'root soft nproc unlimited' >> /etc/security/limits.conf", # Elasticsearch 用户打开的文件句柄数量设置为 65536(最大) "echo 'elasticsearch - nofile 65536' >> /etc/security/limits.conf", # Elasticsearch 用户可以锁定无限量的内存,不受限制地锁定内存 "echo 'elasticsearch - memlock unlimited' >> /etc/security/limits.conf", # soft/hard 模式下所有用户打开的文件句柄数量设置为 65536(最大) "echo '* soft nofile 65536' >> /etc/security/limits.d/20-nproc.conf", "echo '* hard nofile 65536' >> /etc/security/limits.d/20-nproc.conf", "/etc/init.d/elasticsearch start", # 等待启动(自定义命令) "check port", # 设置 ES 快照存储目录 "curl -XPUT -H \"Content-Type: application/json\" 'http://localhost:9200/_snapshot/backup' -d '{\"type\":\"fs\",\"settings\":{\"location\":\"%s/backup/es\",\"compress\":true}}'" % data_path, ] with alive_bar(len(cmds), title=fill_title('安装 elastic'), bar='smooth', spinner='classic') as bar: for cmd in cmds: if cmd == "check port": # 端口检查 while True: if check_port(9200): break else: time.sleep(3) time.sleep(3) bar() else: run_cmd(cmd, bar) # 安装 minio def install_minio(): cmds = [ "mv -f ./module/minio/ %s/" % program_path, ] with alive_bar(len(cmds), title=fill_title('安装 minio'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 redis def install_redis(): cmds = [ "tar -zxvf ./module/redis/redis*.tar.gz -C %s/" % program_path, "mv -f %s/redis*/ %s/redis/" % (program_path, program_path), ] with alive_bar(len(cmds), title=fill_title('安装 redis'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 编译安装 keepalived def install_keepalived(): cmds = [ "mkdir -p /etc/keepalived", "mv -f ./module/keepalived/keepalived.conf /etc/keepalived/", "chmod 644 /etc/keepalived/keepalived.conf", ] with alive_bar(len(cmds), title=fill_title('安装 keepalived'), bar='smooth', spinner='classic') as bar: for cmd in cmds: if cmd.startswith("cd"): os.chdir(cmd.split(' ')[1]) bar() else: run_cmd(cmd, bar) # 安装 FFMpeg def install_ffmpeg(): cmds = [ "tar -xvf ./module/ffmpeg/ffmpeg-git-arm64-static.tar", "cp -rf ffmpeg-git-20231006-arm64-static /usr/local/ffmpeg-arm64-static", "echo 'export PATH=$PATH:/usr/local/ffmpeg-arm64-static' >> /etc/profile", "source /etc/profile" ] with alive_bar(len(cmds), title=fill_title('安装 FFMpeg'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 nginx def install_nginx(): cmds = [ "mv -f ./module/nginx %s/" % program_path, ] with alive_bar(len(cmds), title=fill_title('安装 nginx'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装 nodejs 运行环境 def install_nodejs(): cmds = [ "tar -xzvf ./module/node/nvm.tar.gz -C /root/", "echo 'export NVM_DIR=\"$HOME/.nvm\"' >> ~/.bashrc", "echo '[ -s \"$NVM_DIR/nvm.sh\" ] && \. \"$NVM_DIR/nvm.sh\"' >> ~/.bashrc", "echo '[ -s \"$NVM_DIR/bash_completion\" ] && \. \"$NVM_DIR/bash_completion\"' >> ~/.bashrc", "source ~/.bashrc" ] with alive_bar(len(cmds), title=fill_title('安装 nodejs'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 修改config.json配置文件 def update_config(path, mode): # 读取文件内容 with open(path, "r") as file: config_data = json.load(file) config_data["app"]["tenantMode"] = mode # 写入修改后的内容 with open(path, "w") as file: json.dump(config_data, file, indent=4) # 安装 fort def install_program(): cmds = [ # 设置主机名 "echo 'Fort' > /etc/hostname", # 设置登入时的欢迎信息 "mv -f ./module/motd/motd /etc/", # 创建 ES 异常, 未录入指令暂存文件 "touch %s/fortlog/cmdlog" % data_path, # 创建 laswatchdog 进程区分堡垒机与日志审计的文件 "touch %s/fort" % config_path, # 安装堡垒机主进程 "tar -zxvf ./module/fort/jd_analysis.tar.gz -C %s/" % program_path, "tar -zxvf ./module/fort/cmp-agent.tar.gz -C %s/" % program_path, "tar -zxvf ./module/fort/minio-sentinel.tar.gz -C %s/" % program_path, "tar -zxvf ./module/fort/download.tar.gz -C %s/" % program_path, # 放置 Python, C 二进制工具f "mv -f ./module/c_program/ %s/" % program_path, # 放置所有自启动脚本 "mv -f ./module/services/* /etc/init.d/", # 创建 fort 用户, 用于实现 RDP 共享盘 "useradd fort", "echo 'fort:j1d1@cl0vdsec.c0m' | chpasswd", "chown -R fort:fort %s/fort" % data_path ] with alive_bar(len(cmds), title=fill_title('安装 program'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) config_json_path = program_path + '/jd_analysis/config.json' update_config(config_json_path, tenant_flag) # 安装 licence def install_licence(): cmds = [ "mv -f ./module/licence /usr/local/", "chmod 755 -R /usr/local/licence/", "cp -rf ./module/java/licence %s/fort/" % data_path, "mv -f ./module/java/licence.jar %s/java/" % program_path, "mv -f ./module/java/google-authenticator.jar %s/java/" % program_path, ] with alive_bar(len(cmds), title=fill_title('安装 licence'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 设置定时任务 def set_scheduled_tasks(): with alive_bar(1, title=fill_title('设置定时任务'), bar='smooth', spinner='classic') as bar: run_cmd("echo '59 23 * * * %s/shell/deleteLog.sh' > /var/spool/cron/root" % program_path, bar) # 设置服务自启 def auto_server(): chk_servers = [ "mongodb", "elasticsearch", "pm2-init.sh", "agent", "fstart", # "guacd", "licence", "minio", "nginx", "redis", "scanagent", "snmpd", "tomcat", "laswatchdog", ] sys_servers = [ "keepalived", "ntpd" ] with alive_bar(len(chk_servers) + len(sys_servers), title=fill_title('设置服务自启'), bar='smooth', spinner='classic') as bar: for server in chk_servers: run_cmd("chkconfig --add %s" % server, None) run_cmd("chkconfig %s on" % server, bar) for server in sys_servers: run_cmd("systemctl enable %s" % server, bar) # 设置防火墙 def set_firewall(): open_ports = [ "443", "22", "7002", "161", ] with alive_bar(len(open_ports), title=fill_title('设置防火墙'), bar='smooth', spinner='classic') as bar: run_cmd("iptables -F", None) # 清空防火墙 run_cmd("iptables -X", None) # 清空防火墙 run_cmd("systemctl start firewalld", None) for port in open_ports: run_cmd("firewall-cmd --zone=public --add-port=%s/tcp --permanent" % port, bar) run_cmd("firewall-cmd --reload", None) # 安装结束操作 def install_over(): print("安装完毕,重启系统中...") run_cmd("init 6", None) def install_fort(): set_time_zone() creat_dir() set_env() install_tools() enrich_fonts() install_phantomjs() install_watchdog() install_snmpd() install_scripts() # install_guacd() install_tomcat() install_mongodb() install_elastic() install_minio() install_redis() install_keepalived() install_ffmpeg() install_nginx() install_nodejs() install_program() install_licence() set_scheduled_tasks() auto_server() set_firewall() # 安装桌面 def install_desktop(): cmds = [ "tar -xzvf ./module/kylin_dnf_desktop_cache.tar.gz -C /var/cache/", "yum -y -C groupinstall \"带 UKUI GUI 的服务器\"", "systemctl set-default graphical.target", ] with alive_bar(len(cmds), title=fill_title('安装桌面环境'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 安装kvm def install_kvm(): cmds = [ "tar -xzvf ./module/kylin_dnf_kvm_cache.tar.gz -C /var/cache/", "yum -y -C install qemu libvirt virt-install bridge-utils virt-manager", "systemctl start libvirtd", "systemctl enable libvirtd", ] with alive_bar(len(cmds), title=fill_title('安装 kvm'), bar='smooth', spinner='classic') as bar: for cmd in cmds: run_cmd(cmd, bar) # 默认安装 def def_install(): install_init() install_fort() install_over() # 自定义安装 def cus_install(): choice = [ "install fort", "install kvm", "install mongodb (To be implemented)", "install elasticsearch (To be implemented)", "install minio (To be implemented)", "install redis (To be implemented)", "install nginx (To be implemented)", "install tomcat (To be implemented)", "install keepalived (To be implemented)", ] # 用户选择自定义安装后的问题集 questions = [ { "type": "filepath", "name": "fort_path", "message": "Enter path to install(default is /usr/local/fort):", "only_directories": True, }, { "type": "checkbox", "name": "custom_selected", "message": "Custom:", "choices": choice, "validate": lambda result: len(result) >= 1, "invalid_message": "should be at least 1 selection", "instruction": "(select at least 1)", }, ] answers = prompt(questions) # 重新设置部署目录 if answers['fort_path'] != "": global fort_path fort_path = answers['fort_path'] # 安装前初始化 install_init() # 安装用户选择的服务 for selected in answers['custom_selected']: if selected == "install fort": install_fort() elif selected == "install mongodb": # 待实现 pass elif selected == "install elasticsearch": # 待实现 pass elif selected == "install minio": # 待实现 pass elif selected == "install redis": # 待实现 pass elif selected == "install nginx": # 待实现 pass elif selected == "install tomcat": # 待实现 pass elif selected == "install keepalived": # 待实现 pass elif selected == "install kvm": install_desktop() install_kvm() pass else: pass # 安装结束操作 install_over() def Multi_install(): global tenant_flag tenant_flag = "Multi" main() def Single_install(): global tenant_flag tenant_flag = "Single" main() def main(): # 问题集A questions = [ { "type": "list", "name": "install_type", "message": "Select to install:", "choices": ["Default install", "Custom install", "Exit"], "default": None, } ] # 结果集A answers = prompt(questions) # 安装类型(默认安装|自定义安装) install_type = answers["install_type"] if install_type == "Default install": def_install() elif install_type == "Custom install": cus_install() else: pass def tenant(): questions = [ { "type": "list", "name": "tenant_mode", "message": "select tenant mode to install", "choices": ["Multi", "Single"], "default": None, } ] answer = prompt(questions) tenant_mode = answer["tenant_mode"] if tenant_mode == "Multi": Multi_install() elif tenant_mode == "Single": Single_install() else: pass tenant()