首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用数据库/sql库并在新连接失败时从vault获取密码

问使用数据库/sql库并在新连接失败时从vault获取密码
EN

Stack Overflow用户
提问于 2019-05-29 15:52:56
回答 2查看 532关注 0票数 0

我有一个用Go编写的长时间运行的守护进程,它监听一个端口,并为每个新连接启动多个go例程来处理数据。在我的脚本的func db ()中,有一个全局变量database/sql被分配了连接上下文,该上下文是由main库的open()函数返回的。

出于安全原因,我们将数据库密码存储在保险库中,每隔几天轮换一次。我可以在vault第一次创建连接上下文时从vault获取密码,并且在所有go例程中都使用相同的上下文来创建新的数据库连接。但是,当vault轮换密码时,所有新的数据库连接都会失败。我想知道处理这种情况的最好方法是什么,以便它在失败时从保管库获取密码并重新连接。如果它是一种oop语言,我可以扩展db库并覆盖连接函数来捕获错误,并在连接失败时从vault获取密码。有没有类似的方法可以在Go中使用,或者有任何其他的方法来处理这个问题?我是新来的,如果我没有把问题说对,很抱歉。

代码语言:javascript
复制
package main

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "net"
)

var db *sql.DB
const port = "port number"

func main() {

    db, err = sql.Open("mysql","<Connection string that contains the password fetched from vault>")

    db.SetMaxOpenConns(100)

    listener, err := net.Listen("tcp", ":"+port)

    for {
        conn, err := listener.Accept() 

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    // Uses db variable to connect to db.
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-12 12:35:38

我已经解决了这个问题,创建了一个自定义驱动程序,导入github.com/go- sql - driver /mysql并在sql包中注册,这样当需要新连接时,客户驱动程序可以从vault获取密码,并将其传递给mysql驱动程序以打开连接。请参考下面的代码示例。

代码语言:javascript
复制
package vault-mysql-driver

import (
    "database/sql"
    "github.com/go-sql-driver/mysql"
)

type VaultMysqlDriver struct {
    *mysql.MySQLDriver
}

func updateDsn(dsn string) (string, err) {
    // logic to fetch password from vault and update dsn with the password
}

func (d VaultMysqlDriver) Open(dsn string) (driver.Conn, error) {

    updateddsn, err := updateDsn(dsn)

    // Pass down the dsn with password to mysql driver's open function
    return d.MySQLDriver.Open(updateddsn)

}

// When initialised will register the driver in sql package
func init() {
    sql.Register(vault-driver, &CyberarkMysqlDriver{&mysql.MySQLDriver{}})
}

这个包现在被导入到守护进程中,如下所示:

代码语言:javascript
复制
import (
    "database/sql"
    _ "vault-mysql-driver"// init is invoked and it will get registered in sql package
    "net"
)

var db *sql.DB
const port = "port number"

func main() {
    // vault-driver is used instead of mysql so that the sql package knows to use the custom driver for new connections.
    db, err = sql.Open("vault-driver","<Connection string that contains the password fetched from vault>")

    db.SetMaxOpenConns(100)

    listener, err := net.Listen("tcp", ":"+port)

    for {
        conn, err := listener.Accept() 

        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    // Uses db variable to connect to db.
}

这样,每当vault轮换密码时,都不会有任何连接失败,因为vault驱动程序总是会为每个新连接从vault获取密码。

票数 0
EN

Stack Overflow用户

发布于 2019-06-04 09:26:30

为什么你必须在main上创建上下文?为什么不创建一个单独的包/名称空间并在其中执行数据库连接。使用方法创建新的命名空间...createDBClient()这将通过从存储库获取密码来创建新的数据库上下文,并将其存储在全局var db中GetDBClient()这将检查全局var数据库中是否包含某些内容,如果是,则检查它是否可以连接到数据库(https://golang.org/pkg/database/sql/#DB.Ping)如果不能连接,则调用createDBClient()多次使用睡眠循环此方法如果未连接则崩溃,如果连接则返回上下文

现在,在您的handleConnection()中调用db := newnamespace.GetDBClient()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56355577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档