import (
"context"
+ "encoding/base64"
"fmt"
"io/ioutil"
"log"
"sync"
"time"
+ consulAPI "github.com/hashicorp/consul/api"
"github.com/hashicorp/vault/api"
)
return err
}
+ masterToken, err := ioutil.ReadFile(cfg.masterTokenFile())
+ if err != nil {
+ return err
+ }
+
cfgPath := path.Join(cfg.DataDir, "vault.hcl")
err = atomicWriteFile(cfgPath, []byte(fmt.Sprintf(`backend "consul" {
address = "127.0.0.1:%d"
path = "vault"
+ token = %q
}
listener "tcp" {
address = "127.0.0.1:%d"
tls_disable = 1
- }`, cfg.Ports.ConsulHTTP, cfg.Ports.VaultServer)), 0644)
+ }`, cfg.Ports.ConsulHTTP, masterToken, cfg.Ports.VaultServer)), 0644)
if err != nil {
return err
}
}
atomicWriteJSON(path.Join(cfg.DataDir, "vault-keys.json"), resp, 0400)
atomicWriteFile(path.Join(cfg.DataDir, "vault-root-token.txt"), []byte(resp.RootToken), 0400)
+ vault.SetToken(resp.RootToken)
+ ok := false
for _, key := range resp.Keys {
resp, err := vault.Sys().Unseal(key)
if err != nil {
}
if !resp.Sealed {
log.Printf("unseal successful")
- return nil
+ ok = true
+ break
}
}
- return fmt.Errorf("vault unseal failed!")
+ if !ok {
+ return fmt.Errorf("vault unseal failed!")
+ }
+
+ // Use master token to create a management token
+ master, err := consul.master(ctx)
+ if err != nil {
+ return err
+ }
+ mgmtToken, _, err := master.ACL().Create(&consulAPI.ACLEntry{Name: "vault", Type: "management"}, nil)
+ if err != nil {
+ return err
+ }
+ if err = atomicWriteFile(path.Join(cfg.DataDir, "vault-mgmt-token.txt"), []byte(mgmtToken), 0400); err != nil {
+ return err
+ }
+
+ // Mount+configure consul backend
+ if err = waitCheck(ctx, 30*time.Second, func(context.Context) error {
+ // Typically this first fails "500 node not active but
+ // active node not found" but then succeeds.
+ return vault.Sys().Mount("consul", &api.MountInput{Type: "consul"})
+ }); err != nil {
+ return err
+ }
+ _, err = vault.Logical().Write("consul/config/access", map[string]interface{}{
+ "address": fmt.Sprintf("127.0.0.1:%d", cfg.Ports.ConsulHTTP),
+ "token": string(mgmtToken),
+ })
+ if err != nil {
+ return err
+ }
+
+ // Create a role
+ _, err = vault.Logical().Write("consul/roles/write-all", map[string]interface{}{
+ "policy": base64.StdEncoding.EncodeToString([]byte(`key "" { policy = "write" }`)),
+ })
+ if err != nil {
+ return err
+ }
+
+ // Generate a new token with the write-all role
+ secret, err := vault.Logical().Read("consul/creds/write-all")
+ if err != nil {
+ return err
+ }
+ token, ok := secret.Data["token"].(string)
+ if !ok {
+ return fmt.Errorf("secret token broken?? %+v", secret)
+ }
+ log.Printf("Vault supplied token with lease duration %s (renewable=%v): %q", time.Duration(secret.LeaseDuration)*time.Second, secret.Renewable, token)
+ return nil
}
func (vb *vaultBooter) client(ctx context.Context) (*api.Client, error) {