一般传统的批量作业(比如批量巡检、批量修改、批量配置、批量部署等)采取的是SSH证书免密登录、账号密码交互登录,第三方组件(如python的saltstack、func主受控端模式)等方式实现对远程主机的访问与控制,一旦密码文件泄露或主控主机(主控端)被攻破,则相关主机相当于完全开放,系统将面临极大的危险。
所要解决的技术问题:
- 解决批量作业过程中,作业主机列表文件密码安全性问题;
- 根据作业主机列表文件解码密钥不同,明确具体作业人员;
- 依靠不同的作业主机列表文件,实现对作业范围的控制问题。
技术方案:
本方法主要分为两个阶段,
与附图对应,描述软件的步骤。
- 将包含主机名(或IP)、账号、密码等信息的主机列表文件上传服务器;
- 运行脚本,根据提示输入加密密钥;
- 读取主机列表文件A,对账号、密码等敏感信息加密,将加密后的主机列表信息写入新的主机列表文件B;
- 删除原主机列表文件A;
- 批量作业开始,提示输入解密密钥(采用对称加密,解密密钥即加密密钥);
- 读取新的主机列表文件B,获取到主机名、用户名密文、密码密文等敏感信息;同时触发邮件通知,告知超级管理员作业人员(根据解密密钥关联明确)、作业主机列表文件、作业脚本类型、作业时间等信息;
- 根据操作人员输入的解密密钥对用户名、密码等敏感信息进行解密,获取到相应的敏感信息明文;
- 使用主机名(或IP)、用户名、密码明文等敏感信息,结合sshpass交互工具,登录远程主机;
- 在远程主机上完成相关作业后返回脚本运行的主机;
- 对主机列表文件中下一台主机执行相同作业;
- 记录作业日志,批量作业结束
关键技术手段以及对应的有益效果
- 利用openssl在base64的应用,采用aes-256-cbc加解密算法结合加密密钥,对主机列表文件中的敏感信息进行加密处理,避免主机信息泄露;
- 采用本方法加密的敏感信息密文,每次加密处理后的密文都不同,较好的防范了对密文的暴力破解;
- 同一批作业主机列表文件,可针对不同作业人员分配不同的加解密密钥,在作业过程中对解密密钥进行二次加密保存,明确作业人员,便于事故追责;
- 批量作业成功触发,即邮件通知超级管理员,告知作业人员、作业范围、作业类型等信息;
对不同作业人员、作业类型,可分配不同的加密后的主机文件列表和解密密钥,实现主机范围和作业人员权限的双重控制。
脚本示例:
#! /bin/bash
####created by 川中胡子
##加密
encrypt(){
#读取文件中的行
cat hosts|while read LINE
do
#将字符串$LINE分割到数组
arr=($LINE)
num=0
# ${arr[@]}存储整个数组
for s in ${arr[@]}
do
if [ $num -eq 0 ];then
ip=$s
elif [ $num -eq 1 ];then
user=$s
else
password=$s
fi
let num++
done
enc_user=`echo ${user}|openssl aes-256-cbc -k ${enc_key} -base64`
enc_pwd=`echo ${password}|openssl aes-256-cbc -k ${enc_key} -base64`
echo "${ip};${enc_user};${enc_pwd}" >>hosts.enc
done
}
##解密
decrypt(){
#清空原解密主机列表文件
>hosts.dec
#读取文件中的行
cat hosts.enc|while read LINE
do
#将字符串$LINE分割到数组
arr=($LINE)
num=0
# ${arr[@]}存储整个数组
for s in ${arr[@]}
do
if [ $num -eq 0 ];then
ip=$s
elif [ $num -eq 1 ];then
enc_user=$s
else
enc_pwd=$s
fi
let num++
done
user=`echo ${enc_user}|openssl aes-256-cbc -d -k ${enc_key} -base64`
password=`echo ${enc_pwd}|openssl aes-256-cbc -d -k ${enc_key} -base64`
echo "${ip};${user};${password}" >>hosts.dec
done
}
main(){
#备份IFS
OLD_IFS="$IFS"
#设置新的分隔符为;
IFS=";"
read -p "Please Input the encrypt key:" enc_key
if [ "$1" == "enc" -o ! -n "$1" ];then
encrypt;
read -p "Encrypt success,will delete hosts,Y or N:" del_confirm
if [ `expr match $del_confirm "[Yy]"` -ne 0 ];then
rm -f hosts
elif [ `expr match $del_confirm "[N|n]"` -ne 0 ];then
echo "You'd better delete the host list file:hosts!"
else
echo "Error input,You'd better delete the host list file:hosts!"
fi
elif [ "$1" == "dec" ];then
decrypt;
else
echo "Error input,You'd better input 'enc' or 'dec',no input means encrypt!"
fi
#恢复IFS
IFS="$OLD_IFS"
}
main $1