-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend.go
111 lines (91 loc) · 2.26 KB
/
backend.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package vault_plugin_secrets_grafana
import (
"context"
"fmt"
"strings"
"sync"
"github.com/Boostport/vault-plugin-secrets-grafana/client"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
func Factory(version string) logical.Factory {
return func(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) {
b := backend(version)
if err := b.Setup(ctx, conf); err != nil {
return nil, err
}
return b, nil
}
}
type grafanaBackend struct {
*framework.Backend
lock sync.RWMutex
client *client.Grafana
}
func backend(version string) *grafanaBackend {
var b grafanaBackend
b.Backend = &framework.Backend{
Help: strings.TrimSpace(backendHelp),
PathsSpecial: &logical.Paths{
SealWrapStorage: []string{
"config",
"role/*",
},
},
Paths: framework.PathAppend(
pathRole(&b),
[]*framework.Path{
pathConfig(&b),
pathCredentials(&b),
},
),
Secrets: []*framework.Secret{
b.grafanaToken(),
},
BackendType: logical.TypeLogical,
Invalidate: b.invalidate,
}
if version != "" {
b.Backend.RunningVersion = fmt.Sprintf("v%s", version)
}
return &b
}
func (b *grafanaBackend) reset() {
b.lock.Lock()
defer b.lock.Unlock()
b.client = nil
}
func (b *grafanaBackend) invalidate(_ context.Context, key string) {
if key == configStoragePath {
b.reset()
}
}
func (b *grafanaBackend) getClient(ctx context.Context, s logical.Storage) (*client.Grafana, error) {
b.lock.RLock()
unlockFunc := b.lock.RUnlock
defer func() { unlockFunc() }()
if b.client != nil {
return b.client, nil
}
b.lock.RUnlock()
b.lock.Lock()
unlockFunc = b.lock.Unlock
config, err := getConfig(ctx, s)
if err != nil {
return nil, err
}
if config == nil {
config = new(grafanaConfig)
}
baseURL := strings.TrimSuffix(strings.ToLower(config.URL), "/")
b.client, err = client.New(baseURL, config.Token)
if err != nil {
return nil, fmt.Errorf("error creating grafana client: %w", err)
}
return b.client, nil
}
const backendHelp = `
The Grafana secrets backend dynamically generates Grafana Cloud Access Policy tokens and Grafana Service Account tokens.
After mounting this backend, credentials to manage Grafana Cloud or Grafana tokens must be configured with the
"config/" endpoint.
`