在上一篇 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/fsm
helm 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 2048
openssl 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 secret
kubectl create secret generic -n httpbin server-cert \
--from-file=./server-cert.pem \
--from-file=./server-key.pem
kubectl apply -n httpbin -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- port: 8443
name: https
- port: 8000
name: http
selector:
app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
labels:
app: httpbin
spec:
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-cert
EOF
复制代码
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/v1
kind: Ingress
metadata:
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:80
Hi, 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/v1
kind: Ingress
metadata:
name: httpbin
annotations:
pipy.ingress.kubernetes.io/tls-trusted-ca-secret: httpbin/trust-client-cert
spec:
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:443
Hi, there!
复制代码
评论