-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.go
129 lines (115 loc) · 3.44 KB
/
server.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
package config
import (
"github.com/fsnotify/fsnotify"
"github.com/joho/godotenv"
"github.com/kiwisheets/gql-server/util/key"
"github.com/kiwisheets/util"
"github.com/maxtroughear/goenv"
"github.com/sirupsen/logrus"
)
const (
jwtEcPrivateKey = "JWT_EC_PRIVATE_KEY_FILE"
)
var jwtEcPrivateKeyFilename string
var config Config
// Server retrieves config from environment variables
func Server() *Config {
godotenv.Load()
jwtEcPrivateKeyFilename = goenv.MustGet(jwtEcPrivateKey)
config = Config{
Version: goenv.MustGet("APP_VERSION"),
Environment: goenv.MustGet("ENVIRONMENT"),
Hash: util.HashConfig{
Salt: goenv.MustGetSecretFromEnv("HASH_SALT"),
MinLength: goenv.CanGetInt32("HASH_MIN_LENGTH", 10),
},
GraphQL: util.GqlConfig{
APIPath: goenv.CanGet("API_PATH", "/"),
ComplexityLimit: 200,
PlaygroundPath: goenv.CanGet("PLAYGROUND_PATH", "/graphql"),
PlaygroundAPIPath: goenv.CanGet("PLAYGROUND_API_PATH", "/api/"),
Port: goenv.MustGet("PORT"),
Environment: goenv.MustGet("ENVIRONMENT"),
},
Database: util.DatabaseConfig{
Host: goenv.MustGet("POSTGRES_HOST"),
Port: goenv.MustGet("POSTGRES_PORT"),
User: goenv.MustGet("POSTGRES_USER"),
Password: goenv.MustGetSecretFromEnv("POSTGRES_PASSWORD"),
Database: goenv.MustGet("POSTGRES_DB"),
MaxConnections: goenv.CanGetInt32("POSTGRES_MAX_CONNECTIONS", 20),
},
Redis: util.RedisConfig{
Address: goenv.MustGet("REDIS_ADDRESS"),
},
}
registerFileWatchers()
privateKey, err := key.ParseEcPrivateKeyFromPemStr(goenv.MustGetSecretFromFile(jwtEcPrivateKeyFilename))
if err != nil {
logrus.WithFields(logrus.Fields{
"filename": jwtEcPrivateKeyFilename,
}).Fatal("failed to parse key, check it exists and if it is a valid EC256 private key")
}
config.JWT.mutex.Lock()
config.JWT.privateKey = privateKey
config.JWT.mutex.Unlock()
return &config
}
func registerFileWatchers() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
logrus.Error("failed to initialise file watcher, will load without watching")
}
err = watcher.Add(jwtEcPrivateKeyFilename)
if err != nil {
logrus.WithFields(logrus.Fields{
"filename": jwtEcPrivateKeyFilename,
}).Error("failed to watch file, check it exists")
}
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
logrus.Error("watcher error")
continue
}
logrus.WithFields(logrus.Fields{
"event": event,
}).Debug("file watch event")
if event.Op&fsnotify.Write == fsnotify.Write {
reloadFile(event.Name)
}
case err, ok := <-watcher.Errors:
if !ok {
logrus.Error("watcher error")
continue
}
logrus.WithFields(logrus.Fields{
"error": err,
}).Error("watcher error")
}
}
}()
}
func reloadFile(filename string) {
if filename == jwtEcPrivateKeyFilename {
keyString := goenv.MustGetSecretFromFile(jwtEcPrivateKeyFilename)
if keyString == "" {
return
}
logrus.WithFields(logrus.Fields{
"filename": filename,
}).Info("reloading file")
privateKey, err := key.ParseEcPrivateKeyFromPemStr(keyString)
if err != nil {
logrus.WithFields(logrus.Fields{
"filename": jwtEcPrivateKeyFilename,
}).Error("failed to parse key, check it exists and if it is a valid EC256 private key. continuing with existing private key")
return
}
config.JWT.mutex.Lock()
config.JWT.privateKey = privateKey
config.JWT.mutex.Unlock()
}
}