在上一篇 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!
复制代码
评论