forked from hashicorp/vault-lambda-extension
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
134 lines (114 loc) · 3.45 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
133
134
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"os/signal"
"path"
"syscall"
"github.com/hashicorp/vault-lambda-extension/config"
"github.com/hashicorp/vault-lambda-extension/extension"
"github.com/hashicorp/vault-lambda-extension/vault"
)
const (
extensionName = "vault-lambda-extension"
)
var (
extensionClient = extension.NewClient(os.Getenv("AWS_LAMBDA_RUNTIME_API"))
)
func main() {
logger := log.New(os.Stderr, fmt.Sprintf("[%s] ", extensionName), log.Ldate|log.Ltime|log.LUTC)
ctx, cancel := context.WithCancel(context.Background())
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT)
go func() {
s := <-sigs
cancel()
logger.Println("Received", s)
logger.Println("Exiting")
}()
_, err := extensionClient.Register(ctx, extensionName)
if err != nil {
logger.Fatal(err)
}
initialiseExtension(logger)
processEvents(ctx, logger)
}
func initialiseExtension(logger *log.Logger) {
logger.Println("Initialising")
vaultAddr := os.Getenv("VAULT_ADDR")
vaultAuthRole := os.Getenv("VAULT_AUTH_ROLE")
vaultAuthProvider := os.Getenv("VAULT_AUTH_PROVIDER")
configuredSecrets, err := config.ParseConfiguredSecrets()
if err != nil {
logger.Fatalf("Failed to parse configured secrets to read: %s", err)
}
if vaultAddr == "" || vaultAuthProvider == "" || vaultAuthRole == "" || len(configuredSecrets) == 0 {
logger.Fatal("missing VAULT_ADDR, VAULT_AUTH_PROVIDER, VAULT_AUTH_ROLE, or VAULT_SECRET_ environment variables.")
}
client, err := vault.NewClient(logger, vaultAuthRole, vaultAuthProvider)
if err != nil {
logger.Fatalf("error getting client: %s", err)
} else if client == nil {
logger.Fatalf("nil client returned: %s", err)
}
if _, err = os.Stat(config.DefaultSecretDirectory); os.IsNotExist(err) {
err = os.MkdirAll(config.DefaultSecretDirectory, 0755)
if err != nil {
logger.Fatalf("Failed to create directory %s: %s", config.DefaultSecretDirectory, err)
}
}
err = ioutil.WriteFile(path.Join(config.DefaultSecretDirectory, "token"), []byte(client.Token()), 0644)
if err != nil {
logger.Fatal(err)
}
for _, s := range configuredSecrets {
// Will block until shutdown event is received or cancelled via the context.
secret, err := client.Logical().Read(s.VaultPath)
if err != nil {
logger.Fatalf("error reading secret: %s", err)
}
content, err := json.MarshalIndent(secret, "", " ")
if err != nil {
logger.Fatalf("%s", err)
}
dir := path.Dir(s.FilePath)
if _, err = os.Stat(dir); os.IsNotExist(err) {
err = os.MkdirAll(dir, 0755)
if err != nil {
logger.Fatalf("Failed to create directory %q for secret %s: %s", dir, s.Name(), err)
}
}
err = ioutil.WriteFile(s.FilePath, content, 0644)
if err != nil {
logger.Fatal(err)
}
}
logger.Println("Initialised")
}
// processEvents polls the Lambda Extension API for events. Currently all this
// does is signal readiness to the Lambda platform after each event, which is
// required in the Extension API.
func processEvents(ctx context.Context, logger *log.Logger) {
for {
select {
case <-ctx.Done():
return
default:
logger.Println("Waiting for event...")
res, err := extensionClient.NextEvent(ctx)
if err != nil {
logger.Fatalf("Error receiving event: %s", err)
}
logger.Println("Received event")
// Exit if we receive a SHUTDOWN event
if res.EventType == extension.Shutdown {
logger.Println("Received SHUTDOWN event, exiting")
return
}
}
}
}