1package dependency
2
3import (
4	"log"
5	"time"
6
7	"github.com/hashicorp/vault/api"
8)
9
10var (
11	// Ensure implements
12	_ Dependency = (*VaultTokenQuery)(nil)
13)
14
15// VaultTokenQuery is the dependency to Vault for a secret
16type VaultTokenQuery struct {
17	stopCh      chan struct{}
18	secret      *Secret
19	vaultSecret *api.Secret
20}
21
22// NewVaultTokenQuery creates a new dependency.
23func NewVaultTokenQuery(token string) (*VaultTokenQuery, error) {
24	vaultSecret := &api.Secret{
25		Auth: &api.SecretAuth{
26			ClientToken:   token,
27			Renewable:     true,
28			LeaseDuration: 1,
29		},
30	}
31	return &VaultTokenQuery{
32		stopCh:      make(chan struct{}, 1),
33		vaultSecret: vaultSecret,
34		secret:      transformSecret(vaultSecret),
35	}, nil
36}
37
38// Fetch queries the Vault API
39func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
40	select {
41	case <-d.stopCh:
42		return nil, nil, ErrStopped
43	default:
44	}
45
46	if vaultSecretRenewable(d.secret) {
47		renewSecret(clients, d)
48	}
49
50	// The secret isn't renewable, probably the generic secret backend.
51	// TODO This is incorrect when given a non-renewable template. We should
52	// instead to a lookup self to determine the lease duration.
53	opts = opts.Merge(&QueryOptions{})
54	dur := leaseCheckWait(d.secret)
55	if dur < opts.VaultGrace {
56		dur = opts.VaultGrace
57	}
58
59	log.Printf("[TRACE] %s: token is not renewable, sleeping for %s", d, dur)
60	select {
61	case <-time.After(dur):
62	case <-d.stopCh:
63		return nil, nil, ErrStopped
64	}
65
66	return nil, nil, ErrLeaseExpired
67}
68
69func (d *VaultTokenQuery) stopChan() chan struct{} {
70	return d.stopCh
71}
72
73func (d *VaultTokenQuery) secrets() (*Secret, *api.Secret) {
74	return d.secret, d.vaultSecret
75}
76
77// CanShare returns if this dependency is shareable.
78func (d *VaultTokenQuery) CanShare() bool {
79	return false
80}
81
82// Stop halts the dependency's fetch function.
83func (d *VaultTokenQuery) Stop() {
84	close(d.stopCh)
85}
86
87// String returns the human-friendly version of this dependency.
88func (d *VaultTokenQuery) String() string {
89	return "vault.token"
90}
91
92// Type returns the type of this dependency.
93func (d *VaultTokenQuery) Type() Type {
94	return TypeVault
95}
96