生成PKI公私密钥对及数字证书
PKI体系是数字证书的基础。
PKI体系是数字证书的基础。
X.509
X.509是国际电联ITU-T的标准,用于规范基于公钥密码体系PKI(public key infrastructure)体系的数字证书管理。其标准主要由RFC5280[1]描述,现在常用的数字证书正是基于X.509标准的。
证书结构
X.509 v3数字证书的结构如下:
1 | Certificate |
数字证书编码和扩展名
数字证书使用文件作为载体,目前有两种编码方法,多种文件扩展名。
编码格式(同时可以作为对应编码格式的扩展名)
DER(Distinguished Encoding Rules)
DER[4]是一种二进制编码格式。可以使用.der作为DER格式编码的数字证书的文件扩展名。通常应该这样说,”我有一个DER编码格式的数字证书”,而不是,”我有一个DER数字证书”。
PEM(Privacy-Enhanced Mail)
PEM采用BASE64文本编码格式,用于不同类型的X.509 v3数字证书。PEM一般以BEGIN XXX开头,以END XXX结束。
比如:
使用PEM格式存储的数字证书:
1 | -----BEGIN CERTIFICATE----- |
使用PEM格式存储的私钥
1 | -----BEGIN PRIVATE KEY----- |
或者
1 | -----BEGIN RSA PRIVATE KEY----- |
使用PEM格式存储的证书请求文件
1 | -----BEGIN CERTIFICATE REQUEST----- |
证书文件扩展名
.crt
CeRTificate的缩写,用于证书文件,可以是DER或者PEM编码格式。
.cer
CERtificate的缩写,用于证书文件,可以是DER或者PEM编码格式。
.key
用于存储私钥或者公钥,可以使DER或者PEM编码格式。
CRT文件和CER文件只有在使用相同编码的时候才可以安全地相互替代。
查看数字证书
PEM编码格式证书
1 | $ openssl x509 -in cert.(pem cer crt) -text -noout |
DER编码格式证书
1 | $ openssl x509 -in cert.(der cer crt) -inform der -text -noout |
数字证书编码格式转换
PEM to DER
1 | $ openssl x509 -in cert.crt -outform der -out cert.der |
DER to PEM
1 | openssl x509 -in cert.crt -inform der -outform pem -out cert.pem |
其他名词
PKCS#11是目前最常用的标准之一。
PKCS#11为加密令牌定义了一组平台无关的API ,如硬件安全模块和智能卡。PKCS#11称为Cyptoki,定义了一套独立于技术的程序设计接口,USBKey安全应用需要实现的接口。由于没有一个真正的标准加密令牌,这个API已经发展成为一个通用的加密令牌的抽象层。 PKCS#11 API定义最常用的加密对象类型(RSA密钥,X.509证书,DES /三重DES密钥等)和所有需要使用的功能,创建/生成,修改和删除这些对象。pkcs#11只提供了接口的定义, 不包括接口的实现,一般接口的实现是由设备提供商提供的,如usbkey的生产厂商会提供 符合PKCS#11接口标准的API的实现。这样你只要通过接口调用API函数即可实现其功能。
References:
[1]rfc5280
[2]X.509
[3]DER vs. CRT vs. CER vs. PEM Certificates and How To Convert Them
[4]DER (Distinguished Encoding Rules) certificate encoding
===
[erq]
公钥经CA签名后才成为数字证书。数字证书用来保证公钥是可信任的,这是一个始自CA根证书(root certificate)的信任链。CA根证书内置CA的公钥和身份信息,CA的根证书都是自签的。CA使用其私钥签发数字证书,也就是将申请人的公钥和身份信息按X.509标准进行数字签名。比如使用浏览器浏览https站点时,就可以使用内置的CA根证书来验证服务器端的数字证书是不是有效。当然使用数字证书的领域包含但不限于web,任何需要身份鉴别的地方都可以使用数字证书。
Jenkins是开源的CI(Continuous Integration)服务器。
安装
编辑文件 /etc/apt/sources.list.d/jenkins.list,其内容如下:
1 | deb http://pkg.jenkins-ci.org/debian binary/ |
然后执行以下命令:
1 | $ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key sudo apt-key add - |
配置
端口
Jenkins默认监听8080端口,如果与其他应用程序端口冲突,修改/etc/default/jenkins文件:
HTTP_PORT=8082
然后
1 | # /etc/init.d/jenkins restart |
就可以了
访问控制
Jenkins默认安装是没有启用访问控制的,也就是可以随便匿名访问,要启用安全控制,访问Jenkins web界面,从”系统管理->安全设置”中配置即可。
邮件通知
打开Manage Jenkins -> Configure System:
Jenkins Location -> System Admin e-mail address 设置管理员邮箱地址
E-mail Notification -> SMTP server 输入stmp服务器地址
Default user e-mail suffix 用户邮箱后缀,比如@openwares.net
Advanced -> Use SMTP Authentication 输入smtp认证需要的User Name和password
Use SSL 如果服务器使用SSL则勾选,如果使用TLS/STARTTLS则不要勾选
SMTP Port 指定端口,默认25
如果smtp服务器使用TLS,则需要在jenkins配置文件/etc/default/jenkins中添加JAVA选项:
JAVA_ARGS=”-Dmail.smtp.starttls.enable=true” # enable STARTTLS
否则测试邮件发送会有异常:
1 | Failed to send out e-mail |
然后重新启动jenkins。
但是如果启用STARTSSL时服务器的SSL证书是自签的,又会抛出异常:
1 | Failed to send out e-mail |
因为证书是不受信任的:-(。
那么还需要在jenkins配置文件/etc/default/jenkins中添加一个JAVA选项:
JAVA_ARGS=”-Dcom.sun.net.ssl.checkRevocation=false” #disable cert verify
这样就可以正常发送邮件了。
References:
[1]Jenkins Debian packages
[2]Installing Jenkins on Ubuntu
===
[erq]
账户配置
提交到gerrit的changes中的用户名和邮箱地址必须与gerrit用户信息一致,否则会被拒绝,除非有Forge XXX权限。
1 | $ git config --global user.name "username" |
克隆gerrit仓库
一般来说为ssh主机设置别名可以省很多事,不用每次输入复杂的远程仓库地址了:
~/.ssh/config文件中添加如下行:
1 | Host cr |
然后可以这样克隆远程仓库了
1 | $ git clone ssh://cr/project |
而且以后都可以使用cr这个别名来代替远程gerrit仓库地址
安装commit-msg钩子
commit-msg是gerrit提供的钩子脚本,会为每个提交添加Change-Id行。
1 | $ scp cr:hooks/commit-msg .git/hooks/ |
提交changes
首先checkout出devel分支。根据不同的策略,master有可能是禁止推送更新的。
1 | $ git checkout devel |
经过一段时间的工作,有了commit后,就可以将commit提交到服务器接受代码审核。
1 | $ git push origin HEAD:refs/for/devel |
直接git push推送到远程devel分支是被禁止的,推送到refs/for/devel会在gerrit服务器上生成新的需要评审的changes。
可以通过增加一个远程配置来进一步简化命令行:
.git/config中添加如下行:
1 | \[remote "review"\] |
之后就可以这样推送changes了:
1 | $ git push review |
使用git-review
git-review是针对gerrit的一个命令
1 | # apt-get install git-review |
git-review默认使用gerrit远程仓库别名
1 | $ git remote add gerrit ssh://cr/project |
然后在工程根目录下建立git-review配置文件.gitreview
1 | \[gerrit\] |
最后通过
1 | $ git review |
就可以推送changes了。
verify和code review
通过不应该通过开发人员进行verify,CI服务器会在changes提交后自动进行verify。
Code Review可以通过gerrit web接口进行。通过verify和code review的changes可以通过submit合并到目标分支。
个人分支
如果gerrit服务器提供了sandbox个人分支,那么可以将自己的阶段性工作保存在sandbox中而不用提交到gerrit服务器进行评审,直到感觉可以参加评审时再向devel分支提交changes。
1 | $ git checkout devel |
一般来说为了devel分支的整洁,建议先在个人分支工作,等工作比较成熟后再合并回devel分支,然后再向gerrit服务器推送changes。
References:
[1]Gerrit Code Review - Uploading Changes
[2]Gerrit Code Review - Change-Ids
===
[erq]
荷兰程序员Vincent Driessen的A successful Git branching model[1]对于集中式的中小型项目是一个相当不错的分支模型。他还制作了一副pdf大图Git-branching-model。
分支模型
有两个常设分支,master和devel(或叫develop,or whatever)。master分支用于最终产品发布,而devel分支用于日常开发。
其他临时性分支包括特性分支feature或叫topic分支,预发布分支release,热补丁分支hotfix。
feature用于新功能开发,分支自devel,新功能开发完毕必须merge回devel分支,或者不再需要此特性,直接丢弃分支。命名方式一般为feature-特性名或者特性编号。
release用于产品正式发布前的预发布,分支自devel。命名方式一般为release-(即将发布的版本号),比如release-1.2。release分支功能上不应该再发生变化,只是一些小的完善或者bug的修复还有实施版本策略。确认版本可以发布后,将release合并到master,并在master上打版本tag。release同时要合并回devel分支,之后可以删除release分支。
hotfix用于正式发布产品的紧急bug修复,分支自master。命名方式一般为hotfix-bug编号,比如hotfix-1312,bug编号来自bug tracking系统,比如Trac。bug修复完毕后,将hotfix分支合并回master分支,并更新产品号以及打新的tag。如果当前存在release分支,则应将hotfix合并到release分支而不是master分支。hotfix还需要合并回devel分支。之后可以将hotfix分支删除。
合并分支时使用- -no-ff选项,不让分支fast forwarding以保持完整清晰的版本历史。
个人分支
除了常设分支和临时分支外,每个开发人员还可以设立自己的个人分支(personal branch)。个人分支以自己的名字命名,分支自devel。个人分支方便开发人员保存和在不同机器间同步未最终完成的工作成果,代码重构,并且可以减少devel分支的commit,保持devel分支的整洁。个人分支上的工作告一段落后,更新本地代码库,将个人分支上的工作成果合并到devel分支,然后推送devel分支到中央仓库。
代码审核
master分支只有项目管理员可以touch,其他开发人员无法向master推送更新。而开发人员向devel分支推送的更新必须经过gerrit代码审核服务器,在通过其他开发人员的code review和CI服务器的自动verify后,才可以正式merge到devel分支。
其他临时分支和个人分支不经过gerrit,直接进入中央仓库。
持续集成
每当开发人员向devel推送更新,这在gerrit叫做change,CI服务器会自动对新提交的change进行编译和运行单元测试,根据结果给于适当的verify值。
当代码通过审核merge到devel后,自动触发CI服务器,拉取devel分支,然后编译部署到测试环境进行自动化测试和人工测试。
而master分支发布产品时也可以通过触发CI进行自动编译和部署到产品环境。
References:
[1]A successful Git branching model
[2]Git分支管理策略
[3]实用 Git 工作流
[4]一个成功的Git分支模型
===
[erq]
gerrit从2.6开始,默认不再添加verified category,也就是changes上就看不到verified label了。
具体的原因见gerrit的Change 44084。这是为了简化out of the box工作流,如果需要与jenkins等CI环境集成,则需要手动添加verified category,只要在All-Projects的project.config文件里添加5行文本就可以了。
添加V标签
1 | $ mkdir temp && cd temp |
在文件project.config中添加如下5行:
1 | \[label "Verified"\] |
然后提交到远程仓库
1 | $ git commit -a -m "add verified category" |
因为在分离头(detached HEAD)状态,所以手工指定将当前HEAD push到远程引用refs/meta/config。
登录gerrit站点,changes上面就有V标签了。
verified label的用法见官方文档。
References:
[1]HOW TO EDIT THE PROJECT.CONFIG FOR ALL PROJECTS IN GERRIT
===
[erq]
Gradle是使用Groovy做为DSL的构建工具,十分强大且易用。
Lambda表达式本质就是一个匿名函数,其理论基础来自于λ演算。不过Lambda表达式是受到很多限制的匿名函数,比如有些语言只允许有一条表达式。闭包是持有自由变量从而具有状态的函数,闭包通常使用匿名函数来实现。闭包拥有的自由变量类似于对象拥有的成员变量。