使用ACME CA为ASM网关签发证书

简介: 阿里云服务网格ASM提供全托管式服务网格平台,兼容Istio开源服务网格,简化服务治理,包括流量管理、认证安全和可观测性。产品文档:[https://help.aliyun.com/zh/asm](https://help.aliyun.com/zh/asm)。本文指导如何使用cert-manager和ACME CA为ASM网关获取HTTPS证书,涉及ACME协议、挑战验证及Let's Encrypt的使用。

阿里云服务网格Service Mesh,简称ASM)提供一个全托管式的服务网格平台,兼容社区Istio开源服务网格,用于简化服务的治理,包括服务调用之间的流量路由与拆分管理、服务间通信的认证安全以及网格可观测性能力,从而极大地减轻开发与运维的工作负担。产品文档主页:https://help.aliyun.com/zh/asm/product-overview/what-is-asm?spm=a2c4g.11186623.0.0.3dcb29aae25AFJ

本文演示如何使用cert-manager对接ACME CA,为ASM网关签发浏览器信任的HTTPS证书。

ACME是什么?

ACME的定义可以参考RFC 8555: Automatic Certificate Management Environment (ACME)

简而言之,ACME就是一种可以自动化处理X.509证书签发请求的协议。通过这个协议,可以对证书申请者的身份进行验证,从而为其签发证书。

当前有很多公共的ACME CA。Let's Encrypt就是一个非营利性的公共ACME CA,它可以签发出一般浏览器信任的证书。入门指南

本文也将使用let's Encrypt来做演示。

cert-manager中对于ACME的说明

cert-manager的ACME Issuer会向ACME CA Server注册一个账户。当你创建一个ACME Issuer,cert-manager将会生成一个私钥,用来和ACME Server通信。公共ACME Server颁发的证书通常是被客户端信任的。这意味着:客户端浏览器访问时,会信任你当前的URL。

提示一下:

用公共CA为自己的网站颁发证书,主要是为了让浏览器相信:当前Server就是为这个域名提供服务。所以公共CA需要确认:申请证书的Server就是这个域名的拥有者。

Solving Challenges

Challenges是ACME中的一个概念。申请证书时,为了让ACME CA Server确认当前客户端(证书申请者)确实拥有这个域名,客户端一般需要完成一些挑战(challenges)。这是为了确保让不拥有这个域名的人申请到这个证书,防止出现域名欺骗的问题。cert-manager目前提供了两种验证challenge - HTTP01和DNS01 challenge。

HTTP01 challenge是通过server提供计算出的密钥来完成的,该密钥应该存在于 HTTP URL 端点上并且可以通过互联网进行路由。这个URL需要使用当前申请的证书的域名。一旦ACME Server可以通过互联网在这个URL中获取到这个key,ACME server就会确认“你是当前域名的所有者”。当你创建了一个HTTP01 challenge,cert-manager会自动配置你集群的Ingress,来将这个URL的请求路由到一个小的web server上,这个web server上会存有这个key。

DNS01 challenge时通过提供DNS TXT记录中存在的一个计算出来的密钥来完成的。一旦这个TXT记录在互联网上传播开来,ACME server就可以通过DNS查找来获取这个key,并确认当前客户端确实拥有这个域名。拥有了正确的权限后,cert-manager将自动为给定的DNS提供商提供此TXT记录。

使用前提

步骤一:准备公网域名

要使用Let's Encrypt为域名签发证书,首先需要有一个公网域名,并且需要您将公网域名指向要使用的ASM网关。具体流程需要查看您的DNS提供商的文档。如果您使用的是阿里云提供的DNS服务,可以参考:如何添加域名解析记录_云解析DNS(DNS)-阿里云帮助中心

步骤二:创建对接Let's Encrypt的Issuer资源

使用数据面集群的kubeconfig,创建如下资源:

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-prod-issuer
  namespace: istio-system
spec:
  acme:
    email: 'test@mail.com'    # 这个不是必填字段,但是建议填写。ACME Server可能通过该邮箱向您发送与证书相关的重要通知。
    privateKeySecretRef:
      name: letsencrypt-prod
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - http01:
        ingress:
          ingressClassName: istio

上述issuer资源指定了一个http01类型的solver,使用Ingress API,ingressClassName是istio。下面步骤中将会解释这个solver如何生效。

说明:

