Vault には TOTP Secrets Engine があり、TOTP コードの生成や検証が可能になっている。
ここでは、TOTP Secrets Engine を利用し、Go からそれを利用する方法についてメモ程度に書く。
TOTP Secrets Engine を有効にする
$ vault secrets enable totp
デフォルトでは totp/
という Path になるので、必要に応じて -path
オプションで変更する。
CLI で試す
generate=true
というオプションを渡すことで named key を作ることができ、 account_name
と紐付けることができる。
❯ vault write totp/keys/username generate=true issuer=Vault-TOTP-Demo account_name=user@example.com
Key Value
--- -----
barcode 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
url otpauth://totp/Vault-TOTP-Demo:user@example.com?algorithm=SHA1&digits=6&issuer=Vault-TOTP-Demo&period=30&secret=I2O7ICIEYIXIQNX5AAARCTWW5BX6N3AD
barcode
は QR コードを Base64 エンコードしたもの。
適当に echo $BARCODE | base64 -d > qrcode.png
などして開き、Google Authenticator などで開くと利用できる。
TOTP コードの検証はパスに write するだけで可能。
❯ vault write totp/code/username code=123456
Key Value
--- -----
valid false # 間違っている場合は false
❯ vault write totp/code/username code=892373
Key Value
--- -----
valid true # 正しい場合は true
Go から使う
Vault は API クライアントがあり、これを利用する。
package main
import (
"encoding/json"
"fmt"
"net/http"
"time"
"os"
"github.com/hashicorp/vault/api"
)
const (
vaultAddr = os.Getenv("VAULT_ADDR")
staticToken = os.Getenv("VAULT_TOKEN")
)
var httpClient = &http.Client{
Timeout: 10 * time.Second,
}
func main() {
token := staticToken
client, err := api.NewClient(&api.Config{Address: vaultAddr, HttpClient: httpClient})
if err != nil {
panic(err)
}
client.SetToken(token)
code := "123456"
username := "username"
path := "totp/code/" + username
data := map[string]interface{}{"code": code}
resp, err := client.Logical().Write(path, data)
if err != nil {
panic(err)
}
b, _ := json.Marshal(resp.Data)
fmt.Println(string(b))
}
❯ go run totp.go # 間違っている場合
{"valid":false}
❯ go run totp.go # 正しい場合
{"valid":true}
このように、かなり簡単に TOTP が利用できる。バックアップコードなどはアプリケーション側で生成して持つようにして、TOTP の実装は Vault に任せるとすると手軽で良さそう。