diff --git a/config/config.go b/config/config.go index cd1b1a646..2a26fd133 100644 --- a/config/config.go +++ b/config/config.go @@ -37,7 +37,7 @@ import ( "os" "github.com/BurntSushi/toml" - logging "github.com/op/go-logging" + "github.com/op/go-logging" ) var log = logging.MustGetLogger("honeytrap:config") @@ -50,6 +50,8 @@ var format = logging.MustStringFormatter( // Config defines the central type where all configuration is umarhsalled to. type Config struct { + toml.MetaData + Listener toml.Primitive `toml:"listener"` Web toml.Primitive `toml:"web"` @@ -72,10 +74,11 @@ var Default = Config{} // Load attempts to load the giving toml configuration file. func (c *Config) Load(r io.Reader) error { - _, err := toml.DecodeReader(r, c) + md, err := toml.DecodeReader(r, c) if err != nil { return err } + c.MetaData = md logBackends := []logging.Backend{} for _, log := range c.Logging { diff --git a/server/honeytrap.go b/server/honeytrap.go index 67a36d2aa..6be784670 100644 --- a/server/honeytrap.go +++ b/server/honeytrap.go @@ -42,7 +42,6 @@ import ( "github.com/mattn/go-isatty" - "github.com/BurntSushi/toml" "github.com/fatih/color" "github.com/honeytrap/honeytrap/cmd" @@ -63,6 +62,7 @@ import ( _ "github.com/honeytrap/honeytrap/services/eos" _ "github.com/honeytrap/honeytrap/services/ethereum" _ "github.com/honeytrap/honeytrap/services/ftp" + _ "github.com/honeytrap/honeytrap/services/hadoop" _ "github.com/honeytrap/honeytrap/services/ipp" _ "github.com/honeytrap/honeytrap/services/redis" _ "github.com/honeytrap/honeytrap/services/smtp" @@ -329,6 +329,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { w.Start() channels := map[string]pushers.Channel{} + isChannelUsed := make(map[string]bool) // sane defaults! for key, s := range hc.config.Channels { @@ -336,7 +337,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Type string `toml:"type"` }{} - err := toml.PrimitiveDecode(s, &x) + err := hc.config.PrimitiveDecode(s, &x) if err != nil { log.Error("Error parsing configuration of channel: %s", err.Error()) continue @@ -355,6 +356,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { log.Fatalf("Error initializing channel %s(%s): %s", key, x.Type, err) } else { channels[key] = d + isChannelUsed[key] = false } } @@ -365,7 +367,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Categories []string `toml:"categories"` }{} - err := toml.PrimitiveDecode(s, &x) + err := hc.config.PrimitiveDecode(s, &x) if err != nil { log.Error("Error parsing configuration of filter: %s", err.Error()) continue @@ -378,6 +380,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { continue } + isChannelUsed[name] = true channel = pushers.TokenChannel(channel, hc.token) if len(x.Categories) != 0 { @@ -394,6 +397,12 @@ func (hc *Honeytrap) Run(ctx context.Context) { } } + for name, isUsed := range isChannelUsed { + if !isUsed { + log.Warningf("Channel %s is unused. Did you forget to add a filter?", name) + } + } + // initialize directors directors := map[string]director.Director{} availableDirectorNames := director.GetAvailableDirectorNames() @@ -403,7 +412,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Type string `toml:"type"` }{} - err := toml.PrimitiveDecode(s, &x) + err := hc.config.PrimitiveDecode(s, &x) if err != nil { log.Error("Error parsing configuration of director: %s", err.Error()) continue @@ -431,7 +440,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Type string `toml:"type"` }{} - if err := toml.PrimitiveDecode(hc.config.Listener, &x); err != nil { + if err := hc.config.PrimitiveDecode(hc.config.Listener, &x); err != nil { log.Error("Error parsing configuration of listener: %s", err.Error()) return } @@ -455,7 +464,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Port string `toml:"port"` }{} - if err := toml.PrimitiveDecode(s, &x); err != nil { + if err := hc.config.PrimitiveDecode(s, &x); err != nil { log.Error("Error parsing configuration of service %s: %s", key, err.Error()) continue } @@ -518,7 +527,7 @@ func (hc *Honeytrap) Run(ctx context.Context) { Services []string `toml:"services"` }{} - if err := toml.PrimitiveDecode(s, &x); err != nil { + if err := hc.config.PrimitiveDecode(s, &x); err != nil { log.Error("Error parsing configuration of generic ports: %s", err.Error()) continue } @@ -597,6 +606,10 @@ func (hc *Honeytrap) Run(ctx context.Context) { } } + if len(hc.config.Undecoded()) != 0 { + log.Warningf("Unrecognized keys in configuration: %v", hc.config.Undecoded()) + } + if err := l.Start(ctx); err != nil { fmt.Println(color.RedString("Error starting listener: %s", err.Error())) return diff --git a/services/hadoop/hadoop.go b/services/hadoop/hadoop.go new file mode 100644 index 000000000..5e58e9ed3 --- /dev/null +++ b/services/hadoop/hadoop.go @@ -0,0 +1,139 @@ +/* +* Honeytrap +* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/) +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU Affero General Public License version 3 as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +* details. +* +* You should have received a copy of the GNU Affero General Public License +* version 3 along with this program in the file "LICENSE". If not, see +* . +* +* See https://honeytrap.io/ for more details. All requests should be sent to +* licensing@honeytrap.io +* +* The interactive user interfaces in modified source and object code versions +* of this program must display Appropriate Legal Notices, as required under +* Section 5 of the GNU Affero General Public License version 3. +* +* In accordance with Section 7(b) of the GNU Affero General Public License version 3, +* these Appropriate Legal Notices must retain the display of the "Powered by +* Honeytrap" logo and retain the original copyright notice. If the display of the +* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices +* must display the words "Powered by Honeytrap" and retain the original copyright notice. + */ + +package hadoop + +import ( + "bufio" + "context" + "io" + "net" + "net/http" + "strings" + + "github.com/honeytrap/honeytrap/pushers" + "github.com/honeytrap/honeytrap/services" +) + +var ( + hadoopRequestNameNode = map[string]func(*hadoopService) string{ + "service=NameNode,name=NameNodeInfo": (*hadoopService).showNameNode, + "service=NameNode,name=FSNamesystemState": (*hadoopService).showFSNamesystemState, + } + hadoopRequestDataNode = map[string]func(*hadoopService) string{ + "service=DataNode,name=DataNodeInfo": (*hadoopService).showDataNode, + } +) + +func Hadoop(options ...services.ServicerFunc) services.Servicer { + s := &hadoopService{ + hadoopServiceConfig: hadoopServiceConfig{ + Version: "2.7.1", + Os: "Linux", + }, + } + for _, o := range options { + o(s) + } + return s +} + +type hadoopServiceConfig struct { + Version string `toml:"version"` + Os string `toml:"os"` +} + +type hadoopService struct { + hadoopServiceConfig + + ch pushers.Channel +} + +func (s *hadoopService) SetChannel(ch pushers.Channel) { + s.ch = ch +} + +func (s *hadoopService) ShowRequest(req *http.Request, hadoopRequest map[string]func(*hadoopService) string) string { + for i, _ := range req.Form { + if !strings.Contains(strings.Join(req.Form[i], ""), ":") { + return s.showEmpty() + } + request := strings.Split(strings.Join(req.Form[i], ""), ":") + switch request[0] { + case "Hadoop": + fn, ok := hadoopRequest[request[1]] + if !strings.Contains(request[1], ",") { + return s.showEmpty() + } + if !ok { + return s.showNothing() + } + return fn(s) + default: + return s.showNothing() + } + } + return "" +} + +func (s *hadoopService) Handle(ctx context.Context, conn net.Conn) error { + defer conn.Close() + br := bufio.NewReader(conn) + req, err := http.ReadRequest(br) + if err == io.EOF { + return nil + } else if err != nil { + return err + } + + err = req.ParseForm() + if err != nil { + return err + } + +<<<<<<< HEAD + port := strings.Split(conn.LocalAddr().String(), ":") + + if port[1] == "50070" { + return s.HandleNameNode(conn, req) + } else if port[1] == "50075" { +======= + port := conn.LocalAddr().(*net.TCPAddr).Port + + if port == 50070 { + return s.HandleNameNode(conn, req) + } else if port == 50075 { +>>>>>>> 3ca8ba0529510d2a72fa2251532783c3bfcfdbf6 + return s.HandleDataNode(conn, req) + } + + return nil +} diff --git a/services/hadoop/hadoop_datanode.go b/services/hadoop/hadoop_datanode.go new file mode 100644 index 000000000..96706922d --- /dev/null +++ b/services/hadoop/hadoop_datanode.go @@ -0,0 +1,126 @@ +/*/* +* Honeytrap +* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/) +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU Affero General Public License version 3 as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +* details. +* +* You should have received a copy of the GNU Affero General Public License +* version 3 along with this program in the file "LICENSE". If not, see +* . +* +* See https://honeytrap.io/ for more details. All requests should be sent to +* licensing@honeytrap.io +* +* The interactive user interfaces in modified source and object code versions +* of this program must display Appropriate Legal Notices, as required under +* Section 5 of the GNU Affero General Public License version 3. +* +* In accordance with Section 7(b) of the GNU Affero General Public License version 3, +* these Appropriate Legal Notices must retain the display of the "Powered by +* Honeytrap" logo and retain the original copyright notice. If the display of the +* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices +* must display the words "Powered by Honeytrap" and retain the original copyright notice. + */ + +package hadoop + +import ( + "fmt" + "io/ioutil" + "net" + "net/http" + "strings" + "time" + + "github.com/honeytrap/honeytrap/event" + "github.com/honeytrap/honeytrap/services" +) + +/*Example config: + +[service.hadoop_datanode] +type="hadoop_datanode" +version="2.7.1" +os="Linux" + +[[port]] +port="tcp/50075" +services=["hadoop_datanode"] + +*/ + +var ( + _ = services.Register("hadoop_datanode", Hadoop) +) + +func (s *hadoopService) HandleDataNode(conn net.Conn, req *http.Request) error { + + hadoopRequest := hadoopRequestDataNode + + s.ch.Send(event.New( + services.EventOptions, + event.Service("Hadoop DataNode"), + event.Category("hadoop_datanode"), + event.SourceAddr(conn.RemoteAddr()), + event.DestinationAddr(conn.LocalAddr()), + event.Custom("http.user-agent", req.UserAgent()), + event.Custom("http.method", req.Method), + event.Custom("http.proto", req.Proto), + event.Custom("http.host", req.Host), + event.Custom("http.url", req.URL.String()), + event.Custom("http.request", req.RequestURI), + )) + + if req.URL.Path != "/jmx" { + resp := http.Response{ + StatusCode: http.StatusNotFound, + Status: http.StatusText(http.StatusNotFound), + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Request: req, + Header: map[string][]string{ + "Cache-Control": []string{"must-revalidate,no-cache,no-store"}, + "Date": []string{time.Now().Format(http.TimeFormat)}, + "Pragma": []string{"no-cache"}, + "Content-Type": []string{"text/html; charset=iso-8859-1"}, + "Content-length": []string{fmt.Sprintf("%d", len(s.htmlErrorPage(req.URL.Path)))}, + "Server": []string{"Jetty(6.1.26)"}, + }, + } + resp.Body = ioutil.NopCloser(strings.NewReader(s.htmlErrorPage(req.URL.Path))) + return resp.Write(conn) + } + + resp := http.Response{ + StatusCode: http.StatusOK, + Status: http.StatusText(http.StatusOK), + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Request: req, + Header: map[string][]string{ + "Cache-Control": []string{"no-cache"}, + "Expires": []string{time.Now().Format(http.TimeFormat)}, + "Date": []string{time.Now().Format(http.TimeFormat)}, + "Pragma": []string{"no-cache"}, + "Content-Type": []string{"application/json; charset=utf-8"}, + "Access-Control-Allow-Methods": []string{req.Method}, + "Access-Control-Allow-Origin": []string{"*"}, + "Transfer-Encoding": []string{"chunked"}, + "Server": []string{"Jetty(6.1.26)"}, + }, + } + + resp.Body = ioutil.NopCloser(strings.NewReader(s.ShowRequest(req, hadoopRequest))) + + return resp.Write(conn) + +} diff --git a/services/hadoop/hadoop_messages.go b/services/hadoop/hadoop_messages.go new file mode 100644 index 000000000..121eda0bf --- /dev/null +++ b/services/hadoop/hadoop_messages.go @@ -0,0 +1,193 @@ +/* +* Honeytrap +* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/) +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU Affero General Public License version 3 as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +* details. +* +* You should have received a copy of the GNU Affero General Public License +* version 3 along with this program in the file "LICENSE". If not, see +* . +* +* See https://honeytrap.io/ for more details. All requests should be sent to +* licensing@honeytrap.io +* +* The interactive user interfaces in modified source and object code versions +* of this program must display Appropriate Legal Notices, as required under +* Section 5 of the GNU Affero General Public License version 3. +* +* In accordance with Section 7(b) of the GNU Affero General Public License version 3, +* these Appropriate Legal Notices must retain the display of the "Powered by +* Honeytrap" logo and retain the original copyright notice. If the display of the +* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices +* must display the words "Powered by Honeytrap" and retain the original copyright notice. + */ +package hadoop + +import ( + "fmt" + "time" +) + +func getDayLetter() string { + return fmt.Sprint(time.Now().Weekday(), time.Month(time.Now().Month()), time.Now().Day()) +} + +func getDayNumber() string { + return fmt.Sprintf("%v-%d-%v", time.Now().Year(), time.Month(time.Now().Month()), time.Now().Day()) +} + +func getTime() string { + return fmt.Sprintf("%v:%v:%v", time.Now().Hour(), time.Now().Minute(), time.Now().Second()) +} + +func (s *hadoopService) htmlErrorPage(reqPath string) string { + return fmt.Sprintln(` + + + + Error 404 NOT_FOUND + +

HTTP ERROR 404

+

Problem accessing `, reqPath, `. Reason: +

    NOT_FOUND


Powered by Jetty://
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + `) +} + +func (s *hadoopService) showEmpty() string { + return `{ }` +} + +func (s *hadoopService) showNothing() string { + return ` +{ + "beans": [] +}` +} + +func (s *hadoopService) showFSNamesystemState() string { + return fmt.Sprintln(` +{ + "beans" : [ { + "name" : "Hadoop:service=NameNode,name=FSNamesystemState", + "modelerType" : "org.apache.hadoop.hdfs.server.namenode.FSNamesystem", + "CapacityTotal" : 41083600896, + "CapacityUsed" : 327680, + "CapacityRemaining" : 14096678912, + "TotalLoad" : 1, + "SnapshotStats" : "{\"SnapshottableDirectories\":0,\"Snapshots\":0}", + "BlocksTotal" : 31, + "MaxObjects" : 0, + "FilesTotal" : 35, + "PendingReplicationBlocks" : 0, + "UnderReplicatedBlocks" : 0, + "ScheduledReplicationBlocks" : 0, + "PendingDeletionBlocks" : 0, + "BlockDeletionStartTime" : 1532001516964, + "FSState" : "Operational", + "NumLiveDataNodes" : 1, + "NumDeadDataNodes" : 0, + "NumDecomLiveDataNodes" : 0, + "NumDecomDeadDataNodes" : 0, + "VolumeFailuresTotal" : 0, + "EstimatedCapacityLostTotal" : 0, + "NumDecommissioningDataNodes" : 0, + "NumStaleDataNodes" : 0, + "NumStaleStorages" : 0, + "TopUserOpCounts" : "{\"timestamp\":\"`, getDayNumber(), `T`, getTime(), `-0400\",\"windows\":[{\"windowLenMs\":300000,\"ops\":[]},{\"windowLenMs\":1500000,\"ops\":[]},{\"windowLenMs\":60000,\"ops\":[]}]}" + } ] +}`) +} + +func (s *hadoopService) showNameNode() string { + return fmt.Sprintln(` +{ + "beans" : [ { + "name" : "Hadoop:service=NameNode,name=NameNodeInfo", + "modelerType" : "org.apache.hadoop.hdfs.server.namenode.FSNamesystem", + "UpgradeFinalized" : true, + "ClusterId" : "CID-5e691286-4de5-4dde-800b-c02a7a8bf44a", + "Version" : "`, s.Version, `, r15ecc87ccf4a0228f35af08fc56de536e6ce657a", + "Used" : 327680, + "Free" : 14100385792, + "Safemode" : "", + "NonDfsUsedSpace" : 26982887424, + "PercentUsed" : 7.975932E-4, + "BlockPoolUsedSpace" : 327680, + "PercentBlockPoolUsed" : 7.975932E-4, + "PercentRemaining" : 34.321205, + "CacheCapacity" : 0, + "CacheUsed" : 0, + "TotalBlocks" : 31, + "TotalFiles" : 35, + "NumberOfMissingBlocks" : 0, + "NumberOfMissingBlocksWithReplicationFactorOne" : 0, + "LiveNodes" : "{\"4a41865ca8bc:50010\":{\"infoAddr\":\"172.17.0.2:50075\",\"infoSecureAddr\":\"172.17.0.2:0\",\"xferaddr\":\"172.17.0.2:50010\",\"lastContact\":0,\"usedSpace\":327680,\"adminState\":\"In Service\",\"nonDfsUsedSpace\":26982887424,\"capacity\":41083600896,\"numBlocks\":31,\"version\":\"`, s.Version, `\",\"used\":327680,\"remaining\":14100385792,\"blockScheduled\":0,\"blockPoolUsed\":327680,\"blockPoolUsedPercent\":7.975932E-4,\"volfails\":0}}", + "DeadNodes" : "{}", + "DecomNodes" : "{}", + "BlockPoolId" : "BP-1961412683-172.17.0.32-1450036414523", + "NameDirStatuses" : "{\"failed\":{},\"active\":{\"/tmp/hadoop-root/dfs/name\":\"IMAGE_AND_EDITS\"}}", + "NodeUsage" : "{\"nodeUsage\":{\"min\":\"0.00%\",\"median\":\"0.00%\",\"max\":\"0.00%\",\"stdDev\":\"0.00%\"}}", + "NameJournalStatus" : "[{\"stream\":\"EditLogFileOutputStream(/tmp/hadoop-root/dfs/name/current/edits_inprogress_0000000000000000192)\",\"manager\":\"FileJournalManager(root=/tmp/hadoop-root/dfs/name)\",\"required\":\"false\",\"disabled\":\"false\"}]", + "JournalTransactionInfo" : "{\"LastAppliedOrWrittenTxId\":\"192\",\"MostRecentCheckpointTxId\":\"191\"}", + "NNStarted" : `, getDayLetter(), `"07:58:36 EDT 2018", + "CompileInfo" : "2015-06-29T06:04Z by jenkins from (detached from 15ecc87)", + "CorruptFiles" : "[]", + "DistinctVersionCount" : 1, + "DistinctVersions" : [ { + "key" : "`, s.Version, `", + "value" : 1 + } ], + "SoftwareVersion" : "`, s.Version, `", + "RollingUpgradeStatus" : null, + "Threads" : 33, + "Total" : 41083600896 + } ] +}`) +} + +func (s *hadoopService) showDataNode() string { + return fmt.Sprintln(` +{ + "beans" : [ { + "name" : "Hadoop:service=DataNode,name=DataNodeInfo", + "modelerType" : "org.apache.hadoop.hdfs.server.datanode.DataNode", + "XceiverCount" : 1, + "DatanodeNetworkCounts" : [ ], + "Version" : "`, s.Version, `", + "RpcPort" : "50020", + "HttpPort" : null, + "NamenodeAddresses" : "{\"4a41865ca8bc\":\"BP-1961412683-172.17.0.32-1450036414523\"}", + "VolumeInfo" : "{\"/tmp/hadoop-root/dfs/data/current\":{\"freeSpace\":14075846656,\"usedSpace\":327680,\"reservedSpace\":0}}", + "ClusterId" : "CID-5e691286-4de5-4dde-800b-c02a7a8bf44a" + } ] +}`) +} diff --git a/services/hadoop/hadoop_namenode.go b/services/hadoop/hadoop_namenode.go new file mode 100644 index 000000000..ed5e3e2b2 --- /dev/null +++ b/services/hadoop/hadoop_namenode.go @@ -0,0 +1,123 @@ +/* +* Honeytrap +* Copyright (C) 2016-2017 DutchSec (https://dutchsec.com/) +* +* This program is free software; you can redistribute it and/or modify it under +* the terms of the GNU Affero General Public License version 3 as published by the +* Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +* details. +* +* You should have received a copy of the GNU Affero General Public License +* version 3 along with this program in the file "LICENSE". If not, see +* . +* +* See https://honeytrap.io/ for more details. All requests should be sent to +* licensing@honeytrap.io +* +* The interactive user interfaces in modified source and object code versions +* of this program must display Appropriate Legal Notices, as required under +* Section 5 of the GNU Affero General Public License version 3. +* +* In accordance with Section 7(b) of the GNU Affero General Public License version 3, +* these Appropriate Legal Notices must retain the display of the "Powered by +* Honeytrap" logo and retain the original copyright notice. If the display of the +* logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices +* must display the words "Powered by Honeytrap" and retain the original copyright notice. + */ + +package hadoop + +import ( + "fmt" + "io/ioutil" + "net" + "net/http" + "strings" + "time" + + "github.com/honeytrap/honeytrap/event" + "github.com/honeytrap/honeytrap/services" +) + +/*Example config: + +[service.hadoop_namenode] +type="hadoop_namenode" +version="2.7.1" +os="Linux" + +[[port]] +port="tcp/50070" +services=["hadoop_namenode"] + +*/ + +var ( + _ = services.Register("hadoop_namenode", Hadoop) +) + +func (s *hadoopService) HandleNameNode(conn net.Conn, req *http.Request) error { + hadoopRequest := hadoopRequestNameNode + s.ch.Send(event.New( + services.EventOptions, + event.Service("Hadoop NameNode"), + event.Category("hadoop_namenode"), + event.SourceAddr(conn.RemoteAddr()), + event.DestinationAddr(conn.LocalAddr()), + event.Custom("http.user-agent", req.UserAgent()), + event.Custom("http.method", req.Method), + event.Custom("http.proto", req.Proto), + event.Custom("http.host", req.Host), + event.Custom("http.url", req.URL.String()), + event.Custom("http.request", req.RequestURI), + )) + + if req.URL.Path != "/jmx" { + resp := http.Response{ + StatusCode: http.StatusNotFound, + Status: http.StatusText(http.StatusNotFound), + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Request: req, + Header: map[string][]string{ + "Cache-Control": []string{"must-revalidate,no-cache,no-store"}, + "Date": []string{time.Now().Format(http.TimeFormat)}, + "Pragma": []string{"no-cache"}, + "Content-Type": []string{"text/html; charset=iso-8859-1"}, + "Content-length": []string{fmt.Sprintf("%d", len(s.htmlErrorPage(req.URL.Path)))}, + "Server": []string{"Jetty(6.1.26)"}, + }, + } + resp.Body = ioutil.NopCloser(strings.NewReader(s.htmlErrorPage(req.URL.Path))) + return resp.Write(conn) + } + + resp := http.Response{ + StatusCode: http.StatusOK, + Status: http.StatusText(http.StatusOK), + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Request: req, + Header: map[string][]string{ + "Cache-Control": []string{"no-cache"}, + "Expires": []string{time.Now().Format(http.TimeFormat)}, + "Date": []string{time.Now().Format(http.TimeFormat)}, + "Pragma": []string{"no-cache"}, + "Content-Type": []string{"application/json; charset=utf-8"}, + "Access-Control-Allow-Methods": []string{req.Method}, + "Access-Control-Allow-Origin": []string{"*"}, + "Transfer-Encoding": []string{"chunked"}, + "Server": []string{"Jetty(6.1.26)"}, + }, + } + + resp.Body = ioutil.NopCloser(strings.NewReader(s.ShowRequest(req, hadoopRequest))) + + return resp.Write(conn) +}