cert-manager支持使用Ingress API和Gateway API两种类型的solver。ASM对这两种API都提供了支持。

本例中使用Ingress API。

等待issuer就绪,可以使用如下命令查看issuer状态:

k -n istio-system get issuer letsencrypt-prod-issuer
NAME                      READY   AGE
letsencrypt-prod-issuer   True    8m3s

步骤三:为ASM网关签发证书

使用数据面集群的kubeconfig,创建如下资源:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: istio-ingressgateway-certs
  namespace: istio-system
spec:
  dnsNames:
  - ${测试域名}    # test.com
  issuerRef:
    group: cert-manager.io
    kind: Issuer
    name: letsencrypt-prod-issuer
  secretName: istio-ingressgateway-certs

等待certificate就绪,可以用如下命令查看certificate状态:

kubectl -n istio-system get certificate istio-ingressgateway-certs
NAME                         READY   SECRET                       AGE
istio-ingressgateway-certs   True    istio-ingressgateway-certs   59m

证书签发的过程解析

创建certificate资源之后,cert-manager就会使用上一步创建的issuer为这个域名签发证书。这个过程中,我们上一步配置的solver就会生效。

Let's Encrypt将会使用HTTP01 challenge来确认:当前server是这个域名的所有者。为此,Let's Encrypt将会发送一个HTTP请求到这个域名,然后它需要获取到一个合法的返回值,才可以完成验证。

可是在这个例子中,我们的网关上只有httpbin的路由规则,并没有任何和challenge有关的配置。Let's Encrypt是否真的发送了challenge请求?以及请求是如何被响应的呢?

首先可以确认的是:Let's Encrypt确实发送了challenge请求,这一点可以通过网关日志来确认。使用如下命令查看网关日志:

kubectl -n istio-system logs ${网关pod名称} | grep letsencrypt | tail -1
{"authority_for":"xxxxxxx","bytes_received":"0","bytes_sent":"87","downstream_local_address":"xx.xx.xx.xx:80","downstream_remote_address":"xx.xx.xx.xx:57101","duration":"0","istio_policy_status":"-","method":"GET","path":"/.well-known/acme-challenge/JfKvfdSNmkR7UqmCQU0OSkJC3EsnP4ZUiCc28OLLLxA","protocol":"HTTP/1.1","request_id":"e6806d08-0469-4383-be8e-4d7506b39ec5","requested_server_name":"-","response_code":"200","response_flags":"-","route_name":"-","start_time":"2024-04-08T12:04:06.153Z","trace_id":"-","upstream_cluster":"outbound|8089||cm-acme-http-solver-c4ch9.istio-system.svc.cluster.local","upstream_host":"xx.xx.xx.xx:8089","upstream_local_address":"xx.xx.xx.xx:55886","upstream_response_time":"0","upstream_service_time":"0","upstream_transport_failure_reason":"-","user_agent":"Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)","x_forwarded_for":"xx.xx.xx.xx"}

可以看到网关上确实存在Let's Encrypt发出的请求,并且该请求被正常返回了。这是为什么呢?

此时自然可以想到前面在issuer中配置了ingressClassName为istio。其实,cert-manager会自动创建一个ingressClassName为istio的ingress资源,将challenge请求转发给cert-manager对应的solver来完成验证。

可是在certificate就绪之后,使用kubectl -n istio-system get ingress无法看到相关的ingress资源,这是为什么呢?

这是因为cert-manager在完成证书签发后,会自动删除solver相关的资源,其中就包括ingress、service、deployment等资源。

步骤四:验证Let's Encrypt签发的证书

创建如下网关规则,在网关的443端口上配置上一步生成的证书:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: httpbin-https
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - ${测试域名}
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      credentialName: istio-ingressgateway-certs
      mode: SIMPLE

修改原有的httpbin-vs虚拟服务,为如下内容:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: httpbin-vs
  namespace: default
spec:
  gateways:
    - httpbin
    - httpbin-https  # 新增这一行
  hosts:
    - '*'
  http:
    - name: test
      route:
        - destination:
            host: httpbin.default.svc.cluster.local
            port:
              number: 8000

配置完成之后,在浏览器中访问https://${测试域名},可以看到如下形式的浏览器地址栏,点击小锁图标,可以看到显示“连接安全”:

image.png

此时浏览器已经信任您的证书。

说明

