首页 > 解决方案 > istio 安全 grpc 网关的身份验证握手失败

问题描述

设置:

笔记:

证书/密钥生成

# Root certificate and private key
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=test/CN=test.com' -keyout certs/test.com.key -out certs/test.com.crt

# Certificate and private key for matchmaker service
openssl req -out certs/matchmaker.test.com.csr -newkey rsa:2048 -nodes -keyout certs/matchmaker.test.com.key -subj "/CN=matchmaker.test.com/O=matchmaker" 
openssl x509 -req -days 365 -CA certs/test.com.crt -CAkey certs/test.com.key -set_serial 0 -in certs/matchmaker.test.com.csr -out certs/matchmaker.test.com.crt 

Kubernetes 清单

创建秘密以包括媒人的证书和密钥:
kubectl create -n istio-system secret tls matchmaker-creds --key=path/to/matchmaker.test.com.key --cert=path/to/matchmaker.test.com.crt

Gateway、VirtualService 和 Service 清单:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: gateway
spec:
  selector:
    istio: ingressgateway # use Istio default gateway implementation
  servers:
  - port:
      number: 80
      name: grpc
      protocol: GRPC
    hosts:
      - "*"
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: matchmaker-creds
    hosts:
      #- "*"
      - matchmaker.test.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vservice
spec:
  gateways:
    - gateway
  hosts:
    #- "*"
    - matchmaker.test.com
  http:
  - match:
    - authority:
        exact: "matchmaker"
    route:
    - destination:
        host: matchmaker
        port:
          number: 5001
---
apiVersion: v1
kind: Service
metadata:
  name: matchmaker
spec:
  selector:
    server: matchmaker
  ports:
    - name: https # Note: must be changed to grpc if we're connecting through port 80 in the gateway
      port: 5001

服务器代码
服务器不需要包含任何 tls 设置,因为网关使用 TLS 终止,所以发送到matchmaker服务的请求应该是未加密的,对吧?

const (
    port = ":5001"
)

func main() {
    matchmakerServer, err := matchmaker.Init()
    if err != nil {
        log.Fatal(err)
    }

    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    initializer := initializer.NewInitializer()

    grpcServer := grpc.NewServer()
    mmprotos.RegisterMatchmakerServer(grpcServer, matchmakerServer)
    initprotos.RegisterInitializerServer(grpcServer, initializer)

    // Register health check
    healthService := healthcheck.NewHealthChecker()
    grpc_health_v1.RegisterHealthServer(grpcServer, healthService)

    version := os.Getenv("VERSION")

    matchmakerServer.Logger.WithField("version", version).Infof("listening on %v", lis.Addr())

    err = grpcServer.Serve(lis)
    if err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

客户端代码

const (
    address = "<ip-addr>:443"
    token = "<jwt-token>"
)

func main() {
    creds, err := credentials.NewClientTLSFromFile("path/to/test.com.crt", "")
    if err != nil {
        log.Fatal(err)
    }

    opts := []grpc.DialOption{
        grpc.WithTransportCredentials(creds),
        grpc.WithAuthority("matchmaker"),
        //grpc.WithBlock(),
    }

    conn, err := grpc.Dial(address, opts...)
    if err != nil {
        log.Fatal(err)
    }

    defer conn.Close()

    client := initprotos.NewInitializerClient(conn)

    md := metadata.Pairs(
        "Authorization",
        fmt.Sprintf("Bearer %v", token),
    )

    ctx := metadata.NewOutgoingContext(
        context.TODO(),
        md,
    )

    _, err = client.Connect(ctx, &initprotos.EmptyRequest{})
    if err != nil {
        log.Fatalf("connect method err: %v", err)
    }
}

当请求发送到 istio 网关时,istio 代理日志不会显示任何有用的信息。

标签: gokubernetesnetworkinggrpcistio

解决方案


推荐阅读