1 概述
本文之所以稱之為半自動化霹疫,是因?yàn)樽C書的申請并非日常工作,只是一段時(shí)間才需要申請邪意,同時(shí)九妈,在創(chuàng)建證書和辦法證書的時(shí)候,有些參數(shù)需要根據(jù)用戶的需求自己調(diào)整雾鬼,如證書的有效時(shí)間萌朱,還有,是否給私鑰加密等等策菜,因?yàn)榻心_本設(shè)置為半自動化晶疼,手動輸入一些參數(shù),到達(dá)用戶的需求又憨。當(dāng)然如果環(huán)境是固定翠霍,參數(shù)也是固定,有效時(shí)間固定蠢莺,該腳本配合crontab也可以實(shí)現(xiàn)自動化申請和頒發(fā)等操作
CA中心又稱CA機(jī)構(gòu)壶运,即證書授權(quán)中心(Certificate Authority ),或稱證書授權(quán)機(jī)構(gòu)浪秘。本文將介紹通過openssl這個(gè)工具如何創(chuàng)建根CA蒋情,子CA,證書申請耸携,證書頒發(fā) 和吊銷證書等操作進(jìn)行介紹
2 概念
2.1創(chuàng)建私有CA
openssl的配置文件:/etc/pki/tls/openssl.cnf.這個(gè)配置文件里的相關(guān)配置棵癣,如證書信息匹配策略,證書的相關(guān)文件保存路徑和命名都在這里做規(guī)定夺衍,本文將在文末附屬該配置文件部分重要參數(shù)的介紹
其中狈谊,證書信息匹配策略有三種:匹配、支持和可選
匹配指要求申請?zhí)顚懙男畔⒏鶦A設(shè)置信息必須一致,支持指必須填寫這項(xiàng)申請信息河劝,可選指可有可無
用戶在自己機(jī)器生成證書請求文件后壁榕,將對應(yīng)請求文件發(fā)給服務(wù)器,服務(wù)器收到請求文件后赎瞎,確認(rèn)無誤牌里,將對于進(jìn)行簽發(fā),并把證書發(fā)給申請主機(jī)
2.2 證書申請步驟
證書的申請有如下四個(gè)步驟
a. 生成申請請求
由客戶端自己創(chuàng)建务甥,完成后將生成的文件發(fā)送到證書簽發(fā)機(jī)構(gòu)
b. RA核驗(yàn)牡辽,
RA(Registration Authority),數(shù)字證書注冊審批機(jī)構(gòu)敞临。RA系統(tǒng)是CA的證書發(fā)放态辛、管理的延伸。它負(fù)責(zé)證書申請者的信息錄入挺尿、審核以及證書發(fā)放等工作(安全審計(jì))奏黑。同時(shí),對發(fā)放的證書完成相應(yīng)的管理功能(安全管理)编矾。
c. CA簽署
核驗(yàn)通過后攀涵,在CA服務(wù)器生成證書
d. 獲取證書
將創(chuàng)建完成的證書發(fā)給申請者
3. 實(shí)驗(yàn)步驟
3.1 創(chuàng)建根CA
3.1.1、創(chuàng)建所需要的文件
touch?/etc/pki/CA/index.txt
#生成證書索引數(shù)據(jù)庫文件
echo 01 >/etc/pki/CA/serial
#指定第一個(gè)頒發(fā)證書的序列號
3.1.2 CA自簽證書
要先有私鑰洽沟,才能給自己頒發(fā)證書
生成私鑰,文件名是固定的蜗细,而且目錄也是當(dāng)前固定的目錄裆操,因?yàn)樵谂渲梦募镏付寺窂胶兔Q
cd /etc/pki/CA/
執(zhí)行以下這步后會在該目錄下生成加密的文件
(umask 066; openssl? genrsa? -out ?/etc/pki/CA/private/cakey.pem? -des 3? 2048)
.生成自簽名證書,給自己簽名炉媒,-x509是關(guān)鍵字踪区,表示要自己申請,而且給自己頒發(fā)證書
這里文件的路徑都是有要求的吊骤,以下要輸入密碼
openssl? req -new -x509 -key? /etc/pki/CA/private/cakey.pem?? -days 7300 -out ?/etc/pki/CA/cacert.pem
要輸入密碼缎岗,然后要提交信息
-new: 生成新證書簽署請求
-x509: 專用于CA生成自簽證書
-key: 生成請求時(shí)用到的私鑰文件
-days n:證書的有效期限
-out /PATH/TO/SOMECERTFILE: 證書的保存路徑
3.2 創(chuàng)建子CA
3.2.1子CA上創(chuàng)建私鑰和證書請求文件
方法和根CA基本一致
在 /etc/pki/CA下創(chuàng)建serial 和index.txt
以下加密des3,如果加密白粉,每次辦法都要輸入密碼
作為子CA传泊,不能給自己頒發(fā)證書,要向根CA申請證書鸭巴,不加x509選項(xiàng)
生成subca.csr文件眷细,把這個(gè)文件復(fù)制到服務(wù)器根CA對應(yīng)的目錄/etc/kpi/CA/下
3.2.2根CA上頒發(fā)證書給子CA
這里對根私鑰加了口令,所有要先輸入密碼鹃祖,才能輸入信息
生成文件subca.crt溪椎,把這個(gè)文件拷貝到子CA上,注意,這個(gè)文件拷貝到子CA上的時(shí)候校读,要把名稱改成
cacert.pem沼侣,才能作為服務(wù)器端的私鑰給客戶端來簽名頒發(fā)
到這里服務(wù)器端根CA操作完成,此時(shí)子CA可以給其他的客戶端頒發(fā)證書了
3.2.3驗(yàn)證
找一臺機(jī)器歉秫,向子CA申請證書
生成請求文件蛾洛,這里輸入的選項(xiàng)要和根CA的配置文件策略一致
完成后,將這個(gè)請求文件發(fā)送到子CA上
這個(gè)操作在3.3里講到
3.2.4子CA頒發(fā)證書給客戶端
建議頒發(fā)的證書文件都放在統(tǒng)一的目錄下端考,頒發(fā)的第一個(gè)證書是在serial從01開始
openssl? ca -in rhel5.csr -out certs/rhel5.crt -days 300
出現(xiàn)如下報(bào)錯(cuò)雅潭,有的奇怪,都是henan却特,但是還是報(bào)錯(cuò)扶供,因?yàn)檫@客戶端版本5上的openssl版本和子CA上版本不一致,
導(dǎo)致不兼容裂明。解決頒發(fā)是升級openssl的版本為同一版本
3.3頒發(fā)證書
3.3.1?在需要使用證書的主機(jī)生成證書請求
給web服務(wù)器生成私鑰椿浓,test.key這個(gè)名字可以自命名,但是后綴不能該闽晦,2048是長度
(umask066; opensslgenrsa-out /etc/pki/tls/private/test.key2048)
生成證書申請文件扳碍,用私鑰來生成請求文件,后綴一般建議為csr,和服務(wù)器生成基本一致仙蛉,少了關(guān)鍵字-x509,表示不是自簽名笋敞,而是申請證書
-days 365申請時(shí)間,這個(gè)時(shí)間是沒有意義的荠瘪,因?yàn)槭怯煞?wù)器端頒發(fā)的時(shí)候指定夯巷,客戶端指定時(shí)間是沒有意義的
openssl? req? -new -key /etc/pki/tls/private/test.key -days 365 -out /etc/pki/tls/test.csr
這里的請求文件名(key名)每一次是默認(rèn)要不一樣的,如果要運(yùn)行哀墓,需要更改index.txt.attr里的yes改成no
這里私鑰文件沒有加密des趁餐,所以和服務(wù)器不一樣,不需要回車后填密碼篮绰,只需要回車后填入信息
國家后雷,省,公司這三項(xiàng)是配置模板里規(guī)定match的吠各,所以要和服務(wù)器端一樣
3.3.2?發(fā)送請求文件給CA
將證書請求文件傳輸給CA臀突,可以用scp拷貝到服務(wù)器端對應(yīng)的路徑
3.3.3CA簽署證書,并將證書頒發(fā)給請求者
-days 365這里指定的時(shí)間是有效期贾漏,讓客戶端用多久的時(shí)間惧辈,有效的,不指定默認(rèn)就是服務(wù)配置文件設(shè)定的時(shí)間
commonName = supplied這個(gè)字段是supplied,如果新的證書請求的信息的commonName和之前的請求信息一樣磕瓷,盒齿,那么當(dāng)上一個(gè)請求信息生成的證書還沒有被吊銷的時(shí)候念逞,新的證書將不再生成,生成0字節(jié)的文件
openssl? ca -in /tmp/test.csr?-out /etc/pki/CA/certs/test.crt -days 365
完成后把證書文件發(fā)回給客戶端
3.4吊銷證書
當(dāng)客戶出現(xiàn)異常边翁,服務(wù)器端可以吊銷證書
3.4.1在客戶端獲取要吊銷的證書的serial
openssl? x509 -in /PATH/FROM/CERT_FILE? [-noout|-serial|-subject]
3.4.2在CA上吊銷
根據(jù)客戶提交的serial與subject信息翎承,對比檢驗(yàn)是
否與index.txt文件中的信息一致,吊銷證書:
這一步是在CA服務(wù)上操作的符匾,吊銷后證書狀態(tài)為R
openssl? ca -revoke /etc/pki/CA/newcerts/SERIAL.pem
吊銷后叨咖,要把這個(gè)信息發(fā)布出去“〗海客戶端才知道哪些證書被吊銷
3.4.3指定第一個(gè)吊銷證書的編號
在服務(wù)器根CA上操作
crlnumber證書吊銷列表編號甸各,在index.txt這個(gè)文件里可以看到證書的狀態(tài)
echo 01 > /etc/pki/CA/crlnumber
/etc/pki/CA/crlnumber里保存的數(shù)字表示
接下去要吊銷的是第幾個(gè)證書,如已經(jīng)吊銷了5個(gè)證書焰坪,則當(dāng)前文件保存的就是06趣倾,表示接下去要吊銷第6個(gè)證書
注意:第一次更新證書吊銷列表前,才需要執(zhí)行某饰,如果之前已經(jīng)吊銷過證書儒恋,這個(gè)語句就不需要執(zhí)行了
3.4.4更新證書吊銷列表
把這個(gè)文件發(fā)布到官方網(wǎng)站上,讓所有使用者都知道證書被吊銷了
openssl ca? -gencrl? -out? /etc/pki/CA/crl/crl.pem
3.4.5查看crl文件
執(zhí)行如下語句進(jìn)行查看黔漂,不是必須的步驟
openssl crl?-in? /etc/pki/CA/crl/crl.pem?-noout? -text
4 半自動化腳本
以下的腳本诫尽,將實(shí)現(xiàn)以上5個(gè)步驟,為了方便演示炬守,將操作寫在同一腳本里牧嫉。通過選項(xiàng)操作對應(yīng)的操作。
用戶只需要輸入相關(guān)操作减途,就可以完成CA的搭建和證書申請酣藻,頒發(fā),吊銷等操作
腳本如下
#!/bin/bash
#
#******************************************************************************
#Author:? ? ? ? ? ? ? Sunny
#Date:? ? ? ? ? ? ? ? 2017-09-09
#FileName:? ? ? ? ? ? install_ca.sh
#version:? ? ? ? ? ? ? 1.0
#Your change info:
#Description:? ? ? ? ? For auto create CA,subCA,generate and revoke cert
#Copyright(C):? ? ? ? 2017? All rihts reserved
#*****************************************************************************
CApath=/etc/pki/CA
certpath=/etc/pki/CA/certs
tlspath=/etc/pki/tls
tlsprivatepath=/etc/pki/tls/private
caprivatepate=/etc/pki/CA/private
#check certification info,run below cmd
#openssl x509 -in cent7bbaa.crt -noout -text
#check certification request infomation,run cmd as below
#openssl req -noout -text -in aa.csr
#check certification status,run cmd as below,01 is serial number
#openssl ca -status 01
active_ip(){
actip=$(ip a| grep -E "[0-9]+\/"| cut -d / -f1|sed -nr? 's@.*( [0-9]+\.[^0][0-9]*\.[0-9]+\.[0-9]+)@\1@p'|cut -d " " -f2|head -1)
}
pri_key_name(){
echo "private key name should end with .key,such as clent.key"
read -p "enter your private key name(default:client."$actip".key) " prikey
if [ -z ${prikey:-} ];then
prikey=client."$actip".key
fi
}
cli_csr_name(){
echo "Cert request name should end with .crs,such as clent.csr"
read -p "enter your cert request name(default:client."$actip".csr) " clicsr
if [ -z ${clicsr:-} ];then
clicsr=client."$actip".csr
fi
}
key_length(){
echo "key length should be one of 1024,2048,4096"
read -p "enter your private key length(default:2048): " length
if [ -z ${length:-} ]; then
length=2048
fi
}
root_pre(){
[ -e "$CApath"/index.txt ] || touch? "$CApath"/index.txt
[ -e "$CApath"/serial ] || echo 01 >? "$CApath"/serial
#create a server private key
echo "unless you have modify ca private key name in /etc/pki/tls/openssl.cnf,only use default cakey.pem"read -p "enter your ca private key name accord to openssl.cnf (default:cakey.pem) " cakey
if [ -z ${cakey:-} ];then
cakey=cakey.pem
fi
key_length
if [ -e "$caprivatepate"/"$cakey"? ] ;then
echo "The server already have private key,$cakey, under "$caprivatepate"/,please check"
else
umask 066;
read -p "enter yes to encrypt private key,other enter will no enrypt: " yorn
if [ "$yorn" = yes ];then
read -p "enter encrypt key word(eg:-des3): " encry
openssl genrsa -out "$caprivatepate"/"$cakey" "$encry" "$length"
else
openssl genrsa -out "$caprivatepate"/"$cakey"? "$length"
fi
umask 022;
fi
}
echo "Enter 1 : run at root CA server and rootca_sig_itself"
echo "Enter 2 : run at sub_server,generate a private key and signature request file,and send request file to root CA "
echo "Enter 3 : run at client host,generate certification requst file and send to server auto"
echo "Enter 4 : run at server,generate certification and send to client auto"
echo "Enter 5 : run at server,to revoke some certification"
read -p "Please input your choice: " choice
case $choice in
1)
root_pre;
#generate a signature certificate for itself,-x509 is key work,means it signature to itself
echo "unless you have modify ca? signature certificate name in /etc/pki/tls/openssl.cnf,only use default cacert.pem"
read -p "enter your ca signature cer name accord to openssl.cnf (default:cacert.pem) " cacert
if [ -z ${cacert:-} ];then
cacert=cacert.pem
fi
if [ -e "$CApath"/"$cacert"? ] ;then
echo "The server already have signature certificate,"$cacert" under "$CApath",please check"
else
openssl? req -new -x509 -key "$caprivatepate"/"$cakey"? -days 7300 -out? "$CApath"/"$cacert"
fi
;;
2)
root_pre;
#generate a signature certificate request file and send to root CA
read -p "enter your ca signature cer request file? (default:subca.csr): " subcacert
if [ -z ${subcacert:-} ];then
subcacert=subca.csr
fi
if [ -e "$CApath"/"$subcacert"? ] ;then
echo "The sub ca already have signature certificate,"$subcacert"under "$CApath",please check"
else
openssl? req -new? -key "$caprivatepate"/"$cakey"? -days 7300 -out? "$CApath"/"$subcacert"
fi
#send request file to root CA
read -p "which root CA would you send(default:192.168.32.61): " serip
if [ -z ${serip:-} ];then
serip=192.168.32.61
fi
expect -c "
spawn? scp? "$CApath"/"$subcacert"? root@"$serip":"$CApath"/certs/
expect {
\"*assword\" {set timeout 500; send \"Pass1234\r\"; }
\"yes/no\" { send \"yes\r\"; exp_continue; }
}
expect eof"
;;
3)
echo "Please check whether you are in client"
#client generate private key
active_ip
pri_key_name
cli_csr_name
key_length
if [ -e "$tlsprivatepath"/"$prikey"? ] ;then
echo "The client already have private key "$prikey" under "$tlsprivatepat",please check"
else
umask 066;
if [ "$yorn" = yes ];then
read -p "enter encrypt key word(eg:-des3): " encry
openssl genrsa -out "$tlsprivatepath"/"$prikey" "$encry" "$length"
else
openssl genrsa -out "$tlsprivatepath"/"$prikey"? "$length"
fi
umask 022;
fi
#generate a signature certificate to root ca,without -x509.
if [ -e "$tlspath"/"$clicsr"? ] ;then
echo "The client already have signature certificate request file,"$clicsr" under "$tlspath",please check"
else
openssl req -new -key "$tlsprivatepath"/"$prikey" -out "$tlspath"/"$clicsr"
fi
#send request file to CA
read -p "which CA would you send(default:192.168.32.61): " serip
if [ -z ${serip:-} ];then
serip=192.168.32.61
fi
expect -c "
spawn? scp? "$tlspath"/"$clicsr" root@"$serip":"$CApath"/certs/
expect {
\"*assword\" {set timeout 500; send \"Pass1234\r\"; }
\"yes/no\" { send \"yes\r\"; exp_continue; }
}
expect eof"
;;
4)
read -p "enter which requst file in "$CApath"/certs you want want server to generate as certification(eg:cent7.csr): " clientrsq
read -p "enter new client cetification name(eg:cent7.crt): " crtname
[ -e "$CApath"/certs/"$crtname" ] && { echo $crtname exist,please check;exit 6; }
read -p "enter many days would the cert be avlid(eg:365): " days
if [ -e "$CApath"/certs/"$clientrsq" ];then
#attention,no only $crtname be generated,but also serial.pem file will be generate under dir newcerts
openssl ca -in? "$CApath"/certs/"$clientrsq" -out "$CApath"/certs/"$crtname" -days "$days"
else
echo "$clientrsq does no exist in "$CApath"/certs,please check"
fi
read -p "which client would you send(eg:192.168.32.61): " clip
expect -c "
spawn? scp? "$CApath"/certs/"$crtname"? root@"$clip":"$tlspath"
expect {
\"*assword\" {set timeout 500; send \"Pass1234\r\"; }
\"yes/no\" { send \"yes\r\"; exp_continue; }
}
expect eof"
;;
5)
read -p "Please input the serial number you want to revoke(eg:03): " sernum
echo "you can run cmd? openssl x509 -in cent7bt.crt -noout -text? to check the serial number,cent7bt.crt is the certification you want to revoke"
openssl ca -revoke /etc/pki/CA/newcerts/"$sernum".pem
crlnum=$(cat /etc/pki/CA/crlnumber)
[ -z $crlnum ] && echo 01 > /etc/pki/CA/crlnumber;
openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem;
#check the the crl list
#openssl? crl? -in /etc/pki/CA/crl/crl.pem? -noout? -text
;;
*)
echo? "your input is wrong,please check"
;;
esac
unset ip
unset crtname
unset CApath
unset clinetsrq
?
5?/etc/pki/tls/openssl.cnf 講解
本附錄只針對一些重要字段用中文做了備注观蜗,內(nèi)容如下
/etc/pki/tls/openssl.cnf
CA的配置文件,這個(gè)文件文件很關(guān)鍵衣洁,配置和CA密切相關(guān)
[ CA_default ]? 這里新創(chuàng)建的文件名必須一樣墓捻,如果要改,就要跟defaults一樣
dir? ? = /etc/pki/CA? ? ? # Where everything is kept坊夫,CA工作目錄砖第,CA信息保存的目錄
#
certs? ? ? = $dir/certs? ? ? ? # Where the issued certs are kept,定義一個(gè)變量
crl_dir? ? = $dir/crl? ? ? # Where the issued crl are kept环凿,證書吊銷列表
database? ? = $dir/index.txt? ? # database index file.這個(gè)是一個(gè)文件梧兼,保存證書數(shù)據(jù)庫,如頒發(fā)了哪些證書智听,證書編號羽杰,證書狀態(tài)等信息保存在這里渡紫,這個(gè)文件默認(rèn)沒有,要手工創(chuàng)建一個(gè)空文件考赛,頒發(fā)證書的時(shí)候惕澎,會手動頒發(fā),沒有空文件的話颜骤,頒發(fā)的時(shí)候會報(bào)錯(cuò)
#unique_subject = no? ? ? ? ? ? # Set to 'no' to allow creation of
# several ctificates with same subject.
new_certs_dir? = $dir/newcerts? ? # default place for new certs.默認(rèn)新證書的放置目錄唧喉,這個(gè)文件是自動生成的,用數(shù)字編號
certificate = $dir/cacert.pem? # The CA certificate忍抽,CA自己的證書八孝,根CA自己給自己頒發(fā),子CA上級頒發(fā)
serial? ? ? = $dir/serial? ? ? # The current serial number鸠项,要手動創(chuàng)建干跛,當(dāng)前系列號,是一個(gè)16進(jìn)制數(shù)锈锤,實(shí)際意義是下一個(gè)證書的編號驯鳖,默認(rèn)是從00開始,可以自己指定開始的值久免,必須是16進(jìn)制數(shù)
crlnumber? = $dir/crlnumber? ? # the current crl number浅辙,證書吊銷編號,也是指下一個(gè)證書被吊銷的編號阎姥,即下一個(gè)被吊銷的證書的編號
# must be commented out to leave a V1 CRL
crl? ? = $dir/crl.pem? ? ? # The current CRL
private_key = $dir/private/cakey.pem# The private key记舆。CA的私鑰
RANDFILE? ? = $dir/private/.rand? ? # private random number file,隨機(jī)數(shù)
x509_extensions = usr_cert? ? ? # The extentions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt? ? = ca_default? ? ? ? # Subject Name options呼巴,命名方式
cert_opt? ? = ca_default? ? ? ? # Certificate field options
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions? ? = crl_ext
default_days? ? = 365? ? ? ? ? # how long to certify for泽腮,證書的有效期,可以指定
default_crl_days= 30? ? ? ? ? ? # how long before next CRL衣赶,CRL的有效期
default_md? = default? ? ? # use public key default MD
preserve? ? = no? ? ? ? ? ? # keep passed DN ordering
# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy? ? ? = policy_match诊赊,策略,由下面來指定府瞄,表示客戶要申請證書的時(shí)候碧磅,要求客戶提供的信息
# For the CA policy
[ policy_match ]? 這個(gè)是系統(tǒng)默認(rèn)的策略
countryName? ? = match? 國家,match是必須匹配遵馆,兩邊都是同樣的信息鲸郊,其他的可以不一樣
stateOrProvinceName = match? 省,match如果不一樣货邓,就會拒絕秆撮,不會頒發(fā)證書
organizationName? ? = match? 組織
organizationalUnitName? = optional 部門
commonName? ? ? = supplied? 通用名,如網(wǎng)站服務(wù)器的域名换况,一般是嚴(yán)格匹配职辨,也可以寫成泛域名盗蟆,申請費(fèi)用比較貴
emailAddress? ? ? ? = optional? ,可選項(xiàng)拨匆,不強(qiáng)制要求一樣
# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ] 給外部使用姆涩,不用match選項(xiàng),都不要求完全一樣
countryName? ? = optional
stateOrProvinceName = optional
localityName? ? ? ? = optional
organizationName? ? = optional
organizationalUnitName? = optional
commonName? ? ? = supplied
emailAddress? ? ? ? = optional
[ req ]
default_bits? ? ? ? = 2048
default_md? ? ? = sha1
default_keyfile? ? = privkey.pem
distinguished_name? = req_distinguished_name
attributes? ? ? = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
6 總結(jié)
由于openssl這個(gè)命令很強(qiáng)大惭每,有大量的參數(shù)骨饿,本文只是列出的參數(shù)是生成很頒發(fā)等必須用到的幾個(gè)參數(shù),如果需要有更多其他選項(xiàng)台腥,用戶可自行添加