实际场景中,您需要确认您当前的证书颁发机构是否支持ACME协议。如果支持,则ASM网关可以通过cert-manager自动从CA处获取证书。比如Sectigo目前已经支持了ACME协议,其原理与本文所述类似,您可以参考Overview :: Sectigo Certificate Manager Documentation


目录
相关文章
|
12月前
|
弹性计算 运维 Serverless
使用ASM Serverless网关支撑各种弹性业务场景
ASM Serverless网关就是基于虚拟节点和ECI提供的一种Serverless 网关形态,充分支撑各种弹性和免节点运维场景的用户诉求。
178 1
|
12月前
|
调度 UED Perl
部署ASM网关Pod到指定的节点上
配置高性能和高可用的ASM网关,可确保业务连续性并提升用户体验。本文介绍如何配置ASM网关,将网关Pod部署到指定节点上,从而提高ASM网关的高可用性并增强与业务Pod的隔离性。
165 0
|
Serverless Perl 测试技术
使用ASM管理Knative服务(4):使用ASM网关实现HTTPS访问Knative服务
ASM网关支持HTTPS协议和动态加载证书功能。在使用Knative on ASM时,可以通过ASM网关来实现HTTPS访问。本文将演示如何使用ASM网关来实现HTTPS访问Knative服务。
225 0
使用ASM管理Knative服务(4):使用ASM网关实现HTTPS访问Knative服务
|
域名解析 运维 Kubernetes
如何使用ASM网关对接阿里云WAF
Web应用防火墙(Web Application Firewall,简称WAF)为您的网站或App业务提供一站式安全防护。WAF可以有效识别Web业务流量的恶意特征,在对流量清洗和过滤后,将正常、安全的流量返回给服务器,避免网站服务器被恶意入侵导致性能异常等问题,从而保障网站的业务安全和数据安全。 ASM网关支持对接WAF,并且可以通过自定义访问日志格式来查看WAF对回源请求添加的Header,更方便线上运维。本文将介绍ASM网关如何对接WAF,以及如何使用ASM的自定义访问日志能力进行调试。
287 0
如何使用ASM网关对接阿里云WAF
|
运维 Kubernetes 安全
解锁ASM网关:一致的规则配置, 多样化的入出口网关场景
作为业内首个全托管Istio兼容的服务网格产品ASM,一开始从架构上就保持了业界领先性、以及与社区发展的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立, 保持高可用部署与稳定性。阿里云ASM产品是基于社区开源的Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵
212 0
解锁ASM网关:一致的规则配置, 多样化的入出口网关场景
|
负载均衡 Kubernetes 安全
服务网格ASM使用FAQ之(5):ASM网关支持在SLB侧创建HTTPS类型的监听
ASM网关提供HTTPS安全支持、证书动态加载,从而提升ASM网关安全性。除了在ASM网关侧绑定证书的方式之外, 还可以在负载均衡侧管理证书。 本文介绍如何支持ASM网关服务在负载均衡侧绑定证书, 并创建HTTPS类型的监听。
295 0
|
2月前
|
运维 网络协议 安全
长连接网关技术专题(十):百度基于Go的千万级统一长连接服务架构实践
本文将介绍百度基于golang实现的统一长连接服务,从统一长连接功能实现和性能优化等角度,描述了其在设计、开发和维护过程中面临的问题和挑战,并重点介绍了解决相关问题和挑战的方案和实践经验。
85 1
|
6月前
|
负载均衡 应用服务中间件 API
微服务技术系列教程(25) - SpringCloud- 接口网关服务Zuul
微服务技术系列教程(25) - SpringCloud- 接口网关服务Zuul
59 0
|
5月前
|
负载均衡 Cloud Native Java
【云原生】Spring Cloud Alibaba 之 Gateway 服务网关实战开发
【云原生】Spring Cloud Alibaba 之 Gateway 服务网关实战开发
408 0
|
3月前
|
缓存 安全 API
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现
公司对外开放的OpenAPI-Server服务,作为核心内部系统与外部系统之间的重要通讯枢纽,每天处理数百万次的API调用、亿级别的消息推送以及TB/PB级别的数据同步。经过多年流量的持续增长,该服务体系依然稳固可靠,展现出强大的负载能力。
65 9
【亿级数据专题】「高并发架构」盘点本年度探索对外服务的百万请求量的API网关设计实现