使用 vault API 包的身份验证方法
Authentication methods using the vault API package
我正在尝试使用 Vault Golang Package 通过 API 进行身份验证。
我创建了一个新客户端,然后可以设置我的令牌:
client, err := api.NewClient(&api.Config{Address: vaultAddr, HttpClient: httpClient})
if err != nil {
return nil, errors.Wrap(err, "could not create vault client")
}
client.SetToken(token)
太好了,但是我想使用其他身份验证方法(LDAP、Userpass 等)
对 API 进行身份验证
这可能吗?如何使用 API?
检索令牌
我想我可以只使用 net/http 通过 API 调用来检索令牌,但是是否有任何方法可以以另一种方式进行实际身份验证?
我最终设法解决了这个问题。这不是很明显,但很有道理。
Vault 有一个 generic write method 用于写入数据。您可以利用它通过简单地构建 URL 并将 PUT 请求发送到该端点
来使用 API 执行登录
看起来有点像这样:
// create a vault client
client, err := api.NewClient(&api.Config{Address: url, HttpClient: httpClient})
if err != nil {
panic(err)
}
// to pass the password
options := map[string]interface{}{
"password": password,
}
// the login path
// this is configurable, change userpass to ldap etc
path := fmt.Sprintf("auth/userpass/login/%s", username)
// PUT call to get a token
secret, err := client.Logical().Write(path, options)
没有足够的声誉在此处添加额外提示而不是对已接受答案的评论。可以从授权响应中提取令牌,如下所示:
client.SetToken(secret.Auth.ClientToken)
相关接口记录在这里:
我写了一个 GitHub 要点,其中包含一个使用 AWS IAM 角色对您的 Go 程序进行身份验证的函数。这里是 a link.
注意:对 Vault 进行身份验证只会让您获得一个令牌。如果 AWS IAM 角色允许,令牌稍后可用于读取机密。
您需要创建一个 AWS STS 请求,从中提取一些信息,然后将其发送到 Vault。
这是 GitHub 要点中的函数。它将使用一个 AWS IAM 角色和一些 Vault 环境变量,例如 VAULT_ADDR
。这是身份验证请求的一些 other environment variables that the Vault Golang library may read. It produces an authenticated Vault *api.Client
、令牌和响应。
它基于 this GitHub project。
package vault
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/vault/api"
)
// AWSLogin will create a Vault client, login via an AWS role, and return a valid Vault token and client that can be
// used to get secrets.
// The authProvider is likely "aws". It's the "Path" column as described in these docs:
// https://www.vaultproject.io/api/auth/aws#login.
// The serverID is an optional value to be placed in the X-Vault-AWS-IAM-Server-ID header of the HTTP request.
// The role is an AWS IAM role. It needs to be able to read secrets from Vault.
func AWSLogin(authProvider, serverID, role string) (client *api.Client, token string, secret *api.Secret, err error) {
// Create the Vault client.
//
// Configuration is gathered from environment variables by upstream vault package. Environment variables like
// VAULT_ADDR and VAULT_SKIP_VERIFY are relevant. The VAULT_TOKEN environment variable shouldn't be needed.
// https://www.vaultproject.io/docs/commands#environment-variables
if client, err = api.NewClient(nil); err != nil {
return nil, "", nil, fmt.Errorf("failed to create Vault client: %w", err)
}
// Acquire an AWS session.
var sess *session.Session
if sess, err = session.NewSession(); err != nil {
return nil, "", nil, fmt.Errorf("failed to create AWS session: %w", err)
}
// Create a Go structure to talk to the AWS token service.
tokenService := sts.New(sess)
// Create a request to the token service that will ask for the current host's identity.
request, _ := tokenService.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
// Add an server ID IAM header, if present.
if serverID != "" {
request.HTTPRequest.Header.Add("X-Vault-AWS-IAM-Server-ID", serverID)
}
// Sign the request to the AWS token service.
if err = request.Sign(); err != nil {
return nil, "", nil, fmt.Errorf("failed to sign AWS identity request: %w", err)
}
// JSON marshal the headers.
var headers []byte
if headers, err = json.Marshal(request.HTTPRequest.Header); err != nil {
return nil, "", nil, fmt.Errorf("failed to JSON marshal HTTP headers for AWS identity request: %w", err)
}
// Read the body of the request.
var body []byte
if body, err = ioutil.ReadAll(request.HTTPRequest.Body); err != nil {
return nil, "", nil, fmt.Errorf("failed to JSON marshal HTTP body for AWS identity request: %w", err)
}
// Create the data to write to Vault.
data := make(map[string]interface{})
data["iam_http_request_method"] = request.HTTPRequest.Method
data["iam_request_url"] = base64.StdEncoding.EncodeToString([]byte(request.HTTPRequest.URL.String()))
data["iam_request_headers"] = base64.StdEncoding.EncodeToString(headers)
data["iam_request_body"] = base64.StdEncoding.EncodeToString(body)
data["role"] = role
// Create the path to write to for Vault.
//
// The authProvider is the value referenced in the "Path" column in this documentation. It's likely "aws".
// https://www.vaultproject.io/api/auth/aws#login
path := fmt.Sprintf("auth/%s/login", authProvider)
// Write the AWS token service request to Vault.
if secret, err = client.Logical().Write(path, data); err != nil {
return nil, "", nil, fmt.Errorf("failed to write data to Vault to get token: %w", err)
}
if secret == nil {
return nil, "", nil, fmt.Errorf("failed to get token from Vault: %w", ErrSecret)
}
// Get the Vault token from the response.
if token, err = secret.TokenID(); err != nil {
return nil, "", nil, fmt.Errorf("failed to get token from Vault response: %w", err)
}
// Set the token for the client as the one it just received.
client.SetToken(token)
return client, token, secret, nil
}
我正在尝试使用 Vault Golang Package 通过 API 进行身份验证。
我创建了一个新客户端,然后可以设置我的令牌:
client, err := api.NewClient(&api.Config{Address: vaultAddr, HttpClient: httpClient})
if err != nil {
return nil, errors.Wrap(err, "could not create vault client")
}
client.SetToken(token)
太好了,但是我想使用其他身份验证方法(LDAP、Userpass 等)
对 API 进行身份验证这可能吗?如何使用 API?
检索令牌我想我可以只使用 net/http 通过 API 调用来检索令牌,但是是否有任何方法可以以另一种方式进行实际身份验证?
我最终设法解决了这个问题。这不是很明显,但很有道理。
Vault 有一个 generic write method 用于写入数据。您可以利用它通过简单地构建 URL 并将 PUT 请求发送到该端点
来使用 API 执行登录看起来有点像这样:
// create a vault client
client, err := api.NewClient(&api.Config{Address: url, HttpClient: httpClient})
if err != nil {
panic(err)
}
// to pass the password
options := map[string]interface{}{
"password": password,
}
// the login path
// this is configurable, change userpass to ldap etc
path := fmt.Sprintf("auth/userpass/login/%s", username)
// PUT call to get a token
secret, err := client.Logical().Write(path, options)
没有足够的声誉在此处添加额外提示而不是对已接受答案的评论。可以从授权响应中提取令牌,如下所示:
client.SetToken(secret.Auth.ClientToken)
相关接口记录在这里:
我写了一个 GitHub 要点,其中包含一个使用 AWS IAM 角色对您的 Go 程序进行身份验证的函数。这里是 a link.
注意:对 Vault 进行身份验证只会让您获得一个令牌。如果 AWS IAM 角色允许,令牌稍后可用于读取机密。
您需要创建一个 AWS STS 请求,从中提取一些信息,然后将其发送到 Vault。
这是 GitHub 要点中的函数。它将使用一个 AWS IAM 角色和一些 Vault 环境变量,例如 VAULT_ADDR
。这是身份验证请求的一些 other environment variables that the Vault Golang library may read. It produces an authenticated Vault *api.Client
、令牌和响应。
它基于 this GitHub project。
package vault
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/vault/api"
)
// AWSLogin will create a Vault client, login via an AWS role, and return a valid Vault token and client that can be
// used to get secrets.
// The authProvider is likely "aws". It's the "Path" column as described in these docs:
// https://www.vaultproject.io/api/auth/aws#login.
// The serverID is an optional value to be placed in the X-Vault-AWS-IAM-Server-ID header of the HTTP request.
// The role is an AWS IAM role. It needs to be able to read secrets from Vault.
func AWSLogin(authProvider, serverID, role string) (client *api.Client, token string, secret *api.Secret, err error) {
// Create the Vault client.
//
// Configuration is gathered from environment variables by upstream vault package. Environment variables like
// VAULT_ADDR and VAULT_SKIP_VERIFY are relevant. The VAULT_TOKEN environment variable shouldn't be needed.
// https://www.vaultproject.io/docs/commands#environment-variables
if client, err = api.NewClient(nil); err != nil {
return nil, "", nil, fmt.Errorf("failed to create Vault client: %w", err)
}
// Acquire an AWS session.
var sess *session.Session
if sess, err = session.NewSession(); err != nil {
return nil, "", nil, fmt.Errorf("failed to create AWS session: %w", err)
}
// Create a Go structure to talk to the AWS token service.
tokenService := sts.New(sess)
// Create a request to the token service that will ask for the current host's identity.
request, _ := tokenService.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
// Add an server ID IAM header, if present.
if serverID != "" {
request.HTTPRequest.Header.Add("X-Vault-AWS-IAM-Server-ID", serverID)
}
// Sign the request to the AWS token service.
if err = request.Sign(); err != nil {
return nil, "", nil, fmt.Errorf("failed to sign AWS identity request: %w", err)
}
// JSON marshal the headers.
var headers []byte
if headers, err = json.Marshal(request.HTTPRequest.Header); err != nil {
return nil, "", nil, fmt.Errorf("failed to JSON marshal HTTP headers for AWS identity request: %w", err)
}
// Read the body of the request.
var body []byte
if body, err = ioutil.ReadAll(request.HTTPRequest.Body); err != nil {
return nil, "", nil, fmt.Errorf("failed to JSON marshal HTTP body for AWS identity request: %w", err)
}
// Create the data to write to Vault.
data := make(map[string]interface{})
data["iam_http_request_method"] = request.HTTPRequest.Method
data["iam_request_url"] = base64.StdEncoding.EncodeToString([]byte(request.HTTPRequest.URL.String()))
data["iam_request_headers"] = base64.StdEncoding.EncodeToString(headers)
data["iam_request_body"] = base64.StdEncoding.EncodeToString(body)
data["role"] = role
// Create the path to write to for Vault.
//
// The authProvider is the value referenced in the "Path" column in this documentation. It's likely "aws".
// https://www.vaultproject.io/api/auth/aws#login
path := fmt.Sprintf("auth/%s/login", authProvider)
// Write the AWS token service request to Vault.
if secret, err = client.Logical().Write(path, data); err != nil {
return nil, "", nil, fmt.Errorf("failed to write data to Vault to get token: %w", err)
}
if secret == nil {
return nil, "", nil, fmt.Errorf("failed to get token from Vault: %w", ErrSecret)
}
// Get the Vault token from the response.
if token, err = secret.TokenID(); err != nil {
return nil, "", nil, fmt.Errorf("failed to get token from Vault response: %w", err)
}
// Set the token for the client as the one it just received.
client.SetToken(token)
return client, token, secret, nil
}