diff --git a/configmanager/Dockerfile b/configmanager/Dockerfile index 7804c11..a2eb3bc 100644 --- a/configmanager/Dockerfile +++ b/configmanager/Dockerfile @@ -5,6 +5,6 @@ RUN npm install hsts COPY ./server.js /app/server.js RUN mkdir /data COPY ./cad-default.json /data/cad-default.json -COPY ./session-default.json /data/session-default.json +COPY ./config-default.json /data/config-default.json USER nobody CMD ["node", "server.js"] diff --git a/configmanager/config-default.json b/configmanager/config-default.json new file mode 100644 index 0000000..8b7eaf9 --- /dev/null +++ b/configmanager/config-default.json @@ -0,0 +1,14 @@ +{ + "alert": { + "session": { + "in": "", + "key": "" + }, + "username": { + "in": "", + "key": "", + "value": "" + } + }, + "server": "" +} \ No newline at end of file diff --git a/configmanager/server.js b/configmanager/server.js index 43b9505..ff88bd9 100644 --- a/configmanager/server.js +++ b/configmanager/server.js @@ -16,7 +16,7 @@ app.get('/:namespace/:application', (req, res) => { const { namespace, application } = req.params; const filePath = path.resolve(path.normalize(`${__dirname}/data/cad-${namespace}-${application}.json`).replace(/^(\.\.(\/|\\|$))+/, '')); const defaultFilePath = `/data/cad-default.json`; - const sessionFilePath = `/data/session-default.json`; + const configFilePath = `/data/config-default.json`; if(!filePath.startsWith(__dirname)){ return res.end() } @@ -39,15 +39,15 @@ app.get('/:namespace/:application', (req, res) => { if(!decoys) return res.json([]) const decoysJson = JSON.parse(decoys); // Check if the file exists - fs.access(sessionFilePath, fs.constants.F_OK, err => { - if(err) return res.json({ decoys: decoysJson }); + fs.access(configFilePath, fs.constants.F_OK, err => { + if(err) return res.json({ decoy: decoysJson }); // If the file exists, read its contents and return as JSON object - fs.readFile(sessionFilePath, 'utf8', (err, session) => { - if(err) return res.json({ decoys: decoysJson }); - if (session) { - const sessionJson = JSON.parse(session); - return res.json({ decoy: decoysJson, session: sessionJson }); + fs.readFile(configFilePath, 'utf8', (err, config) => { + if(err) return res.json({ decoy: decoysJson }); + if (config) { + const configJson = JSON.parse(config); + return res.json({ decoy: decoysJson, config: configJson }); } return res.json({ decoy: decoysJson }) }) @@ -65,15 +65,15 @@ app.get('/:namespace/:application', (req, res) => { if(!decoys) return res.json([]) const decoysJson = JSON.parse(decoys); // Check if the file exists - fs.access(sessionFilePath, fs.constants.F_OK, err => { + fs.access(configFilePath, fs.constants.F_OK, err => { if(err) return res.json({ decoys: decoysJson }); // If the file exists, read its contents and return as JSON object - fs.readFile(sessionFilePath, 'utf8', (err, session) => { + fs.readFile(configFilePath, 'utf8', (err, config) => { if(err) return res.json({ decoys: decoysJson }); - if (session) { - const sessionJson = JSON.parse(session); - return res.json({ decoy: decoysJson, session: sessionJson }); + if (config) { + const configJson = JSON.parse(config); + return res.json({ decoy: decoysJson, config: configJson }); } return res.json({ decoy: decoysJson }) }) diff --git a/configmanager/session-default.json b/configmanager/session-default.json deleted file mode 100644 index 832b7ac..0000000 --- a/configmanager/session-default.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "session": { - "in": "", - "key": "" - - }, - "username": { - "in": "", - "key": "", - "value": "" - } -} \ No newline at end of file diff --git a/proxy/wasm/alert/alert.go b/proxy/wasm/alert/alert.go index ee901af..1b89f4c 100644 --- a/proxy/wasm/alert/alert.go +++ b/proxy/wasm/alert/alert.go @@ -51,6 +51,9 @@ func SendAlert(filter *config_parser.FilterType, logParameters map[string]string if (err != nil) { proxywasm.LogCriticalf("failed to fetch property: %v", err) } + if string(server[:]) == "" { + server = []byte(logParameters["server"]) + } sourceIP, err := proxywasm.GetProperty([]string{"source", "address"}) if (err != nil) { proxywasm.LogCriticalf("failed to fetch property: %v", err) @@ -72,11 +75,11 @@ func SendAlert(filter *config_parser.FilterType, logParameters map[string]string Time: time.Now().Unix(), RequestID: headers["x-request-id"], DestinationIP: string(destinationIP[:]), - Url: headers[":authority"], + Url: truncate(headers[":authority"]), Server: truncate(string(server[:])), Useragent: truncate(headers["user-agent"]), SourceIP: string(sourceIP[:]), - Path: headers[":path"], + Path: truncate(headers[":path"]), Method: headers[":method"], DecoyType: logParameters["alert"], DecoyKey: decoyKey, diff --git a/proxy/wasm/cloud-active-defense.wasm b/proxy/wasm/cloud-active-defense.wasm index df6e392..19babf5 100755 Binary files a/proxy/wasm/cloud-active-defense.wasm and b/proxy/wasm/cloud-active-defense.wasm differ diff --git a/proxy/wasm/config_parser/parser.go b/proxy/wasm/config_parser/parser.go index 7ca9c54..9c3b667 100644 --- a/proxy/wasm/config_parser/parser.go +++ b/proxy/wasm/config_parser/parser.go @@ -32,7 +32,7 @@ type Parser struct { func newParser(confContent []byte) *Parser { return &Parser{ - Config: &Config{Decoys: DecoyConfig{}, Session: SessionConfig{}}, + Config: &Config{Decoys: DecoyConfig{}, Config: ConfigType{}}, ConfigFile: confContent, } } @@ -52,18 +52,21 @@ func (p *Parser) jsonToStruct(content []byte) error { if err != nil { return err } - if json.Exists("session") { - p.Config.Session = SessionConfig{ - Session: SessionType{ - Key: string(json.GetStringBytes("session", "session", "key")), - In: string(json.GetStringBytes("session", "session", "in")), - Separator: string(json.GetStringBytes("session", "session", "separator")), - }, - Username: UsernameType{ - In: string(json.GetStringBytes("session", "username", "in")), - Value: string(json.GetStringBytes("session", "username", "value")), - Key: string(json.GetStringBytes("session", "username", "key")), - }, + if json.Exists("config") { + p.Config.Config = ConfigType{ + Alert: AlertConfig{ + Session: SessionType{ + Key: string(json.GetStringBytes("config", "alert", "session", "key")), + In: string(json.GetStringBytes("config", "alert", "session", "in")), + Separator: string(json.GetStringBytes("config", "alert", "session", "separator")), + }, + Username: UsernameType{ + In: string(json.GetStringBytes("config", "alert", "username", "in")), + Value: string(json.GetStringBytes("config", "alert", "username", "value")), + Key: string(json.GetStringBytes("config", "alert", "username", "key")), + }, + }, + Server: string(json.GetStringBytes("config", "server")), } } filtersJs := json.GetArray("decoy", "filters") diff --git a/proxy/wasm/config_parser/type_emptyInstances.go b/proxy/wasm/config_parser/type_emptyInstances.go index a802248..cfa9657 100644 --- a/proxy/wasm/config_parser/type_emptyInstances.go +++ b/proxy/wasm/config_parser/type_emptyInstances.go @@ -5,7 +5,7 @@ import ( ) func EmptyConfig() Config { - return Config{ DecoyConfig{}, SessionConfig{} } + return Config{ DecoyConfig{}, ConfigType{} } } func EmptyCondition() ConditionType{ @@ -24,8 +24,12 @@ func EmptyDecoy() DecoyType { return DecoyType{"", "", "", "", "", ""} } -func EmptySessionConfig() SessionConfig { - return SessionConfig{ EmptySession(), EmptyUsername() } +func EmptyConfigType() ConfigType { + return ConfigType{ EmptyAlertConfig(), "" } +} + +func EmptyAlertConfig() AlertConfig { + return AlertConfig{ EmptySession(), EmptyUsername() } } func EmptySession() SessionType { diff --git a/proxy/wasm/config_parser/types.go b/proxy/wasm/config_parser/types.go index e184fe2..d19e096 100644 --- a/proxy/wasm/config_parser/types.go +++ b/proxy/wasm/config_parser/types.go @@ -8,9 +8,15 @@ import ( type Config struct { Decoys DecoyConfig `json:"decoys"` - Session SessionConfig `json:"session"` + Config ConfigType `json:"session"` } -type SessionConfig struct { + +type ConfigType struct { + Alert AlertConfig `json:"config"` + Server string `json:"server"` +} + +type AlertConfig struct { Session SessionType `json:"session"` Username UsernameType `json:"username"` } diff --git a/proxy/wasm/config_parser/validator.go b/proxy/wasm/config_parser/validator.go index f370dfb..16f440d 100644 --- a/proxy/wasm/config_parser/validator.go +++ b/proxy/wasm/config_parser/validator.go @@ -48,7 +48,7 @@ func (v *validator) printErrors() { func (v *validator) Validate(config *Config) error { v.validateFilters(config.Decoys.Filters) - v.validateSessionConf(config.Session) + v.validateAlertConf(config.Config.Alert) v.printErrors() if len(v.errArr) == 0 { return nil @@ -74,7 +74,7 @@ func (v *validator) validateFilters(filters []FilterType) { } } -func (v *validator) validateSessionConf(session SessionConfig) { +func (v *validator) validateAlertConf(session AlertConfig) { v.validateSession(session.Session) v.validateUsername(session.Username) } diff --git a/proxy/wasm/detect/session.go b/proxy/wasm/detect/session.go index 93187f7..4040e28 100644 --- a/proxy/wasm/detect/session.go +++ b/proxy/wasm/detect/session.go @@ -7,8 +7,8 @@ import ( "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm" ) -func FindSession(request map[string]map[string]string, response map[string]map[string]string, config config_parser.SessionConfig) (string, string) { - if (config == config_parser.EmptySessionConfig() || config == config_parser.SessionConfig{}) { +func FindSession(request map[string]map[string]string, response map[string]map[string]string, config config_parser.AlertConfig) (string, string) { + if (config == config_parser.EmptyAlertConfig() || config == config_parser.AlertConfig{}) { return "", "" } @@ -33,7 +33,7 @@ func FindSession(request map[string]map[string]string, response map[string]map[s return sessionValue, usernameValue } -func getSession(headers map[string]map[string]string, config config_parser.SessionConfig) string { +func getSession(headers map[string]map[string]string, config config_parser.AlertConfig) string { if config.Session.In == "header" { if val, exists := headers["header"][config.Session.Key]; exists { return val @@ -46,7 +46,7 @@ func getSession(headers map[string]map[string]string, config config_parser.Sessi return "" } -func getUsername(headers map[string]map[string]string, config config_parser.SessionConfig) string { +func getUsername(headers map[string]map[string]string, config config_parser.AlertConfig) string { if config.Username.In == "header" { if val, exists := headers["header"][config.Username.Key]; exists { return FindInValue(config.Username.Value, val) diff --git a/proxy/wasm/main.go b/proxy/wasm/main.go index 2aaa8d7..b54789c 100644 --- a/proxy/wasm/main.go +++ b/proxy/wasm/main.go @@ -24,7 +24,7 @@ type vmContext struct { } func (*vmContext) NewPluginContext(contextID uint32) types.PluginContext { - return &pluginContext{contextID: contextID, config: &config_parser.Config{Session: config_parser.SessionConfig{} , Decoys: config_parser.DecoyConfig{ Filters: []config_parser.FilterType{}}}} + return &pluginContext{contextID: contextID, config: &config_parser.Config{Config: config_parser.ConfigType{} , Decoys: config_parser.DecoyConfig{ Filters: []config_parser.FilterType{}}}} } type pluginContext struct { @@ -318,10 +318,11 @@ func (ctx *httpContext) OnHttpResponseBody(bodySize int, endOfStream bool) types func (ctx *httpContext) OnHttpStreamDone() { resBody := ctx.body reqBody := *ctx.request.Body - session, username := detect.FindSession(map[string]map[string]string{"header": ctx.request.Headers, "cookie": ctx.request.Cookies, "payload": { "payload": reqBody }}, map[string]map[string]string{ "header": ctx.headers, "cookie": ctx.cookies, "payload": { "payload": resBody }}, ctx.config.Session) + session, username := detect.FindSession(map[string]map[string]string{"header": ctx.request.Headers, "cookie": ctx.request.Cookies, "payload": { "payload": reqBody }}, map[string]map[string]string{ "header": ctx.headers, "cookie": ctx.cookies, "payload": { "payload": resBody }}, ctx.config.Config.Alert) for i := 0; i < len(ctx.alerts); i++ { ctx.alerts[i].LogParameters["session"] = session ctx.alerts[i].LogParameters["username"] = username + ctx.alerts[i].LogParameters["server"] = ctx.config.Config.Server alert.SendAlert(&ctx.alerts[i].Filter, ctx.alerts[i].LogParameters, ctx.request.Headers) } }