自签名证书能否保护多个 CN/FQDN?
Can a self-signed cert secure multiple CNs / FQDNs?
这是一个有点愚蠢的设置,但这是我现在正在查看的内容:
- 我正在学习 Kubernetes
- 我想将自定义代码推送到我的 Kubernetes 集群,这意味着代码必须作为 Docker 图像可用,可从 some Docker 存储库获得(默认为 Docker 集线器)
- 虽然我愿意为 Docker Hub 付费(尽管我宁愿避免它),但我担心将我的自定义代码放在第三方服务上。 Sudden rate limits, security breaches, sudden ToS changes,等等
- 为此,我在我的 Kubernetes 集群中 运行 我自己的 Docker 注册表
- 我不想将 Kubernetes 节点上的 Docker 客户端 运行 配置为信任不安全 (HTTP) Docker 注册表。如果我确实选择从外部注册表中提取任何图像(例如 public 像
nginx
这样的图像,我可能会从 Docker Hub 中提取而不是在本地托管)那么我不想受到攻击MITM 攻击换出图像
- 最终,我将在集群中使用一个构建工具(Jenkins 或其他)从 git 中提取我的代码,构建映像,并将其推送到我的内部注册表。然后从注册表中拉出的所有节点都在集群中。由于注册表从不需要从集群外部的源接收图像或将它们传送到集群外部的源,因此注册表不需要 NodePort 服务,而是可以作为 ClusterIP 服务....最终
- 在我准备好最终设置之前,我正在本地计算机上构建图像并希望将它们推送到注册表(从 Internet)
- 因为我不打算让注册表可以从外界访问(最终),所以我无法利用 Let's Encrypt 为其生成有效证书(即使我正在制作我的 Docker 注册表对外界可用,I can't use Let's Encrypt, anyway 无需编写一些额外的代码来利用 certbot 或其他东西)
我的计划是遵循 this Whosebug post 中的示例:生成一个自签名证书,然后使用该证书启动 Docker 注册表。然后使用 DaemonSet 使该证书在集群中的所有节点上都受到信任。
现在您已完成设置,这是我的问题的症结所在:在我的集群中,我的 Docker 注册表可以通过简单的主机名(例如“docker-registry”)访问,但在我的集群之外,我需要通过节点 IP 地址或指向节点或负载均衡器的域名访问它。
生成自签名证书时,系统要求我提供证书的 CN/FQDN。我输入了“docker-registry”——我打算使用的内部主机名。然后我尝试在本地访问我的注册表以将图像推送到它:
> docker pull ubuntu
> docker tag ubuntu example.com:5000/my-ubuntu
> docker push example.com:5000/my-ubuntu
The push refers to repository [example.com:5000/my-ubuntu]
Get https://example.com:5000/v2/: x509: certificate is valid for docker-registry, not example.com
我可以为 example.com
而不是 docker-registry
生成证书,但是我担心如果我提供我的服务,我会在配置服务或从集群内连接到我的注册表时遇到问题这样的外部域而不是内部主机名。
这就是为什么我想知道我是否可以说我的自签名证书适用于 两者 example.com
和 docker-registry
。如果不是,另外两个可接受的解决方案是:
- 我可以告诉 Docker 客户端不要验证主机名而只隐式信任证书吗?
- 我能否告诉 Docker 注册表根据用于访问的主机名提供两个 不同 证书之一是吗?
如果三个选项中的 none 可行,那么我总是可以放弃从我的本地机器推送图像并开始在集群内构建图像的过程——但我希望推迟它到后来。我现在学到了很多东西,并努力避免被无关紧要的事情分心。
可能解决问题的最简单方法是使用 Docker 的 insecure-registry 功能。您在 post 中提到的有关此问题的担忧(它会让您以后面临安全风险)可能不会适用,因为该功能通过指定要信任的特定 IP 地址或主机名来工作。
例如你可以配置类似
{
"insecure-registries" : [ "10.10.10.10:5000" ]
}
并且您的 Docker 守护进程将在没有 TLS 的情况下访问的唯一 IP 地址是该主机和端口号上的 IP 地址。
如果您不想这样做,则需要获得受信任的 TLS 证书。您提到的每个证书有多个名称的问题通常使用证书中的 Subject Alternative Name 字段处理。 (实际上 Kubernetes 经常使用该功能)。
这是一个有点愚蠢的设置,但这是我现在正在查看的内容:
- 我正在学习 Kubernetes
- 我想将自定义代码推送到我的 Kubernetes 集群,这意味着代码必须作为 Docker 图像可用,可从 some Docker 存储库获得(默认为 Docker 集线器)
- 虽然我愿意为 Docker Hub 付费(尽管我宁愿避免它),但我担心将我的自定义代码放在第三方服务上。 Sudden rate limits, security breaches, sudden ToS changes,等等
- 为此,我在我的 Kubernetes 集群中 运行 我自己的 Docker 注册表
- 我不想将 Kubernetes 节点上的 Docker 客户端 运行 配置为信任不安全 (HTTP) Docker 注册表。如果我确实选择从外部注册表中提取任何图像(例如 public 像
nginx
这样的图像,我可能会从 Docker Hub 中提取而不是在本地托管)那么我不想受到攻击MITM 攻击换出图像 - 最终,我将在集群中使用一个构建工具(Jenkins 或其他)从 git 中提取我的代码,构建映像,并将其推送到我的内部注册表。然后从注册表中拉出的所有节点都在集群中。由于注册表从不需要从集群外部的源接收图像或将它们传送到集群外部的源,因此注册表不需要 NodePort 服务,而是可以作为 ClusterIP 服务....最终
- 在我准备好最终设置之前,我正在本地计算机上构建图像并希望将它们推送到注册表(从 Internet)
- 因为我不打算让注册表可以从外界访问(最终),所以我无法利用 Let's Encrypt 为其生成有效证书(即使我正在制作我的 Docker 注册表对外界可用,I can't use Let's Encrypt, anyway 无需编写一些额外的代码来利用 certbot 或其他东西)
我的计划是遵循 this Whosebug post 中的示例:生成一个自签名证书,然后使用该证书启动 Docker 注册表。然后使用 DaemonSet 使该证书在集群中的所有节点上都受到信任。
现在您已完成设置,这是我的问题的症结所在:在我的集群中,我的 Docker 注册表可以通过简单的主机名(例如“docker-registry”)访问,但在我的集群之外,我需要通过节点 IP 地址或指向节点或负载均衡器的域名访问它。
生成自签名证书时,系统要求我提供证书的 CN/FQDN。我输入了“docker-registry”——我打算使用的内部主机名。然后我尝试在本地访问我的注册表以将图像推送到它:
> docker pull ubuntu
> docker tag ubuntu example.com:5000/my-ubuntu
> docker push example.com:5000/my-ubuntu
The push refers to repository [example.com:5000/my-ubuntu]
Get https://example.com:5000/v2/: x509: certificate is valid for docker-registry, not example.com
我可以为 example.com
而不是 docker-registry
生成证书,但是我担心如果我提供我的服务,我会在配置服务或从集群内连接到我的注册表时遇到问题这样的外部域而不是内部主机名。
这就是为什么我想知道我是否可以说我的自签名证书适用于 两者 example.com
和 docker-registry
。如果不是,另外两个可接受的解决方案是:
- 我可以告诉 Docker 客户端不要验证主机名而只隐式信任证书吗?
- 我能否告诉 Docker 注册表根据用于访问的主机名提供两个 不同 证书之一是吗?
如果三个选项中的 none 可行,那么我总是可以放弃从我的本地机器推送图像并开始在集群内构建图像的过程——但我希望推迟它到后来。我现在学到了很多东西,并努力避免被无关紧要的事情分心。
可能解决问题的最简单方法是使用 Docker 的 insecure-registry 功能。您在 post 中提到的有关此问题的担忧(它会让您以后面临安全风险)可能不会适用,因为该功能通过指定要信任的特定 IP 地址或主机名来工作。
例如你可以配置类似
{
"insecure-registries" : [ "10.10.10.10:5000" ]
}
并且您的 Docker 守护进程将在没有 TLS 的情况下访问的唯一 IP 地址是该主机和端口号上的 IP 地址。
如果您不想这样做,则需要获得受信任的 TLS 证书。您提到的每个证书有多个名称的问题通常使用证书中的 Subject Alternative Name 字段处理。 (实际上 Kubernetes 经常使用该功能)。