-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathstore_sweeper.go
executable file
·128 lines (104 loc) · 2.93 KB
/
store_sweeper.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
package store
import (
"io/ioutil"
"log"
"os"
"path"
"time"
)
func (s *Store) SweepContinuously() {
for {
s.Sweep()
time.Sleep(time.Minute)
}
}
func (s *Store) Sweep() error {
err := s.SweepSecrets(s.SecretLifetime)
if err != nil {
return err
}
err = s.SweepBeingAccessed(s.SecretLifetime + time.Minute)
if err != nil {
return err
}
err = s.SweepAccessed()
if err != nil {
return err
}
err = s.SweepExpiring()
if err != nil {
return err
}
err = s.SweepExpired()
if err != nil {
return err
}
return nil
}
func (s *Store) SweepSecrets(maxAge time.Duration) error {
files, err := ioutil.ReadDir(s.Root)
if err != nil {
log.Print("Error reading store to sweep secrets:", err)
return err
}
cutoff := time.Now().Add(-maxAge)
for _, fileInfo := range files {
if !fileInfo.IsDir() && fileInfo.ModTime().Before(cutoff) {
// Make a record of this secret's expiration
expiredFilePath := path.Join(s.ExpiredPath, fileInfo.Name())
ioutil.WriteFile(expiredFilePath, nil, 0600)
// Move secret to expiring folder. Sweep there will zero and remove it.
expiringFilePath := path.Join(s.ExpiringPath, fileInfo.Name())
filePath := path.Join(s.Root, fileInfo.Name())
err = os.Rename(filePath, expiringFilePath)
if err != nil {
// Just log the error, don't abort sweep.
log.Print("Error moving", filePath, "to", expiringFilePath, err)
} else {
// Rewrite the expired record with the code from the secret file
code := make([]byte, CodeByteSize)
file, err := os.Open(expiringFilePath)
if err != nil {
log.Print("Error opening", filePath, err)
} else {
_, err := file.Read(code)
if err != nil {
log.Print("Error reading", filePath, err)
}
file.Close()
ioutil.WriteFile(expiredFilePath, code, 0400)
}
}
}
}
return nil
}
// This folder shouldn't have leftovers, but just in case...
func (s *Store) SweepBeingAccessed(maxAge time.Duration) error {
// One minute to read the secret should be more than plenty
return sweepFolder(s.BeingAccessedPath, maxAge)
}
func (s *Store) SweepAccessed() error {
return sweepFolder(s.AccessedPath, 24 * time.Hour)
}
func (s *Store) SweepExpiring() error {
return sweepFolder(s.ExpiringPath, 0)
}
func (s *Store) SweepExpired() error {
return sweepFolder(s.ExpiredPath, 24 * time.Hour)
}
func sweepFolder(folderPath string, maxAge time.Duration) error {
files, err := ioutil.ReadDir(folderPath)
if err != nil {
log.Print("Error reading", folderPath, "folder to sweep secrets:", err)
return err
}
cutoff := time.Now().Add(-maxAge)
for _, fileInfo := range files {
if !fileInfo.IsDir() && fileInfo.ModTime().Before(cutoff) {
filePath := path.Join(folderPath, fileInfo.Name())
zeroFileAndRemove(filePath)
}
}
return nil
}