Linux 自动更新sshkey秘钥 kown_host文件

需求说明

  1. 二进制文件,Linux常见操作系统支持
  2. 自动读取现有kown_host文件中的主机地址和端口
  3. 支持通过配置文件更新key

源码

import paramiko
import os
import argparse
# 重写的父类方法,用来解决22端口默认key写入格式为[xxx.xxx.xxx.xx]:22的问题
class CustomAutoAddPolicy(paramiko.MissingHostKeyPolicy):
    def __init__(self):
        self.host_keys = {}
    def missing_host_key(self, client, hostname, key):
        self.host_keys[hostname] = key
        # 处理主机地址,仅保留IP地址
        if ':' in hostname:
            hostname = hostname.split(':')[0].strip('[]')
        client._host_keys.add(hostname, key.get_base64(),key)


def connect(host, port):
    # ecdsa-sha2-nistp256 ssh-ed25519 ssh-dss  ssh-rsa ssh-ed25519常见这四种秘钥协商
    # filename = os.path.expanduser("~/.ssh/known_hosts")
    # if not os.path.exists(os.path.dirname(filename)):
    #     os.makedirs(os.path.dirname(filename))
    ssh_client = paramiko.SSHClient()
    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        ssh_client.connect(hostname=host, port=port, username='root', password='xxx')
    except Exception as e:
        print(e)
        return ssh_client
    return ssh_client
# 去除重复行
def remove_duplicate_lines_inplace(file_path):
    with open(file_path, 'r+') as file:
        lines = file.readlines()
        # 使用 set 去除重复行,并保持原有顺序
        unique_lines = list(set(lines))
        # 移动文件指针到文件开始,截断文件内容
        file.seek(0)
        file.truncate()
        # 写入去重后的内容
        file.writelines(unique_lines)

def write_konw(client,host):
    filename = os.path.expanduser("~/.ssh/known_hosts")
    del_ip(filename=filename,text_to_filter=host)
    with open(filename, "a") as f:
        for hostname, keys in client._host_keys.items():
            for keytype, key in keys.items():
                f.write(
                    "{} {} {}\n".format(
                        hostname, keytype, key.get_base64()
                    )
                )
        print(f'更新{hostname}秘钥成功')

def read_konw_host(filename="~/.ssh/known_hosts"):
    with open(os.path.expanduser(filename),encoding='utf-8') as f:
        try:
            tmp_list = []
            for line in f.readlines():
                if line == '\n':
                    continue
                if ':' in line:
                    line = line.split(' ')
                    info = line[0]
                    host = info.split(':')[0].strip('[]')
                    port = info.split(':')[1]
                    Pubkey_model = line[1]
                    key = line[2]
                else:
                    line = line.split(' ')
                    host = line[0]
                    port = 22
                    Pubkey_model = line[1]
                    key = line[2]
                tmp_list.append([host,port,Pubkey_model,key])
            return tmp_list
        except Exception as e:
                print('其他错误,请检查原始文件格式是否正确')

def read_config(filename):
    with open(os.path.expanduser(filename),encoding='utf-8') as f:
        try:
            tmp_list = []
            for line in f.readlines():
                line = line.split(' ')
                host = line[0]
                port = line[1]
                tmp_list.append([host,port])
            return tmp_list
        except Exception as e:
                print('其他错误,请检查配置文件格式是否正确')


def del_ip(filename, text_to_filter):
    with open(filename, 'r+', encoding='utf-8') as file:
        lines = file.readlines()
        # 将文件指针移动到文件开头
        file.seek(0)
        # 过滤掉包含指定文本的行
        filtered_lines = [line for line in lines if text_to_filter not in line]
        print(filtered_lines)
        # 将结果写回原文件
        file.truncate()
        file.writelines(filtered_lines)

def auto_flush_key_from_kown_host():
    filename = os.path.expanduser("~/.ssh/known_hosts")
    current_list = read_konw_host()
    for i in current_list:
        connect_object= connect(i[0],i[1])
        host_keys = connect_object._host_keys
        if len(host_keys) != 0:
            for host, keys in host_keys.items():
                for keytype, key in keys.items():
                    del_ip(filename=filename,text_to_filter=str(i[0]))
                    with open(file=filename,mode='a',encoding='utf-8') as f:
                        new_key =(f'{host} {keytype} {key.get_base64()}\n')
                        f.write(new_key)
                        print(f'更新{i[0]}密钥成功')
        else:
            print(f'更新{i[0]}密钥错误')
    remove_duplicate_lines_inplace(filename)

def custom_config_reflush_key(config_file_name):
    print(f'当前配置文件路径:{config_file_name}')
    current_list = read_config(config_file_name)
    filename = os.path.expanduser("~/.ssh/known_hosts")
    for i in current_list:
        connect_object= connect(i[0],int(i[1]))
        host_keys = connect_object._host_keys
        if host_keys:
            for host, keys in host_keys.items():
                for keytype, key in keys.items():
                    # print(f"Host: {host}")
                    # print(f"Key Type: {keytype}")
                    # print(f"Key: {key.get_base64()}")
                    del_ip(filename=filename,text_to_filter=str(i[0]))
                    with open(file=filename,mode='a',encoding='utf-8') as f:
                        new_key =(f'{host} {keytype} {key.get_base64()}\n')
                        f.write(new_key)
                        print(f'更新{i[0]}密钥成功')
        else:
            print(f'更新{i[0]}密钥错误')
    remove_duplicate_lines_inplace(filename)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,description="SSH秘钥自动更新V1.0")
    parser.description = """
    SSH秘钥自动更新V1.0
    使用方法:
    1.默认模式:不添加任何参数,将自动从~/.ssh/known_hosts文件中读取IP地址和端口并自动更新密钥。
    2.手动模式:指定host和port进行手动更新
    3.配置模式:使用-f参数指定配置文件,配置文件正确格式为【IP 端口】的形式
    """
    parser.add_argument("host", nargs="?", help="主机名称 or IP地址")
    parser.add_argument("-port", type=int, default=22, help="SSH 服务端口  (default: 22)")
    parser.add_argument("-f", type=str, help="读取文件")
    args = parser.parse_args()
    if args.host:
        connect(args.host, args.port)
        current_client_connect = connect(args.host, args.port)
        write_konw(current_client_connect,host=args.host)
    elif args.f:
        print("配置模式:自动读取配置文件中的主机地址和端口然后更新key")
        custom_config_reflush_key(config_file_name=args.f)
    else:
        print("默认模式:自动读取[know_host]文件并更新")
        auto_flush_key_from_kown_host()

成品打包下载

见顶部资源绑定区

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值