天天看点

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

作者 | 黄超

杏仁运维工程师,关注容器技术和自动化运维。

前言

当今随着人们对网络安全意识的增强,越来越多的网站都开启了 HTTPS 加密来保证数据传输的安全。要开启 HTTPS,首先就需要向 CA 机构申请 SSL 证书,SSL 证书根据可信强度,大概可分为: 域名型证书(DV SSL),企业型证书(OV SSL),增强型证书(EV SSL)。

证书类型审核流程审核周期价格使用场景DV SSL完成域名所有权限的验证1 天免费或几百元博客,个人站点OV SSL需要提交网站企业的资质文件(如营业执照,组织机构代码证等)经过人工审核后发放15 - 30 天几千左右一般的企业EV SSL需要提交网站企业的资质文件(如营业执照,组织机构代码证等)经过人工审核后,还需要律师函的审核才会发放15 - 30 天几千上万金融,电商等安全需求高的网站

对于我们个人而言或者是公司的内部管理系统,我们完全可以选择费用最少,申请周期短的 DV SSL 证书来开启我们站点的 HTTPS。目前在很多云平台(阿里云,腾讯云等)上都能免费地申请 DV SSL 证书,但是都会有数量限制,下面将介绍一个免费,开源的 CA 机构,而且基本上不会有数量上的限制还能实现自动化。

Let's Encrypt

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理
The objective of Let’s Encrypt and the ACME protocol is to make it possible to set up an HTTPS server and have it automatically obtain a browser-trusted certificate, without any human intervention.

Let's Encrypt 是一个由非营利性组织 互联网安全研究小组 (ISRG) 提供的免费,自动化和开放的证书颁发机构。

Let's Encrypt 的证书的 签发/续签 都是通过 ACME 协议实现的,ACME 协议最初就是由 Let's Encrypt 团队开发,协议旨在确保验证,发布和管理方法是完全自动化,一致,合规和安全的,ACME v2 如今已变成了 IETF (RFC 8555) 标准。

Let's Encrypt 的官方已列举了许多实现了 ACME 协议的自动化申请工具/脚本,后面会简单介绍两款,我们先来看看 Let's Encrypt 的工作原理。

Let's Encrypt 的工作原理

首先是注册 Let's Encrypt 的用户(account),ACME 协议规定采用公私钥方式来注册账户,Client 端会根据非对称加密算法生成一对公私钥

openssl genrsa 4096

,用私钥对注册用户所需的信息签名发送至 Let's Lencrypt 端,Let's Lencrypt 用公钥验证成功后将发送给 Client 一个 account object 和 account url,以后 server 端就能根据私钥的签名来验证账户信息的有效性了。

Client                                                   Server

[Contact Information]
[ToS Agreement]
[Additional Data]
Signature                     ------->
                                                         Account URL
                              <-------                   Account Object


                [] Information covered by request signatures
           

接着 Client 会向 Sever 端询问申请这个证书需求的内容,Server 端会发送一组或多组 challenges,要求 Client 证明对申请这个域名有控制权,证明的方式(Challenge Type)有两种:

  1. dns-01: 在 DNS 域名解析记录中新增一条 TXT 类型的记录。
  2. http-01: 在域名的指定目录放入一个文件。

下面就根据 http-01 验证的方式来说明,Let's Encrypt 要求将

ed98

文件放入到

https://examole.com/8303

目录下,通过会发送一个 nonce (随机数)

9cf0b331

要求 Client 用上诉注册账户用的私钥签名。

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

Client 将 nonce(随机数)

9cf0b331

使用私钥进行签名发送给 Server,Server 验证签名和目录下的文件成功后,就代表你对这个域名有控制权了。

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

接着 Client 会构建一个 PKCS#10 证书签名请求 CSR (包含证书一对公私钥)发送给 Server 端,同时用私钥对这个 CSR 进行签名,Server 根据签名确定你申请的这个域名是授权过的(上一步证明过了这个私钥对这个域名有控制权),对证书进行签名,然后颁发给 Client 端,这样就完成了证书的申请。

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

ACME 客户端

acme.sh

acme.sh 是一个纯 shell 的脚本,所以基本上没有什么环境依赖,通过它能自动化地实现证书的申请,更新等操作。

安装过程非常简单,只需要一个命令,脚本相关的东西都放在

~/.acme.sh/

目录:

curl  https://get.acme.sh | sh
           

安装完成后,会在 crontab 中开启每天定时更新证书的 job:

0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null
           
申请证书

acme.sh 默认采用 http 的方式来验证域名的所有权,可以通过

-w

参数来指定验证文件的路径,它会在

/var/www/html

中创建一个

.well-known

文件夹,Let's Encrypt 回去访问这个验证文件,验证成功后会将证书放在

~/.acme.sh/certs/

中:

acme.sh --issue -d example.com -w /var/www/html
           
安装证书

使用下列命令,它就能申请证书并把证书和私钥文件 copy 到你指定的位置,并执行 nginx reload,让配置生效。

acme.sh  --installcert  -d  <domain>.com   
        --key-file   /etc/nginx/ssl/<domain>.key 
        --fullchain-file /etc/nginx/ssl/fullchain.cer 
        --reloadcmd  "service nginx force-reload"
           

配合上 crontab 中的 job, 就能够实现证书的自动更新了。

cert-manager

cert-manager 是一个 kubernetes 的自定义插件,它通过 ACME 协议向 CA 机构(默认是 Let's Encrypt)申请证书。

ansible 建 kubernetes 证书签名请求_SSL证书的自动化管理

cert-manager 会检测到你证书创建资源请求(cert.yaml)并申请证书,成功后放在 Secrets 对象中,并定义更新证书。

cert.yaml

apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: example
  namespace: default
spec:
  secretName: example-ssl-cert
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - www.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - www.example.com
           

这样就能在 ingress 中直接使用了。

常见问题

申请证书频率的限制?
  • 同一个主域下一周只能申请 50 张证书 (例如 http://www.example.com 的主域是 http://example.com)
  • 每个账户每个域名每小时申请验证失败的次数为 5 次
  • 每周只能创建 5 个重复的证书,即使是通过不同账户创建
  • 每个账户同一个 IPv4 地址每 3 小时最多可创建 10 张证书
  • 每个多域名(SAN)证书最多包含 100 个子域
  • 更新证书没有次数的限制,但是更新证书会受到上述重复证书的限制
查询证书列表?

可在 https://crt.sh 进行查询域名的证书详情

关于通配符证书(泛域名证书)的支持:
https:// community.letsencrypt.org /t/acme-v2-production-environment-wildcards/55578

已支持,不过需要使用 DNS 记录进行域名所有权的验证。

Let's Encrypt 证书的兼容性:

兼容性列表: https://letsencrypt.org/docs/certificate-compatibility/

证书丢失了能否通过 Let's Encrypt account private key 找回:
https:// community.letsencrypt.org /t/how-to-get-certificates-which-were-lost/23438

无法只根据 account private key 将证书找回,应为证书的私钥只保存在你的本地,如果你的证书可以确认没有泄露,

就重新申请证书。

Let's Encrypt account private key 泄露了怎么办:
https:// community.letsencrypt.org /t/account-key-compromise/34136

目前从 ACME 的协议里并没有针对这个问题提出改进。最好的做法是,重新申请一个 account,然后在重新申请证书并替换,再将旧的证书吊销。

参考

  • ACME 协议
  • Let's Encrypt 是如何工作的

全文完

我们正在招聘 Java 工程师,欢迎有兴趣的同学投递简历到 [email protected] 。

欢迎搜索关注微信公众号:杏仁技术站(微信号 xingren-tech)。