-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
131 lines (113 loc) · 3.56 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
package main
import (
"strings"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
"github.com/valyala/fastjson"
)
const tickMilliseconds uint32 = 5000
var allowedDomains []string
func main() {
proxywasm.SetVMContext(&vmContext{})
}
type vmContext struct {
// Embed the default VM context here,
// so that we don't need to reimplement all the methods.
types.DefaultVMContext
}
// Override types.DefaultVMContext.
func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext {
return &pluginContext{contextID: contextID}
}
type pluginContext struct {
// Embed the default plugin context here,
// so that we don't need to reimplement all the methods.
types.DefaultPluginContext
contextID uint32
callBack func(numHeaders, bodySize, numTrailers int)
apiHost string
}
// Override types.DefaultPluginContext.
func (*pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
return &httpAuthRandom{contextID: contextID}
}
type httpAuthRandom struct {
// Embed the default http context here,
// so that we don't need to reimplement all the methods.
types.DefaultHttpContext
contextID uint32
}
// Override types.DefaultPluginContext.
func (ctx *pluginContext) OnPluginStart(pluginConfigurationSize int) types.OnPluginStartStatus {
configdata, err := proxywasm.GetPluginConfiguration()
if err != nil {
proxywasm.LogCriticalf("error reading plugin configuration: %v", err)
return types.OnPluginStartStatusFailed
}
s := fastjson.GetString(configdata, "api_host")
if s == "" {
proxywasm.LogCriticalf("api_host is not set")
return types.OnPluginStartStatusFailed
}
ctx.apiHost = s
if err := proxywasm.SetTickPeriodMilliSeconds(tickMilliseconds); err != nil {
proxywasm.LogCriticalf("failed to set tick period: %v", err)
return types.OnPluginStartStatusFailed
}
proxywasm.LogInfof("set tick period milliseconds: %d", tickMilliseconds)
ctx.callBack = func(numHeaders, bodySize, numTrailers int) {
respBody, err := proxywasm.GetHttpCallResponseBody(0, bodySize)
if err != nil {
proxywasm.LogErrorf("failed to get http response body: %v", err)
return
}
var p fastjson.Parser
v, err := p.Parse(string(respBody))
if err != nil {
proxywasm.LogErrorf("failed to parse response body: %v", err)
return
}
allowedDomains = []string{}
for _, domain := range v.GetArray() {
allowedDomains = append(allowedDomains, string(domain.GetStringBytes("name")))
}
proxywasm.LogDebugf("allowed domains: %v", allowedDomains)
}
return types.OnPluginStartStatusOK
}
func (ctx *httpAuthRandom) OnHttpRequestHeaders(int, bool) types.Action {
hs, err := proxywasm.GetHttpRequestHeaders()
if err != nil {
proxywasm.LogCriticalf("failed to get request headers: %v", err)
return types.ActionContinue
}
var authority string
for _, h := range hs {
if h[0] == ":authority" {
authority = h[1]
break
}
}
host := strings.Split(authority, ":")[0]
if !contains(allowedDomains, host) {
proxywasm.SendHttpResponse(403, [][2]string{{"wasm-reason", "domain not allowed"}}, nil, -1)
}
return types.ActionContinue
}
// Override types.DefaultPluginContext.
func (ctx *pluginContext) OnTick() {
hs := [][2]string{
{":method", "GET"}, {":authority", ctx.apiHost}, {":path", "/domains"}, {"accept", "*/*"},
}
if _, err := proxywasm.DispatchHttpCall("controlplane", hs, nil, nil, 5000, ctx.callBack); err != nil {
proxywasm.LogCriticalf("dispatch httpcall failed: %v", err)
}
}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}