在上一篇 Flomesh Ingress 基础功能 介绍中,我们使用 Flomesh Ingress 实现了 HTTPS 入口。实际上从客户端到上游应用会有如下的集中组合方式:
- 客户端 -> HTTP Ingress  -> HTTP Upstream 
- 客户端 -> HTTPS Ingress  -> HTTP Upstream 
- 客户端 -> HTTP Ingress -> HTTPS Upstream 
- 客户端 -> HTTPS Ingress -> HTTPS Upstream 
其中前两种已经做了实现,这篇将会介绍后两种模式所使用的 HTTPS 上游,以及基于 HTTPS 入口的客户端验证。这两种 TLS 的应用也是在 mTLS 中用到的。
演示
继续使用之前的环境,和提供了 HTTP 8000 和 HTTPS 8443 访问的示例应用。
安装 Flomesh Ingress
通过 Helm 安装 fsm。
 helm repo add fsm https://flomesh-io.github.io/fsmhelm repo update
helm install \  --namespace fsm \  --create-namespace \  --set fsm.version=0.2.1-alpha.2 \  --set fsm.ingress.tls.enabled=true \  --set fsm.serviceLB.enabled=true \  fsm fsm/fsm
   复制代码
 示例应用
这里使用的示例应用同时提供了 HTTP 8000 和 HTTPS 8443 访问,有下面几个 path:
为了提供 HTTPS,需要为应用先签发 ca 和服务端证书。
 openssl genrsa 2048 > ca-key.pem
openssl req -new -x509 -nodes -days 365000 \   -key ca-key.pem \   -out ca-cert.pem \   -subj '/CN=flomesh.io'
openssl genrsa -out server-key.pem 2048openssl req -new -key server-key.pem -out server.csr -subj '/CN=example.com'openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365
   复制代码
 
部署示例应用,先创建 Secret 将证书和密钥保存在 secret 中并挂载到应用 pod 中。
 kubectl create namespace httpbin# mount self-signed cert to sample app pod via secretkubectl create secret generic -n httpbin server-cert \  --from-file=./server-cert.pem \  --from-file=./server-key.pem
kubectl apply -n httpbin -f - <<EOFapiVersion: v1kind: ServiceAccountmetadata:  name: httpbin---apiVersion: v1kind: Servicemetadata:  name: httpbin  labels:    app: httpbin    service: httpbinspec:  ports:  - port: 8443    name: https  - port: 8000    name: http      selector:    app: httpbin---apiVersion: apps/v1kind: Deploymentmetadata:  name: httpbin  labels:    app: httpbinspec:  replicas: 1  selector:    matchLabels:      app: httpbin  template:    metadata:      labels:        app: httpbin    spec:      containers:        - name: pipy          image: addozhang/httpbin:latest          env:            - name: PIPY_CONFIG_FILE              value: /etc/pipy/tutorial/gateway/main.js          ports:            - containerPort: 8443            - containerPort: 8000          volumeMounts:          - name: cert            mountPath: "/etc/pipy/tutorial/gateway/secret"            readOnly: true      volumes:      - name: cert        secret:          secretName: server-certEOF
   复制代码
 HTTPS 上游
这个示例用于演示 FSM Ingress 如何将请求发送到 HTTPS 后端。Flomesh Ingress 提供了如下 3 个注解:
- pipy.ingress.kubernetes.io/upstream-ssl-name:上游服务的 SNI,如- example.com
 
 
- pipy.ingress.kubernetes.io/upstream-ssl-secret:包含 TLS 证书的 secret,格式为- SERECT_NAME或者- NAMESPACE/SECRET_NAME,如- httpbin/tls-cert
 
 
- pipy.ingress.kubernetes.io/upstream-ssl-verify:是否对上游的证书进行校验,默认为- false,即证书校验失败也会继续完成连接的建立。
 
在下面的 Ingress 资源示例中,通过注解 pipy.ingress.kubernetes.io/upstream-ssl-secret 指定了命名空间 httpbin 下包含 TLS 证书的 secret tls-cert。
 apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbin  annotations:    pipy.ingress.kubernetes.io/upstream-ssl-secret: httpbin/tls-cert    pipy.ingress.kubernetes.io/upstream-ssl-verify: 'true'spec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8443
   复制代码
 
使用证书和密钥创建 secret tls-cert。
 kubectl create secret generic -n httpbin tls-cert \  --from-file=ca.crt=./ca-cert.pem
   复制代码
 
应用上面的 Ingress 配置,然后使用 HTTP 入口来访问 HTTPS 上游应用。
 curl http://example.com/hi --connect-to example.com:80:$HOST_IP:80Hi, there!
   复制代码
 
检查 fsm-ingress-pipy-xxx pod 的日志,可以看到连接到的是上游的 HTTPS 8443 端口。
 ingress 2023-01-31 09:05:03.285 [INF] [balancer] _sourceIP 10.42.0.1                                                                                                                                           ingress 2023-01-31 09:05:03.285 [INF] [balancer] _connectTLS true                                                                                                                                              ingress 2023-01-31 09:05:03.285 [INF] [balancer] _target.id 10.42.0.20:8443
   复制代码
 客户端证书校验
这个示例了演示了在开启 TLS 卸载以及 mTLS 的情况下,对客户端证书进行验证。
在使用 mTLS 功能之前,确保 FSM Ingress 已经启用并配置了 TLS,需要再 FSM 安装时提供参数 --set fsm.serviceLB.enabled=true。
要启用 mTLS 功能,可以在 FSM Ingress 时通过参数 --set fsm.ingress.tls.mTLS=true 开启,或者在安装后修改配置来开启。具体操作是修改 FSM 命名空间下的 ConfigMap fsm-mesh-config,将 tls.mTLS 的值设置为 true。
在 FSM Ingress 中,提供了注解 pipy.ingress.kubernetes.io/tls-trusted-ca-secret 来配置可信的客户端证书。
 apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: httpbin  annotations:    pipy.ingress.kubernetes.io/tls-trusted-ca-secret: httpbin/trust-client-certspec:  ingressClassName: pipy  rules:  - host: example.com    http:      paths:        - path: /          pathType: Prefix          backend:            service:              name: httpbin              port:                number: 8000  tls:  - hosts:    - example.com    secretName: ingress-cert
   复制代码
 
为 Ingress 签发自签名证书。
 openssl req -x509 -newkey rsa:4096 -keyout ingress-key.pem -out ingress-cert.pem -sha256 -days 365 -nodes -subj '/CN=example.com'
   复制代码
 
使用证书和密钥创建 Secret。
 kubectl create secret tls ingress-cert --cert=ingress-cert.pem --key=ingress-key.pem -n httpbin
   复制代码
 
为客户端签发自签名证书。
 openssl req -x509 -newkey rsa:4096 -keyout client-key.pem -out client-cert.pem -sha256 -days 365 -nodes -subj '/CN=flomesh.io'
   复制代码
 
使用客户端证书作为内容创建 Secret。
 kubectl create secret generic -n httpbin trust-client-cert \  --from-file=ca.crt=./client-cert.pem
   复制代码
 
应用上面的 Ingress 配置。
 curl --cacert ingress-cert.pem --cert client-cert.pem --key client-key.pem https://example.com/hi --connect-to example.com:443:$HOST_IP:443Hi, there!
   复制代码
 
评论