-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwhitelisting.go
116 lines (101 loc) · 2.35 KB
/
whitelisting.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
package doorman
import (
"encoding/json"
"fmt"
"net"
"go.uber.org/zap"
)
var (
_ whitelistLoader = (*staticWhiteList)(nil)
valueWhiteListListLoader = "list"
)
type IPMap map[string]bool
type Networks []*net.IPNet
type Whitelist struct {
ips IPMap
nets Networks
}
type whitelistLoader interface {
Fetch(log *zap.Logger) (*Whitelist, error)
}
type staticWhiteList []string
func parseStaticList(sw []string) (IPMap, Networks, error) {
statics := make(IPMap)
nets := make(Networks, 0)
for _, we := range sw {
iip, ipnet, err := net.ParseCIDR(we)
if err != nil {
ip := net.ParseIP(we)
if ip == nil {
return nil, nil, fmt.Errorf("cannot parse %q as ip", we)
}
statics[we] = true
} else {
// if we have an ipv4 with a 32bit mask, this is a singular ip
if ones, bits := ipnet.Mask.Size(); ones == 32 && bits == 32 {
statics[iip.String()] = true
continue
}
nets = append(nets, ipnet)
}
}
return statics, nets, nil
}
func (sw *staticWhiteList) Fetch(log *zap.Logger) (*Whitelist, error) {
ips, nets, err := parseStaticList(*sw)
if err != nil {
return nil, err
}
return &Whitelist{
ips: ips,
nets: nets,
}, nil
}
func (w *Whitelist) IsAllowed(log *zap.Logger, clip string) bool {
if ok := w.ips[clip]; ok {
return true
}
ip := net.ParseIP(clip)
if ip == nil {
return false
}
for _, n := range w.nets {
if n.Contains(ip) {
log.Debug("ip is whitelisted", zap.String("net", n.String()), zap.String("ip", clip))
return true
}
}
return false
}
type whitelister struct {
loader []whitelistLoader
whitelists []*Whitelist
}
func (wl *whitelister) isAllowed(log *zap.Logger, clientip string) bool {
for _, w := range wl.whitelists {
if w.IsAllowed(log, clientip) {
return true
}
}
return false
}
func fromWhitelistSpecs(log *zap.Logger, bks Plugins) (*whitelister, error) {
res := whitelister{}
for _, b := range bks {
switch b.Type {
case valueWhiteListListLoader:
var w staticWhiteList
if err := json.Unmarshal(b.Spec, &w); err != nil {
return nil, fmt.Errorf("cannot unmarshal static whitelister: %w", err)
}
res.loader = append(res.loader, &w)
ldr, err := w.Fetch(log)
if err != nil {
log.Error("cannot fetch loader data", zap.String("backend", b.Name), zap.Error(err))
} else {
res.whitelists = append(res.whitelists, ldr)
}
}
}
return &res, nil
}