锁上私有化部署的最后一道门:证书的集中式管理

之前的文章的末尾,我提到了

同一个域名解析得到不同的证书或许不是最佳实践,集中式的证书管理获取是更好的选择,有机会再说吧。

经过在互联网上寻觅一番后,我找到了certdcertimate。在本地部署尝试后我选择了certd,因为

  • certimate的docker支持仍有欠缺
  • certd的流程图式部署简洁易懂,在已有TLS证书部署的基础上,几乎不需要看文档,上手就能操作

但是注意:

  • certd的免费版本只能提供10条流水线的支持(考虑到我们可以使用泛域名证书,足够了)

梳理

让我们来梳理一下,一个集中式的证书管理程序需要做什么。

  • 能够自动签发证书
  • 能够将证书下发给主机/CDN
  • 能够控制主机载入证书

简单绘制画个图

总体流程

graph LR
A(发起单个流程)-->B[从CA机构签发证书]-->C[将证书推送到主机/CDN]-->D[执行主机命令重载证书]-->E[通知结果]-->F(结束)

为了实现证书的自动续签,我们只需要在每天定时允许这个流程,视历史记录跳过其中的某些步骤。比如第10天的执行发现证书还有80天过期,那么可以跳过从CA机构签发证书将证书推送到主机/CDN执行主机命令重载证书这些步骤;在第80天发现证书还有10天过期,那么上述所有步骤都需要执行一遍。

从其中的细节来看:

从CA机构签发证书

我们可以选用Let's Encrypt免费签发,其中的域名验证可以使用DNS验证的方式。其流程如下:

graph LR
A(发起证书签发流程)-->B[向CA机构发起申请流程]-->C[通过API向DNS服务商发起DNS编辑请求]--等待DNS修改生效-->D[向CA机构请求证书]-->E[保存获取的证书文件]-->F(结束)
将证书推送到主机/CDN和执行主机命令重载证书

将证书推送到主机/CDN执行主机命令重载证书certd执行,对于大多数CDN服务商,只需要使用申请到的key即可,无需我们做太多操作。但是对于自行部署的主机,我们需要手动配置这部分操作,其流程可以如下:

graph LR
A(发起主机的证书部署)-->B[ssh连接到目标主机]-->C[传输证书和密钥文件到目标主机]-->D[重载目标主机的相关服务]-->F(结束)

这部分操作是整个流程中需要我们手动配置最多的地方,我们会在下文中详细描述。在整个流程中,我们会尽量保持最小权限原则,避免授予certd服务过高的权限。

让我们从安装开始。

安装

certd提供了完整的Docker支持,我们没有理由不使用它~

我们需要找一台可以连接互联网的服务器部署,因为其采用DNS验证的方式部署,公网IP并不是必要条件。

1
2
3
mkdir certd
cd certd
vim docker-compose.yml

编辑为以下内容,或者您也可以使用其GitHub中的版本,此文只删减了部分注释和默认配置。

其README中提供的Docker-compose文件有充足的注释,建议按照需求更改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3.3' # 兼容旧版docker-compose
services:
certd:
# 镜像版本号,建议改成固定版本号
image: greper/certd:latest
container_name: certd # 容器名
restart: unless-stopped # 自动重启
volumes:
# 数据库以及证书存储路径
#【您需要定时备份此目录,以保障数据容灾】
# 默认为/data/certd/目录,本文使用本地的./data/certd
- ./data/certd:/app/data
ports:
# 如果端口有冲突,可以修改第一个7001为其他不冲突 的端口号
- "7001:7001"
dns:
- 223.5.5.5
- 223.6.6.6
environment:
- TZ=Asia/Shanghai
# 设置环境变量即可自定义certd配置
# 配置项见: packages/ui/certd-server/src/config/config.default.ts
# 配置规则: certd_ + 配置项, 点号用_代替
# 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请 及时修改回false
- certd_system_resetAdminPasswd=false
# 如果设置为true,启动后所有配置了cron的流水线任务都将被立即触发一次
- certd_cron_immediateTriggerOnce=false

使用

1
sudo docker compose up -d

启动即可。

等待容器启动完毕,访问7001端口即可,其默认账号为admin,密码为123456。

配置 Certd

坦率地说,这部分内容在 Certd 和其文档站中已有完整的教程,此文不再赘述。

哈哈,好吧,我还是踩坑了,第一次没看懂 Cloudflare 的令牌获取流程,如果你也需要用 Cloudflare 可以看看 ↓

Cloudflare 的 Key 获取

