Golang中解决Grpc未知证书授权错误的方法
Golang中解决Grpc未知证书授权错误的方法 嗨!
我之前有一个托管在 Google App Engine 标准版上的 Web 应用程序,由于现在需要使用 WebSocket API,我将其迁移到了 Google Compute Engine,并使用 Google Datastore 作为数据库。
因此我创建了一个 Dockerfile:
FROM scratch
COPY ./cmd ./
STOPSIGNAL SIGTERM
EXPOSE 80/tcp
EXPOSE 443/tcp
ENV GRPC_GO_LOG_SEVERITY_LEVEL INFO
CMD ["/hello-datastore"]
将编译后的应用程序作为二进制文件嵌入容器中,并将镜像发布到注册表(Google Cloud Registry)。然后从容器镜像(容器优化操作系统)在 Google Cloud Platform 上启动一个实例(虚拟机)并运行应用程序。
在我的 main.go 中:
//import the datastore client
import cloud.google.com/go/datastore
//create a new client
client, err := datastore.NewClient(ctx, *projectID)
if err != nil {
log.Fatal(err)
}
//Puting an entity fails silently.
key := datastore.NameKey("testEntity", "milk", nil)
key.Namespace = "test"
task := &TestEntity{Description: "Buy milk"}
if _, err := client.Put(ctx, key, task); err != nil {
log.Fatalf("Put: %v", err)
}
将 GRPC_GO_LOG_SEVERITY_LEVEL 设置为 INFO 可以显示底层 gRPC 调用的详细信息,但出现了 “x509: unknown certificate authority” 的错误。
INFO: 2018/12/24 15:40:25 Subchannel Connectivity change to CONNECTING
INFO: 2018/12/24 15:40:25 pickfirstBalancer: HandleSubConnStateChange: 0xc000167930, CONNECTING
WARNING: 2018/12/24 15:40:25 grpc: addrConn.createTransport failed to connect to {datastore.googleapis.com:44
3 0 }. Err :connection error: desc = "transport: authentication handshake failed: x509: certificate sig
ned by unknown authority". Reconnecting…
INFO: 2018/12/24 15:40:25 Subchannel Connectivity change to TRANSIENT_FAILURE
INFO: 2018/12/24 15:40:25 pickfirstBalancer: HandleSubConnStateChange: 0xc000167930, TRANSIENT_FAILURE
更多关于Golang中解决Grpc未知证书授权错误的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
确实如此!我刚刚使用了多阶段Docker构建文件,基于alpine:latest镜像构建只是为了获取ca-certificates,然后将其复制到最终镜像中(基于scratch镜像,附加了bin和/etc/ssl/certs/ca-certificates.crt文件)
谢谢
更多关于Golang中解决Grpc未知证书授权错误的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
验证由CA颁发的证书需要一个包含各种可信CA机构证书的"根证书存储库"。操作系统通常会自带这样的存储库,但您没有将其包含在容器中。因此,在容器中运行的程序无法验证其他证书。
您需要在容器构建时添加包含根证书的软件包。
// 代码示例保留原样
func main() {
fmt.Println("hello world")
}
在Golang中遇到gRPC的"x509: unknown certificate authority"错误通常是因为容器环境中缺少根证书。以下是几种解决方案:
方案1:使用包含根证书的基础镜像
将你的Dockerfile从scratch改为包含根证书的基础镜像:
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY ./cmd /hello-datastore
STOPSIGNAL SIGTERM
EXPOSE 80/tcp
EXPOSE 443/tcp
ENV GRPC_GO_LOG_SEVERITY_LEVEL INFO
CMD ["/hello-datastore"]
方案2:在scratch镜像中手动添加证书
FROM scratch
COPY ./cmd /hello-datastore
COPY --from=alpine:latest /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
STOPSIGNAL SIGTERM
EXPOSE 80/tcp
EXPOSE 443/tcp
ENV GRPC_GO_LOG_SEVERITY_LEVEL INFO
CMD ["/hello-datastore"]
方案3:编译时静态链接证书
在Go代码编译时,确保启用CGO并静态链接证书:
// 在编译时使用这些标志:
// CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o cmd/hello-datastore .
对应的Dockerfile:
FROM scratch
COPY ./cmd/hello-datastore /
COPY certs/ca-certificates.crt /etc/ssl/certs/
STOPSIGNAL SIGTERM
EXPOSE 80/tcp
EXPOSE 443/tcp
ENV GRPC_GO_LOG_SEVERITY_LEVEL INFO
CMD ["/hello-datastore"]
方案4:自定义TLS配置(不推荐用于生产)
如果只是测试,可以跳过证书验证:
import (
"crypto/tls"
"google.golang.org/api/option"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func createInsecureClient(ctx context.Context, projectID string) (*datastore.Client, error) {
tlsConfig := &tls.Config{
InsecureSkipVerify: true,
}
creds := credentials.NewTLS(tlsConfig)
return datastore.NewClient(ctx, projectID, option.WithGRPCDialOption(
grpc.WithTransportCredentials(creds),
))
}
推荐方案
对于生产环境,推荐使用方案1或方案2。使用Alpine基础镜像是最简单可靠的方法:
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
COPY ./cmd/hello-datastore /hello-datastore
STOPSIGNAL SIGTERM
EXPOSE 80/tcp
EXPOSE 443/tcp
ENV GRPC_GO_LOG_SEVERITY_LEVEL INFO
CMD ["/hello-datastore"]
这样确保容器中包含完整的根证书链,能够验证Google服务的TLS证书。

