/
main.go
163 lines (145 loc) · 4.44 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package main
import (
"fmt"
"log"
"os"
"time"
//"github.com/pkg/errors"
"github.com/spf13/pflag"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/imorph/gate-keeper/pkg/server"
"github.com/imorph/gate-keeper/pkg/signals"
"github.com/imorph/gate-keeper/pkg/version"
)
func main() {
if err := run(); err != nil {
log.Println("error :", err)
os.Exit(1)
}
}
func run() error {
startTime := time.Now()
// ==================
// Configuration
var cfg struct {
ListenHost string
LogLevel string
LoginThreshold int
PassThreshold int
IPThreshold int
Logger *zap.Logger
}
// command line flags
pfs := pflag.NewFlagSet(version.GetAppName(), pflag.ContinueOnError)
pfs.StringVar(&cfg.ListenHost, "listen-host", "127.0.0.1:10001", "ip:port server will listen on")
pfs.StringVar(&cfg.LogLevel, "log-level", "info", "verbosity of logs, known levels are: debug, info, warn, error, fatal, panic")
pfs.IntVar(&cfg.LoginThreshold, "max-login", 10, "Maximum alowed login attemps before ban")
pfs.IntVar(&cfg.PassThreshold, "max-pass", 100, "Maximum alowed login attemps with same password before ban")
pfs.IntVar(&cfg.IPThreshold, "max-ip", 1000, "Maximum alowed login attemps from single IP before ban")
versionFlag := pfs.BoolP("version", "v", false, "get version number")
// parse flags
err := pfs.Parse(os.Args[1:])
switch {
case err == pflag.ErrHelp:
os.Exit(0)
case err != nil:
pfs.PrintDefaults()
return err
case *versionFlag:
fmt.Printf("%s-%s\n", version.GetVersion(), version.GetRevision())
os.Exit(0)
}
// ==================
// configure logging
cfg.Logger, err = initZap(cfg.LogLevel)
if err != nil {
return err
}
defer func() {
err := cfg.Logger.Sync()
if err != nil {
// may show "sync /dev/stderr: invalid argument" but this is ok?
// https://github.com/uber-go/zap/issues/328
cfg.Logger.Sugar().Warn("error syncing logger", err)
}
}()
stdLog := zap.RedirectStdLog(cfg.Logger)
defer stdLog()
s := server.NewGateKeeperServer(cfg.ListenHost, cfg.Logger, cfg.IPThreshold, cfg.LoginThreshold, cfg.PassThreshold)
go func(s *server.GateKeeperServer) {
err = s.Start()
if err != nil {
cfg.Logger.Error("Error starting server", zap.Error(err))
os.Exit(1)
}
}(s)
cfg.Logger.Info("Application started",
zap.Duration("startup_duration", time.Since(startTime)),
zap.String("listen_address", cfg.ListenHost),
zap.String("log_level", cfg.LogLevel),
zap.String("app_name", version.GetAppName()),
zap.String("version", version.GetVersion()),
zap.String("revision", version.GetRevision()),
)
sig := signals.WaitForSigterm()
//==========================
//stop sequence
sigtime := time.Now()
s.Stop()
cfg.Logger.Sugar().Info("OS signal received, stopping. ", "signal: ", sig)
cfg.Logger.Info("Application stopped",
zap.Duration("stop_duration", time.Since(sigtime)),
zap.String("app_name", version.GetAppName()),
zap.String("version", version.GetVersion()),
zap.String("revision", version.GetRevision()),
)
return nil
}
// zap initialisation logic
func initZap(logLevel string) (*zap.Logger, error) {
level := zap.NewAtomicLevelAt(zapcore.InfoLevel)
_ = level // to satisfy staticcheck
switch logLevel {
case "debug":
level = zap.NewAtomicLevelAt(zapcore.DebugLevel)
case "info":
level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
case "warn":
level = zap.NewAtomicLevelAt(zapcore.WarnLevel)
case "error":
level = zap.NewAtomicLevelAt(zapcore.ErrorLevel)
case "fatal":
level = zap.NewAtomicLevelAt(zapcore.FatalLevel)
case "panic":
level = zap.NewAtomicLevelAt(zapcore.PanicLevel)
default:
log.Fatal("Dont know this log level:", logLevel, "known levels are: debug, info, warn, error, fatal, panic")
}
zapEncoderConfig := zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
zapConfig := zap.Config{
Level: level,
Development: false,
Sampling: &zap.SamplingConfig{
Initial: 100,
Thereafter: 100,
},
Encoding: "json",
EncoderConfig: zapEncoderConfig,
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}
return zapConfig.Build()
}