-
Notifications
You must be signed in to change notification settings - Fork 39
/
daemon.go
150 lines (132 loc) · 4.2 KB
/
daemon.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
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"net"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"github.com/genuinetools/bpfd/action"
"github.com/genuinetools/bpfd/api"
types "github.com/genuinetools/bpfd/api/grpc"
"github.com/genuinetools/bpfd/rules"
"github.com/genuinetools/bpfd/tracer"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
// Register the builtin tracers.
_ "github.com/genuinetools/bpfd/tracer/bashreadline"
_ "github.com/genuinetools/bpfd/tracer/dockeropenbreakout"
_ "github.com/genuinetools/bpfd/tracer/exec"
_ "github.com/genuinetools/bpfd/tracer/open"
_ "github.com/genuinetools/bpfd/tracer/tcpdrop"
// Register the builtin actions.
_ "github.com/genuinetools/bpfd/action/interrupt"
_ "github.com/genuinetools/bpfd/action/kill"
_ "github.com/genuinetools/bpfd/action/stdout"
)
const daemonHelp = `Start the daemon.`
func (cmd *daemonCommand) Name() string { return "daemon" }
func (cmd *daemonCommand) Args() string { return "[OPTIONS]" }
func (cmd *daemonCommand) ShortHelp() string { return daemonHelp }
func (cmd *daemonCommand) LongHelp() string { return daemonHelp }
func (cmd *daemonCommand) Hidden() bool { return false }
func (cmd *daemonCommand) Register(fs *flag.FlagSet) {
fs.StringVar(&cmd.rulesDirectory, "rules-dir", "/etc/bpfd/rules", "Directory that stores the rules files")
}
type daemonCommand struct {
rulesDirectory string
}
func (cmd *daemonCommand) Run(ctx context.Context, args []string) error {
// On ^C, or SIGTERM handle exit.
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
signal.Notify(c, syscall.SIGTERM)
go func() {
for sig := range c {
logrus.Infof("Received %s, exiting", sig.String())
logrus.Info("Gracefully shutting down and unloading all tracers")
tracer.UnloadAll()
os.Exit(0)
}
}()
// Get all the rules from the rule directory.
fi, err := ioutil.ReadDir(cmd.rulesDirectory)
if err != nil {
if !os.IsNotExist(err) {
return fmt.Errorf("listing files in rules directory %s failed: %v", cmd.rulesDirectory, err)
}
}
files := []string{}
for _, file := range fi {
files = append(files, filepath.Join(cmd.rulesDirectory, file.Name()))
}
rls, names, err := rules.ParseFiles(files...)
if err != nil {
return fmt.Errorf("reading rules files from directory %s failed: %v", cmd.rulesDirectory, err)
}
logrus.Infof("Loaded rules: %s", strings.Join(names, ", "))
// List all the compiled in tracers.
tracerList := tracer.List()
logrus.Infof("Daemon compiled with tracers: %s", strings.Join(tracerList, ", "))
tracers := map[string]tracer.Tracer{}
for _, p := range tracerList {
prog, err := tracer.Get(p)
if err != nil {
return err
}
tracers[p] = prog
}
logrus.Debugf("tracers: %#v", tracers)
// List all the compiled in actions.
actionList := action.List()
logrus.Infof("Daemon compiled with actions: %s", strings.Join(actionList, ", "))
actions := map[string]action.Action{}
for _, a := range actionList {
acn, err := action.Get(a)
if err != nil {
return err
}
actions[a] = acn
}
logrus.Debugf("actions: %#v", actions)
// Validate the rules against the tracers and actions.
for _, prs := range rls {
for _, r := range prs {
if err := rules.ValidateTracersAndActions(r, tracerList, actionList); err != nil {
return err
}
}
}
// Create the directory if it doesn't exist.
if err := os.MkdirAll(filepath.Dir(grpcAddress), 0755); err != nil {
return fmt.Errorf("creating directory %s failed: %v", filepath.Dir(grpcAddress), err)
}
// Remove the old socket.
if err := os.RemoveAll(grpcAddress); err != nil {
logrus.Warnf("attempt to remove old sock %s failed: %v", grpcAddress, err)
}
// Start the grpc api server.
l, err := net.Listen("unix", grpcAddress)
if err != nil {
return fmt.Errorf("starting listener at %s failed: %v", grpcAddress, err)
}
s := grpc.NewServer()
opt := api.Opts{
Rules: rls,
Tracers: tracers,
Actions: actions,
TracerList: tracerList,
ActionList: actionList,
}
svr, err := api.NewServer(ctx, opt)
if err != nil {
return fmt.Errorf("creating new api server failed: %v", err)
}
types.RegisterAPIServer(s, svr)
logrus.Infof("gRPC api server listening on: %s", grpcAddress)
return s.Serve(l)
}