使用Golang和Vault构建安全的分布式应用程序

介绍

随着云计算解决方案的普及,构建分布式应用程序已经变得越来越普遍。随之而来的挑战是如何管理和保护分布式系统中的敏感信息。

本文将介绍如何使用Golang和Vault来构建安全的分布式应用程序。

什么是Vault?

Vault 是一个开源的工具,用于安全地管理和保护敏感的数据和令牌。它提供了加密、静态和动态密钥、秘密存储和访问控制等功能。 Vault 是 HashiCorp 公司出品的又一个响当当的项目。

Vault的安装和配置

首先,你需要安装并启动 Vault。 你可以从官方网站下载Vault,官方网站提供了Linux、Windows和macOS的二进制文件

$ wget https://releases.hashicorp.com/vault/1.7.1/vault_1.7.1_linux_amd64.zip

$ unzip vault_1.7.1_linux_amd64.zip

$ sudo mv vault /usr/local/bin

接下来,使用以下命令来启动Vault

$ vault server -dev -dev-root-token-id="00000000-0000-0000-0000-000000000000"

该命令将在您的本机上启动 Vault 服务器。

Vault 启动后,可以使用以下命令检查它是否正在运行:

$ vault status

Success! Vault is initialized

使用Vault API读取和写入秘密

Vault API 具有对数据进行读取和写入的功能。通过使用Vault 的 API,应用程序能够将秘密存储在Vault 中,然后在需要时从Vault 中获取它们。

接下来,让我们尝试将一个字符串写入Vault中:

package main

import (

"fmt"

"github.com/hashicorp/vault/api"

)

func main() {

// 首先,连接到Vault API

client, err := api.NewClient(api.DefaultConfig())

if err != nil {

fmt.Println("Error connecting to the Vault API:", err)

return

}

// 设置Vault的访问令牌

client.SetToken("00000000-0000-0000-0000-000000000000")

// 将字符串写入Vault

secret := map[string]interface{}{

"value": "hello world",

}

_, err = client.Logical().Write("secret/myapp", secret)

if err != nil {

fmt.Println("Error writing to Vault:", err)

return

}

fmt.Println("Secret successfully written to Vault!")

}

现在,我们可以使用以下代码从Vault中读取刚刚写入的秘密:

package main

import (

"fmt"

"github.com/hashicorp/vault/api"

)

func main() {

// 首先,连接到Vault API

client, err := api.NewClient(api.DefaultConfig())

if err != nil {

fmt.Println("Error connecting to the Vault API:", err)

return

}

// 设置Vault的访问令牌

client.SetToken("00000000-0000-0000-0000-000000000000")

// 从Vault中读取秘密

secret, err := client.Logical().Read("secret/myapp")

if err != nil {

fmt.Println("Error reading from Vault:", err)

return

}

// 检查秘密是否存在

if secret == nil {

fmt.Println("No secret found in Vault.")

return

}

// 显示秘密

value, ok := secret.Data["value"].(string)

if !ok {

fmt.Println("Secret value is not a string!")

return

}

fmt.Println(value)

}

使用Vault保护分布式应用程序中的敏感信息

Vault 可以轻松地集成到您的应用程序中。使用Vault,您可以以安全的方式存储和管理访问令牌、数据库凭据、API 密钥等重要信息。

假设您正在编写一个使用 MongoDB 作为后端的分布式Web应用程序。代码如下:

package main

import (

"fmt"

"go.mongodb.org/mongo-driver/mongo"

"go.mongodb.org/mongo-driver/mongo/options"

"os"

)

func main() {

// 获取 MongoDB 连接配置

mongoUrl := os.Getenv("MONGODB_URL")

if mongoUrl == "" {

fmt.Println("MONGODB_URL environment variable not set!")

return

}

// 创建 MongoDB 客户端

clientOptions := options.Client().ApplyURI(mongoUrl)

client, err := mongo.NewClient(clientOptions)

if err != nil {

fmt.Println("Error creating MongoDB client:", err)

return

}

// 连接 MongoDB

err = client.Connect(nil)

if err != nil {

fmt.Println("Error connecting to MongoDB:", err)

return

}

// 断开与 MongoDB 的连接

err = client.Disconnect(nil)

if err != nil {

fmt.Println("Error disconnecting from MongoDB:", err)

return

}

fmt.Println("Successfully connected to MongoDB!")

}

