0
点赞
收藏
分享

微信扫一扫

Flomesh Ingress 使用实践(二)TLS 进阶

背景

在上一篇 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 中用到的。

  • HTTPS 上游:需要针对上游也就是后端服务的证书进行检查
  • 客户端验证:主要是使用 HTTPS 入口时,对客户端使用的证书进行检查

演示

16751581504828.png

继续使用之前的环境,和提供了 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

  • / 返回一个简单的 HTML 页面
  • /hi 返回 200 Hi, there!
  • /api/private 返回 401 Staff only

为了提供 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!
举报

相关推荐

0 条评论