-
Notifications
You must be signed in to change notification settings - Fork 6
/
main.go
132 lines (112 loc) · 3.91 KB
/
main.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
package main
import (
"fmt"
"log"
"os"
"regexp"
"strings"
"github.com/fcantournet/kubernetes-flexvolume-vault-plugin/flexvolume"
"github.com/fcantournet/kubernetes-flexvolume-vault-plugin/vault"
)
const envGeneratorTokenPath = "VAULTTMPFS_GENERATOR_TOKEN_PATH"
const envTokenFileName = "VAULTTMPFS_TOKEN_FILENAME"
const envRoleName = "VAULTTMPFS_ROLE_NAME"
const defaultTokenFilename = "vault-token"
const defaultGeneratorTokenPath = "/etc/kubernetes/vaulttoken"
const defaultRoleName = "applications"
// vaultSecretFlexVolume implement the flexvolume interface
// the struct tags are for envconfig
type vaultSecretFlexVolume struct {
GeneratorTokenPath string
TokenFilename string
RoleName string
}
// Init is a no-op here but necessary to satisfy the interface
func (v vaultSecretFlexVolume) Init() flexvolume.Response {
return flexvolume.Succeed("")
}
// Attach is not necessary for this plugin but need to be implemented to satisfy the interface
func (v vaultSecretFlexVolume) Attach(arg interface{}) flexvolume.Response {
return flexvolume.Succeed("")
}
// Detach is not necessary for this plugin but need to be implemented to satisfy the interface
func (v vaultSecretFlexVolume) Detach(arg string) flexvolume.Response {
return flexvolume.Succeed("")
}
// Mount create the tmpfs volume and mounts it @ dir
func (v vaultSecretFlexVolume) Mount(dir string, dev string, options map[string]string) flexvolume.Response {
stringPolicies, ok := options["vault/policies"]
if !ok {
return flexvolume.Fail(fmt.Sprintf("Missing policies under %v in %v:", "vault/policies", options))
}
policies := strings.Split(strings.Replace(stringPolicies, " ", "", -1), ",")
if len(policies) == 0 {
return flexvolume.Fail(fmt.Sprintf("Empty policies under %v in %v:", "vault/policies", options))
}
// By default we do not unwrap the token
unwraptoken := false
unwraptokenstring, ok := options["vault/unwrap"]
if ok && strings.Compare(strings.ToLower(unwraptokenstring), "true") == 0 {
unwraptoken = true
}
poduidreg := regexp.MustCompile("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{8}")
poduid := poduidreg.FindString(dir)
if poduid == "" {
return flexvolume.Fail(fmt.Sprintf("Couldn't extract poduid from path %v", dir))
}
client, err := vault.InitVaultClient(v.GeneratorTokenPath, v.RoleName)
if err != nil {
return flexvolume.Fail(err.Error())
}
token, metadata, err := client.GetTokenData(policies, poduid, unwraptoken)
if err != nil {
return flexvolume.Fail(fmt.Sprintf("Couldn't obtain token: %v", err))
}
err = writeTokenData(token, metadata, dir, v.TokenFilename)
if err != nil {
err2 := cleanup(dir)
if err2 != nil {
return flexvolume.Fail(fmt.Sprintf("Couldn't create secret volume: %v (failed cleanup: %v)", err, err2))
}
return flexvolume.Fail(fmt.Sprintf("Couldn't create secret volume: %v", err))
}
return flexvolume.Succeed("")
}
// Unmount unmounts the volume ( and delete the tmpfs ?)
func (v vaultSecretFlexVolume) Unmount(dir string) flexvolume.Response {
err := cleanup(dir)
if err != nil {
return flexvolume.Fail(fmt.Sprintf("Failed to Unmount: %v", err))
}
return flexvolume.Succeed(fmt.Sprintf("Unmounted: %v", dir))
}
func main() {
vf := vaultSecretFlexVolume{
GeneratorTokenPath: defaultGeneratorTokenPath,
TokenFilename: defaultTokenFilename,
RoleName: defaultRoleName,
}
if v, ok := os.LookupEnv(envGeneratorTokenPath); ok {
vf.GeneratorTokenPath = v
}
if v, ok := os.LookupEnv(envTokenFileName); ok {
vf.TokenFilename = v
}
if v, ok := os.LookupEnv(envRoleName); ok {
vf.RoleName = v
}
if len(os.Args) == 2 && os.Args[1] == "bootstrap" {
if err := Bootstrap(vf.GeneratorTokenPath); err != nil {
log.Fatal(err)
}
log.Println("Done !")
os.Exit(0)
}
if len(os.Args) == 2 && os.Args[1] == "renew-token" {
if err := renewtoken(vf.GeneratorTokenPath); err != nil {
log.Fatal(err)
}
os.Exit(0)
}
flexvolume.RunPlugin(vf)
}