该应用程序从名为 MONGODB_URL 的环境变量中获取MongoDB的连接URL。 但是,如果您使用程序中的明文密码,则可能会有安全风险。

为了解决这个问题,我们可以使用Vault将敏感的MongoDB凭据存储在Vault中,然后在应用程序中使用Vault API读取它们。

编写代码以将MongoDB连接信息存储在Vault中:

package main

import (

"fmt"

"github.com/hashicorp/vault/api"

"go.mongodb.org/mongo-driver/mongo/options"

"os"

)

func main() {

// 获取 MongoDB 连接配置

mongoUrl := os.Getenv("MONGODB_URL")

if mongoUrl == "" {

fmt.Println("MONGODB_URL environment variable not set!")

return

}

// 连接到Vault API

client, err := api.NewClient(api.DefaultConfig())

if err != nil {

fmt.Println("Error connecting to the Vault API:", err)

return

}

// 设置Vault的访问令牌

client.SetToken("00000000-0000-0000-0000-000000000000")

// 将数据库凭据写入Vault

data := map[string]interface{}{

"mongodbUrl": mongoUrl,

"mongodbUsername": "myuser",

"mongodbPassword": "mypassword",

"mongodbCertificate": "mycertificate",

}

_, err = client.Logical().Write("secret/mongodb", data)

if err != nil {

fmt.Println("Error writing to Vault:", err)

return

}

fmt.Println("Credentials successfully written to Vault!")

}

现在,在原来的Web应用程序中,我们可以使用Vault API来检索与MongoDB连接相关的敏感信息:

package main

import (

"fmt"

"github.com/hashicorp/vault/api"

"go.mongodb.org/mongo-driver/mongo"

"go.mongodb.org/mongo-driver/mongo/options"

"os"

)

func main() {

// 连接到Vault API

client, err := api.NewClient(api.DefaultConfig())

if err != nil {

fmt.Println("Error connecting to the Vault API:", err)

return

}

// 设置Vault的访问令牌

client.SetToken("00000000-0000-0000-0000-000000000000")

// 从Vault读取数据库凭据

secret, err := client.Logical().Read("secret/mongodb")

if err != nil {

fmt.Println("Error reading from Vault:", err)

return

}

// 检查是否存在凭证

if secret == nil {

fmt.Println("No credentials found in Vault.")

return

}

// 获取MongoDB连接的敏感信息

mongoUrl := secret.Data["mongodbUrl"].(string)

mongoUsername := secret.Data["mongodbUsername"].(string)

mongoPassword := secret.Data["mongodbPassword"].(string)

mongoCertificate := secret.Data["mongodbCertificate"].(string)

// 创建MongoDB客户端

clientOptions := options.Client().

ApplyURI(mongoUrl).

SetAuth(options.Credential{

AuthSource: "admin",

Username: mongoUsername,

Password: mongoPassword,

}).

SetTLSConfig(&tls.Config{

RootCAs: mongoCertificate,

InsecureSkipVerify: true,

})

client, err := mongo.NewClient(clientOptions)

if err != nil {

fmt.Println("Error creating MongoDB client:", err)

return

}

// 连接到MongoDB

err = client.Connect(nil)

if err != nil {

fmt.Println("Error connecting to MongoDB:", err)

return

}

// 断开与MongoDB的连接

err = client.Disconnect(nil)

if err != nil {

fmt.Println("Error disconnecting from MongoDB:", err)

return

}

fmt.Println("Successfully connected to MongoDB!")

}

通过使用Vault,您可以简单地存储和保护分布式系统中的敏感信息,同时保护它们不受未经授权的访问和恶意攻击。

后端开发标签