前言
在不同項(xiàng)目環(huán)境配置內(nèi)部https服務(wù)的時(shí)候需要使用不同的證書,為了簡(jiǎn)化生成證書時(shí)手動(dòng)執(zhí)行命令的繁瑣,寫了一個(gè)shell腳本來(lái)生成證書文件。
腳本說明
shell腳本使用說明
shell腳本的使用說明如下:
- 腳本中使用openssl命令生成證書,執(zhí)行前需要保證openssl命令可用。
- 腳本在centos 7和ubuntu 16.04中已經(jīng)驗(yàn)證通過;在windows中的git bash里無(wú)法正確執(zhí)行,不要在windows上的git bash里面執(zhí)行腳本。
- 腳本命令格式如下:
./gen-cert.sh -a 算法 -d 域名 -n 證書文件名
- 腳本中的參數(shù)說明:
- -a 生成的證書中使用的算法,有rsa和ecc兩種選項(xiàng),rsa會(huì)生成2048位的key,ecc生成prime256v1的key;
- -d 證書中的域名,可以支持寫多個(gè)域名,多個(gè)域名使用逗號(hào)分隔。第一個(gè)域名會(huì)作為CN(common name),這個(gè)參數(shù)里面所有的域名會(huì)寫入證書的SAN(通過這可以一個(gè)證書支持多個(gè)不同域名)。
- -n 生成的服務(wù)器證書文件名。腳本生成的證書文件都放在certs目錄下,如果目錄下已經(jīng)存在同名的證書文件則會(huì)跳過。第二次執(zhí)行腳本時(shí),如果-n參數(shù)指定為與第一次不同的名稱,則會(huì)使用第一次生成的CA證書簽發(fā)新的服務(wù)器證書。
- -h 查看腳本幫助。
shell腳本內(nèi)容
shell腳本的內(nèi)容如下:
#!/bin/bash
usage()
{
echo "Usage: $0 [-a [rsa|ecc]] [-d <domain>] [-n <name>] [-h]"
echo " Options:"
echo " -a algorithm.[rsa|ecc]"
echo " -d domain.example: xxx.com,abc.org,*.abc.org"
echo " -n server key name"
echo " -h help"
exit 1
}
srv_key_name="server"
while getopts "a:d:n:h" arg #選項(xiàng)后面的冒號(hào)表示該選項(xiàng)需要參數(shù)
do
case $arg in
a)
alg=$OPTARG #算法
;;
d)
all_domain=$OPTARG #域名,逗號(hào)分隔
;;
n)
srv_key_name=$OPTARG #服務(wù)器證書名稱
;;
h)
usage
exit 0
;;
?) #當(dāng)有不認(rèn)識(shí)的選項(xiàng)的時(shí)候arg為?
usage
exit 1
;;
esac
done
domain="domain.com"
san="DNS:*.${domain},DNS:${domain}"
if [ -n "${all_domain}" ]; then
#分割域名
OLD_IFS="$IFS"
IFS=","
domain_array=($all_domain)
IFS="$OLD_IFS"
domain_len=${#domain_array[@]}
domain=${domain_array[0]}
san=""
for ((i=0;i<domain_len;i++))
{
if [ $i = 0 ];then
san="DNS:${domain_array[i]}"
else
san="${san},DNS:${domain_array[i]}"
fi
}
fi
ca_subj="/C=CN/ST=Hubei/L=Wuhan/O=MY/CN=MY CA"
server_subj="/C=CN/ST=Hubei/L=Wuhan/O=MY/CN=${domain}"
#其中C是Country,ST是state,L是local,O是Organization,OU是Organization Unit,CN是common name
days=14610 # 有效期40年
echo "san:${san}"
sdir="certs"
ca_key_file="${sdir}/ca.key"
ca_crt_file="${sdir}/ca.crt"
srv_key_file="${sdir}/${srv_key_name}.key"
srv_csr_file="${sdir}/${srv_key_name}.csr"
srv_crt_file="${sdir}/${srv_key_name}.crt"
srv_p12_file="${sdir}/${srv_key_name}.p12"
srv_fullchain_file="${sdir}/${srv_key_name}-fullchain.crt"
cfg_san_file="${sdir}/san.cnf"
#algorithm config
if [[ ${alg} = "rsa" ]] ; then
rsa_len=2048
elif [[ ${alg} = "ecc" ]] ; then
ecc_name=prime256v1
else
usage
exit 1
fi #ifend
echo "algorithm:${alg}"
mkdir -p ${sdir}
if [ ! -f "${ca_key_file}" ]; then
echo "------------- gen ca key-----------------------"
if [[ ${alg} = "rsa" ]] ; then
openssl genrsa -out ${ca_key_file} ${rsa_len}
elif [[ ${alg} = "ecc" ]] ; then
openssl ecparam -out ${ca_key_file} -name ${ecc_name} -genkey
fi #ifend
openssl req -new -x509 -days ${days} -key ${ca_key_file} -out ${ca_crt_file} -subj "${ca_subj}"
fi
if [ ! -f "${srv_key_file}" ]; then
echo "------------- gen server key-----------------------"
if [[ ${alg} = "rsa" ]] ; then
openssl genrsa -out ${srv_key_file} ${rsa_len}
elif [[ ${alg} = "ecc" ]] ; then
openssl ecparam -genkey -name ${ecc_name} -out ${srv_key_file}
fi #ifend
openssl req -new -sha256 -key ${srv_key_file} -out ${srv_csr_file} -subj "${server_subj}"
printf "[ SAN ]\nauthorityKeyIdentifier=keyid,issuer\nbasicConstraints=CA:FALSE\nkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment\nsubjectAltName=${san}" > ${cfg_san_file}
openssl x509 -req -days ${days} -sha256 -CA ${ca_crt_file} -CAkey ${ca_key_file} -CAcreateserial -in ${srv_csr_file} -out ${srv_crt_file} -extfile ${cfg_san_file} -extensions SAN
cat ${srv_crt_file} ${ca_crt_file} > ${srv_fullchain_file}
openssl pkcs12 -export -inkey ${srv_key_file} -in ${srv_crt_file} -CAfile ${ca_crt_file} -chain -out ${srv_p12_file}
fi
腳本執(zhí)行示例
- 執(zhí)行命令下面命令生成證書,生成pkcs12格式證書過程中會(huì)提示輸入證書密碼,請(qǐng)保持兩次輸入一致。雖然輸入密碼時(shí)可以直接回車設(shè)為空,由于某些使用證書的場(chǎng)景必須要密碼,所以最好設(shè)置一個(gè)密碼。生成的文件中ca.crt與ca.key為CA證書的公鑰與私鑰;test.crt與test.key為服務(wù)器證書的公鑰與私鑰;test.p12為pkcs12格式的文件,包含了公私鑰。
./gen-cert.sh -a ecc -d test.com,a.com,*.a.com -n test

生成證書
- 生成的服務(wù)器證書中“頒發(fā)給”為test.com,即-d參數(shù)中指定的第一個(gè)域名。

證書信息-常規(guī)
- 簽名算法采用的ECC算法。

證書信息-詳細(xì)信息-算法
- 使用者可選名稱包含了-d參數(shù)中指定的所有域名。

證書信息-詳細(xì)信息-SAN