这个东西好像确实不那么直观,单击获取 API 令牌后,单击创建令牌,选择最下方的自定义令牌。然后将相关配置按照下图配置:

Cloudflare 的 Key 获取
确保红色框内的配置与图中相同,其他条目视自己情况编辑,默认也可。

配置上传证书到主机

至此,按照 Certd 内自带的教程和文档,我们已经可以完成一条完整的流水线,将证书部署到CDN或者对象存储服务,因为这些服务的具体操作都已有服务商和Certd配置好了,所以一切从简。接下来我们进入本文的重点:配置上传证书到主机

流程梳理

我们需要完成以下要点

  • 使用 Certd 将证书推送到目标主机
  • 执行目标主机的具体指令,使相关服务重载证书(本文以 Nginx 为例)

在下文中,我们假设Certd所在的服务器为Certd_server,目标主机服务器为Nginx_server

让我们遵守最小权限原则,开始吧

创建专用于推送证书和重启服务的用户

登录到Nginx_server

创建一个名为cert_push_user的用户,并授予其重载Nginx服务的权限

1
2
sudo useradd -m cert_push_user -s /bin/bash
echo "cert_push_user ALL=(root) NOPASSWD: /usr/sbin/service nginx reload" | sudo tee /etc/sudoers.d/cert_push_user

/etc/ssl/下创建一个nginx文件夹,之后我们所有的证书文件都会上传到这里

配置文件权限,允许cert_push_user用户和www-data组成员(这是 Nginx 进程所属的用户组)访问和管理该目录

确保只有cert_push_userwww-data组可以访问目录,而其他用户无法访问

1
2
3
sudo mkdir -p /etc/ssl/nginx
sudo chown cert_push_user:www-data /etc/ssl/nginx
sudo chmod 750 /etc/ssl/nginx

配置证书推送账号的SSH登录

使用 su 命令切换到 cert_push_user账号

1
2
sudo su cert_push_user
cd ~

创建一个密钥对,密码可以为空

1
ssh-keygen -t rsa -b 4096 -f cert

我们会得到两个文件:certcert.pub文件,其中cert为私钥,cert.pub为公钥,我们需要将公钥写入到该账号的SSH密钥认证文件中。

1
2
3
4
cat cert.pub # 复制展示出来的内容,将其填入下方的authorized_keys文件中
mkdir .ssh
vim .ssh/authorized_keys
# 在文件中填入cert.pub的内容

复制密钥

1
cat cert # 复制展示出来的内容,将其填入Certd的主机连接密钥中

在确保密钥复制后,certcert.pub文件可以删除。

配置Certd的主机登录配置

在证书申请任务之后,我们选择上传证书到主机任务,在下方的主机登录配置中,单击选择添加,配置Nginx_server的SSH相关内容

其中用户名填写我们先前创建的cert_push_user,填写密钥登陆,粘贴我们刚才从**cert文件中复制出来的内容**

其他按情况填写即可

配置部署证书到主机

我们需要填写证书保存路径私钥保存路径和最下方的shell脚本命令

对于证书保存路径私钥保存路径,我们需要填写之前创建的证书路径,并加上我们需要给证书的命名,比如我们希望证书推送到主机后的名字为baidu.com.pembaidu.com.key,那么这俩个空可以这么写:

证书保存路径和私钥保存路径

对于shell脚本命令,没有发挥的空间,我们在前文只授予了该用户重启nginx服务的权限,此空只能填sudo service nginx reload

image-20241103185421027

至此,证书的推送和目标服务的重启就此结束。按需要配置邮件通知即可。

注意:你需要确保Nginx服务读取的证书文件和上文配置的相同,视具体情况编辑你的nginx.conf文件,避免出现证书推送成功但是Nginx找不到证书的情况

更新Certd本身的证书

如果您使用源码部署的方式,Certd服务直接处理HTTPS的情况,可以参考官方文档中的描述。

本文采用了Docker方式部署,Certd本身只提供了HTTP服务,TLS由Nginx管理,所有可以将本机(实体机,非Docker容器)也视作一个Nginx_server,按照上文方式配置。

注意:使用Certd自身管理自身链路的TLS证书,为避免证书部署失败且过期,请确保开启邮件通知功能,在还有一定剩余天数的情况下手动修复相关问题


锁上私有化部署的最后一道门:证书的集中式管理
http://coooolfan.com/2024/11/03/Centralized-Certificate-Management-for-Self-Hosted/
作者
Coolfan
发布于
2024年11月3日
许可协议