小黑又开始折腾新的东西了,上周刚学习完openssl建设私有CA,周六就花了点时间写了这个脚本,时间仓促,搞完就去撸DNS了,如果有啥BUG请见谅,本脚本纯属练习,用来练openssl、awk、
小黑又开始折腾新的东西了,上周刚学习完openssl建设私有CA,周六就花了点时间写了这个脚本,时间仓促,搞完就去撸DNS了,如果有啥BUG请见谅,本脚本纯属练习,用来练openssl、awk、sed等知识点。
先来介绍下建设私有CA的简单步骤(以下路劲为默认安装路径):
(1) 生成私钥;
~]# (umask 077; openssl genrsa -out /etc/pki/CA/private/cakey.pem 4096)
(2) 生成自签证书;
~]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/cacert.pem -days 3655
-new:生成新证书签署请求;
-x509:生成自签格式证书,专用于创建私有CA时;
-key:生成请求时用到的私有文件路径;
-out:生成的请求文件路径;如果自签操作将直接生成签署过的证书;
-days:证书的有效时长,单位是day;
(3) 为CA提供所需的目录及文件;
~]# mkdir -pv /etc/pki/CA/{certs,crl,newcerts}
~]# touch /etc/pki/CA/{serial,index.txt}
~]# echo 01 > /etc/pki/CA/serial
本脚本通过分析openssl.conf文件来得到相关路径,再通过命令建设私有CA,自签证书的相关信息通过数组保存通过echo命令传给生成自签证书的命令。具体的脚本内容如下:
#!/bin/bash
#Program:
# This program is used to creat CA
#History:
#2016/4/9 xiaohei v1.0
#blog:http://zww577593841.blog.51cto.com/6145493/1750689
#
#私有CA存放目录
# dir
#已颁发的证书的存放目录
# certs
#已吊销的证书的存放目录
# crl_dir
#新证书的存放目录
# new_certs_dir
#当前证书的序列号保存文件
# serial
#已颁发证书的索引文件
# database
#CA的自签证书
# certificate
#CA的私钥
# private_key
#openssl.conf配置文件的位置
declare conffile=/etc/pki/tls/openssl.cnf
#定义一个数组保存CA配置文件中需要保存的一些属性名称
declare -a var
var=("dir" "certs" "crl_dir" "new_certs_dir" "serial" "database" "certificate" "private_key")
#临时文件和目录
declare -a tempfile
tempfile=("./ca_default.txt" "./ca_value.txt")
#必要的文件和目录
declare -a creatfile
declare -a creatdir
creatfile=("serial" "database")
creatdir=("certs" "crl_dir" "new_certs_dir")
#openssl.conf关于CA的相关属性
declare -A ca
#自签证书需要填写的信息:国家(大写的两个字母);省;市;公司;部门;主机名;邮箱(可选)
cainfo=("CN" "Beijing" "Beijing" "blackboy" "ops" "ca.blackboy.com" "blackboy@163.com" )
#信号捕捉
trap 'mytrap' INT
mytrap(){
clean_temp
echo -e "\033[31mexit\033[0m"
exit
}
#清理临时文件和变量及数组
clean_temp(){
for((i=0;i<${#tempfile[*]};i++));do
mv -f ${tempfile[$i]} /tmp/
done
unset -v conffile
unset -v var
unset -v tempfile
unset -v ca
unset -v creatfile
unset -v creatdir
unset -v cainfo
}
#分析文件或者目录是否存在
analyse_file_dir(){
if [ -f "$1" ];then
echo -e "\033[32mfile $1 exist\033[0m"
return 0
elif [ -d "$1" ];then
echo -e "\033[32m$1 is exist\033[0m"
return 0
else
echo -e "\033[31m$1 is not exist\033[0m"
return 1
fi
}
#创建需要的文件
creat_file(){
touch "$1"
analyse_file_dir "$1" &> /dev/null && echo -e "\033[32mcreat $1 successful\033[0m" || return 1
return 0
}
#创建需要的目录
creat_dir(){
mkdir -pv "$1"
analyse_file_dir "$1" &> /dev/null && echo -e "\033[33mcreat $1 successful\033[0m" || return 1
return 0
}
#分析并获得conffile变量保存的路径所指的openssl.conf文件的一些信息
analyse_conf(){
analyse_file_dir $1 || exit 1
#通过sed获得配置文件自己需要的部分的内容
sed -n '/\[ CA_default/,/##/s@[#].*@ @gp' $1 | sed 's/=/ = /g' > ${tempfile[0]}
#通过awk格式化上步得到内容并保存到临时文件中
awk '/^[^[:space:]]/{a[$1]=$3}END{for(i in a){printf""i"=%s\n",a[i]};}' ${tempfile[0]} > ${tempfile[1]}
#定义局部变量保存dir项的路径
local dir=$(sed -n 's/^dir=//p' ${tempfile[1]})
#配置文件中$dir代替了dir的路径,还原为其真实路径,并保存在临时文件中
sed -i "s@[$]dir@$dir@g" ${tempfile[1]}
echo "The current OpenSSL configuration"
cat ./ca_value.txt
echo "#################################"
#把配置文件中查找到的属性信息保存到关联数组中
for((i=0;i<${#var[*]};i++));do
ca["${var[$i]}"]=$(awk -F"=" '{if($1~/^'${var[$i]}'$/){print $2}}' ${tempfile[1]})
done
}
#创建私钥
creat_private_key(){
#取文件所在目录名,如果目录不存在则创建
analyse_file_dir ${1%/*} || creat_dir ${1%/*} || return 1
#创建私钥,大小为4096,并将创建的私钥文件的权限设置为只有当前用户可读写
(umask 077; openssl genrsa -out $1 4096)
#分析私钥是否创建完成
analyse_file_dir $1 &> /dev/null && echo -e "\033[32mcreat private key successful\033[0m " || return 1
echo "ok"
return 0
}
#生成自签证书
creat_cacert(){
local info
#生成签发证书时要填写的信息
for ((i=0;i<${#cainfo[*]};i++));do
info="$info${cainfo[$i]}\n"
done
#签发证书
echo -e "$info" | openssl req -new -x509 -key $1 -out $2 -days 3655
#分析证书是否正常生成
analyse_file_dir $2 &> /dev/null && echo -e "\033[32mcreat cacert successful\033[0m " || return 1
}
#如果openssl.conf文件不存在直接退出
analyse_conf $conffile || exit 1
#创建必要的文件和目录,如果创建失败则退出
for((i=0;i<${#creatfile[*]};i++));do
analyse_file_dir ${ca[${creatfile[$i]}]} || creat_file ${ca[${creatfile[$i]}]} || exit 1
done
for((i=0;i<${#creatdir[*]};i++));do
analyse_file_dir ${ca[${creatdir[$i]}]} || creat_dir ${ca[${creatdir[$i]}]} || exit 1
done
#向证书编号文件serial中添加编号
echo "01 >>>>> ${ca[serial]}"
echo "01" > ${ca[serial]}
#调用函数创建CA的私钥
creat_private_key ${ca[private_key]} || exit 1
#创建CA自签证书
creat_cacert ${ca[private_key]} ${ca[certificate]} || exit 1
#查看证书内容
openssl x509 -in ${ca[certificate]} -noout -serial -subject
#清理安装过程中生成的变量、数组、和临时文件
clean_temp
脚本的运行结果如下:
时间仓促,未解释的部分,请见谅。