forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
policy_store.go
158 lines (136 loc) · 3.83 KB
/
policy_store.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package vault
import (
"fmt"
"time"
"github.com/armon/go-metrics"
"github.com/hashicorp/golang-lru"
"github.com/hashicorp/vault/logical"
)
const (
// policySubPath is the sub-path used for the policy store
// view. This is nested under the system view.
policySubPath = "policy/"
// policyCacheSize is the number of policies that are kept cached
policyCacheSize = 1024
)
// PolicyStore is used to provide durable storage of policy, and to
// manage ACLs associated with them.
type PolicyStore struct {
view *BarrierView
lru *lru.Cache
}
// NewPolicyStore creates a new PolicyStore that is backed
// using a given view. It used used to durable store and manage named policy.
func NewPolicyStore(view *BarrierView) *PolicyStore {
cache, _ := lru.New(policyCacheSize)
p := &PolicyStore{
view: view,
lru: cache,
}
return p
}
// setupPolicyStore is used to initialize the policy store
// when the vault is being unsealed.
func (c *Core) setupPolicyStore() error {
// Create a sub-view
view := c.systemView.SubView(policySubPath)
// Create the policy store
c.policy = NewPolicyStore(view)
return nil
}
// teardownPolicyStore is used to reverse setupPolicyStore
// when the vault is being sealed.
func (c *Core) teardownPolicyStore() error {
c.policy = nil
return nil
}
// SetPolicy is used to create or update the given policy
func (ps *PolicyStore) SetPolicy(p *Policy) error {
defer metrics.MeasureSince([]string{"policy", "set_policy"}, time.Now())
if p.Name == "root" {
return fmt.Errorf("cannot update root policy")
}
if p.Name == "" {
return fmt.Errorf("policy name missing")
}
entry := &logical.StorageEntry{
Key: p.Name,
Value: []byte(p.Raw),
}
if err := ps.view.Put(entry); err != nil {
return fmt.Errorf("failed to persist policy: %v", err)
}
// Update the LRU cache
ps.lru.Add(p.Name, p)
return nil
}
// GetPolicy is used to fetch the named policy
func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) {
defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now())
// Check for cached policy
if raw, ok := ps.lru.Get(name); ok {
return raw.(*Policy), nil
}
// Special case the root policy
if name == "root" {
p := &Policy{Name: "root"}
ps.lru.Add(p.Name, p)
return p, nil
}
// Load the policy in
out, err := ps.view.Get(name)
if err != nil {
return nil, fmt.Errorf("failed to read policy: %v", err)
}
if out == nil {
return nil, nil
}
// Parse into a policy object
p, err := Parse(string(out.Value))
if err != nil {
return nil, fmt.Errorf("failed to parse policy: %v", err)
}
p.Name = name
// Update the LRU cache
ps.lru.Add(p.Name, p)
return p, nil
}
// ListPolicies is used to list the available policies
func (ps *PolicyStore) ListPolicies() ([]string, error) {
defer metrics.MeasureSince([]string{"policy", "list_policies"}, time.Now())
// Scan the view, since the policy names are the same as the
// key names.
return CollectKeys(ps.view)
}
// DeletePolicy is used to delete the named policy
func (ps *PolicyStore) DeletePolicy(name string) error {
defer metrics.MeasureSince([]string{"policy", "delete_policy"}, time.Now())
if name == "root" {
return fmt.Errorf("cannot delete root policy")
}
if err := ps.view.Delete(name); err != nil {
return fmt.Errorf("failed to delete policy: %v", err)
}
// Clear the cache
ps.lru.Remove(name)
return nil
}
// ACL is used to return an ACL which is built using the
// named policies.
func (ps *PolicyStore) ACL(names ...string) (*ACL, error) {
// Fetch the policies
var policy []*Policy
for _, name := range names {
p, err := ps.GetPolicy(name)
if err != nil {
return nil, fmt.Errorf("failed to get policy '%s': %v", name, err)
}
policy = append(policy, p)
}
// Construct the ACL
acl, err := NewACL(policy)
if err != nil {
return nil, fmt.Errorf("failed to construct ACL: %v", err)
}
return acl, nil
}