1
0
Fork 0
mirror of https://github.com/Luzifer/vault-user-token.git synced 2024-11-09 01:40:11 +00:00
vault-user-token/main.go

122 lines
2.7 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
"time"
"github.com/hashicorp/vault/api"
homedir "github.com/mitchellh/go-homedir"
log "github.com/sirupsen/logrus"
"github.com/Luzifer/rconfig/v2"
)
var (
cfg = struct {
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warning, error)"`
UseFullHostname bool `flag:"full-hostname" default:"true" description:"Use the full reported hostname (true) or only the first part (false)"`
VaultAddress string `flag:"vault-addr" env:"VAULT_ADDR" default:"https://127.0.0.1:8200" description:"Vault API address"`
VaultRoleID string `flag:"vault-role-id" env:"VAULT_ROLE_ID" default:"" description:"ID of the role to use"`
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
}{}
version = "dev"
hostname string
client *api.Client
)
func init() {
rconfig.AutoEnv(true)
if err := rconfig.Parse(&cfg); err != nil {
log.Fatalf("Unable to parse commandline options: %s", err)
}
if cfg.VersionAndExit {
fmt.Printf("vault-user-token %s\n", version)
os.Exit(0)
}
if cfg.VaultRoleID == "" {
log.Fatalf("You need to supply a role id for this to work")
}
if logLevel, err := log.ParseLevel(cfg.LogLevel); err == nil {
log.SetLevel(logLevel)
} else {
log.Fatalf("Unable to parse log level: %s", err)
}
var err error
if hostname, err = os.Hostname(); err != nil {
log.Fatalf("Could not resolve hostname: %s", err)
}
if parts := strings.Split(hostname, "."); !cfg.UseFullHostname && len(parts) > 1 {
hostname = parts[0]
}
}
func main() {
var err error
client, err = api.NewClient(&api.Config{
Address: cfg.VaultAddress,
})
if err != nil {
log.Fatalf("Unable to create new vault client: %s", err)
}
for {
if err := authenticateVault(); err != nil {
log.Fatalf("Unable to authenticate vault: %s", err)
}
keepRenewingToken()
}
}
func keepRenewingToken() error {
for {
var (
lease *api.Secret
err error
)
if lease, err = client.Auth().Token().RenewSelf(900); err != nil {
log.Errorf("Could not renew token: %s", err)
return err
}
log.Debugf("Token renewed for another %d seconds.", lease.Auth.LeaseDuration)
<-time.After((time.Duration(lease.Auth.LeaseDuration) - 30) * time.Second)
}
}
func authenticateVault() error {
data := map[string]interface{}{
"role_id": cfg.VaultRoleID,
"secret_id": hostname,
}
loginSecret, lserr := client.Logical().Write("auth/approle/login", data)
if lserr != nil || loginSecret.Auth == nil {
return lserr
}
client.SetToken(loginSecret.Auth.ClientToken)
tokenFile, err := homedir.Expand("~/.vault-token")
if err != nil {
return err
}
return ioutil.WriteFile(tokenFile, []byte(loginSecret.Auth.ClientToken), 0o600)
}