Open
Description
grpc-gateway-example 是一个grpc转http的一个示例。不过因为年久失修,证书配置上有问题。
这个示例演示如何将grpc和http绑定到同一个端口,但是grpc-gateway的官方文档的示例更简单
在build工程后,用curl命令测试时,出现错误
curl -X POST -k https://localhost:10000/v1/echo -H "Content-Type: text/plain" -d '{"value": "foo"}'
{"error":"connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead\"","code":14,"message":"connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead\""}
原因是因为,代码中的证书使用的是传统的Common Name (CN) 字段,而没有使用现代标准所推荐的 Subject Alternative Names (SANs) 字段。现代的 TLS 客户端(比如最新版本的浏览器和curl)要求证书使用 SANs 字段来指定有效的主机名。
可以参考下面的文章,确保生成的证书包含SAN字段。简单的方法是修改certs/Makefile
的代码
openssl req -new -x509 -key server.key -out server.pem -days 3650 -subj "/C=cn/OU=devhg/O=devhg/CN=localhost:10000" -addext "subjectAltName = DNS:localhost"
这里新增一条subjectAltName = DNS:localhost
记录。不过,这时会发现还是有问题:
curl -X POST -k https://localhost:10000/v1/echo -H "Content-Type: text/plain" -d '{"value": "foo"}'
{"error":"connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate is valid for localhost, not localhost:10000\"","code":14,"message":"connection error: desc = \"transport: authentication handshake failed: tls: failed to verify certificate: x509: certificate is valid for localhost, not localhost:10000\""}
有人提了一个issue: bad practice on creating the tls credentials,因为代码中固定了ServerName为“localhost:10000”,导致SANs不匹配。一个临时的解决方案是,在生成pem时,修改为subjectAltName = DNS:localhost:10000
,带上端口号。这样可以运行,但证书的可用性降低了。
verify certificate: x509: certificate relies on legacy Common Name field, use SANs instead