如何在 Go 中使用 .crt 文件通过 ssl 连接到 mongoDB

Posted

技术标签:

【中文标题】如何在 Go 中使用 .crt 文件通过 ssl 连接到 mongoDB【英文标题】:How to connect to mongoDB via ssl using .crt file in Go 【发布时间】:2021-11-16 19:00:36 【问题描述】:

我正在尝试使用 .crt 文件连接到托管在 azure 中的 mongo 数据库。

我可以使用命令从我的 linux 机器终端成功连接:

mongo mongodb://username:password@prod-replicaset-0.com:27017,prod-replicaset-1.com:27017,prod-replicaset-2.com:27017/ --tls --tlsCAFile rootca.crt --tlsAllowInvalidCertificates

我还可以通过设置“使用 SSL 协议”并将身份验证机制设置为“SCRAM-SHA-256”从 robo3T 等 mongo UI 客户端进行连接。 [如果我将 Auth Mechanism 设置为任何其他值,将导致身份验证失败]

但我无法使用 Go 语言代码连接到该数据库。

这是我正在使用的代码示例:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "io/ioutil"
    "log"
    "net"

    "github.com/globalsign/mgo"
)

func InitMongo() error 

    rootCerts := x509.NewCertPool()
    ca, err := ioutil.ReadFile("./rootca.crt")
    if err != nil 
        log.Fatalf("failed to read file : %s", err.Error())
        return err
    

    success := rootCerts.AppendCertsFromPEM(ca)
    if !success 
        log.Printf("rootcert failed")
    

    connStr := "mongodb://username:password@prod-replicaset-0.com:27017,prod-replicaset-1.com:27017,prod-replicaset-2.com:27017/?ssl=true"

    dbDialInfo, err := mgo.ParseURL(connStr)
    if err != nil 
        log.Fatal("unable to parse url - " + err.Error())
    

    dbDialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) 
        return tls.Dial("tcp", addr.String(), &tls.Config
            RootCAs:            rootCerts,
            InsecureSkipVerify: true,
        )
    

    // dbDialInfo.Mechanism = "SCRAM-SHA-256"

    _session, err := mgo.DialWithInfo(dbDialInfo)
    if err != nil 
        log.Fatalf("failed to creating db session : %s", err.Error())
        return err
    

    log.Printf("Created session - %v", _session)

    return nil

当我运行这段代码时,我得到了错误: 创建数据库会话失败:“服务器在 SASL 身份验证步骤返回错误:身份验证失败。”

如果我在创建会话之前设置 [dbDialInfo.Mechanism = "SCRAM-SHA-256"],我会收到错误消息: 未能创建数据库会话:“构建期间未启用 SASL 支持(-tags sasl)”

请告诉我是什么导致了这个问题,我该如何连接到数据库。 目前我正在使用“github.com/globalsign/mgo”,如果它需要使用任何其他库,那对我来说完全没问题。 我只想连接到数据库。

rootca.crt 文件类似于:

-----BEGIN CERTIFICATE-----
MIIGLjCCBBagAwIBAgIUbxINX1qe6W+7kolWGp+MX8NbYj8wDQYJKoZIhvcNAQEL
<blah> <blah> <blah> <blah> <blah> <blah> <blah> <blah> <blah> 
jCZAGGHmbrR3zeIsOY8yKau0IXqRp5Wy6NQ0poOTcma9BfwNUVc4/ixsCkEVYbgW
eMs=
-----END CERTIFICATE-----

谢谢。

【问题讨论】:

【参考方案1】:

经过大量研究,我找不到使用 globalsign 库的 .crt 文件连接到 mongodb 的方法。

但是,我使用 mongo-driver 库成功地做到了这一点。 这里的连接字符串可以是以下格式:

mongodb://user:password@replicaset-0.com:27017,replicaset-1.com:27017,replicaset-2.com:27017/?ssl=true&tlsCAFile=./ca.crt&tlsCertificateKeyFile=./ca.pem&authSource=admin&replicaSet=replicaset

示例代码:

import (
    "context"
    "log"
    "os"

    // "github.com/globalsign/mgo"
    mgo "go.mongodb.org/mongo-driver/mongo"

    mongoOptions "go.mongodb.org/mongo-driver/mongo/options"
)
func InitMongo() (error) 
    
    connStr := os.Getenv("MONGODB_CONN_STR")
    dbName := os.Getenv("MONGODB_DATABASE")

    clientOpts := mongoOptions.Client().ApplyURI(connStr)
    if err := clientOpts.Validate(); err != nil 
        log.Print("unable to parse url")
        log.Fatal(err)
    
    client, err := mgo.Connect(context.TODO(), clientOpts)
    if err != nil 
        log.Print("unable to connect into database")
        log.Fatal(err)
    
    if err := client.Ping(context.TODO(), nil); err != nil 
        log.Print("database ping failed")
        log.Fatal(err)
    

    //client.Database(dbName)

    return nil

【讨论】:

以上是关于如何在 Go 中使用 .crt 文件通过 ssl 连接到 mongoDB的主要内容,如果未能解决你的问题,请参考以下文章

ssl证书 只有crt文件 但是使用时需要key或pem文件 请问如何转换

ssl证书 只有crt文件 但是使用时需要key或pem文件 请问如何转换

ssl证书 只有crt文件 但是使用时需要key或pem文件 请问如何转换

如何从 uapi 命令结果中导出 cab crt、key

如何在 Linux 中转换 SSL 证书

Windows 服务器中的新 ssl 证书