youtubebeat/vendor/github.com/elastic/beats/winlogbeat/sys/event.go

204 lines
6.2 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package sys
import (
"encoding/xml"
"fmt"
"time"
)
// UnmarshalEventXML unmarshals the given XML into a new Event.
func UnmarshalEventXML(rawXML []byte) (Event, error) {
var event Event
err := xml.Unmarshal(rawXML, &event)
return event, err
}
// Event holds the data from a log record.
type Event struct {
// System
Provider Provider `xml:"System>Provider"`
EventIdentifier EventIdentifier `xml:"System>EventID"`
Version uint8 `xml:"System>Version"`
LevelRaw uint8 `xml:"System>Level"`
TaskRaw uint16 `xml:"System>Task"`
OpcodeRaw uint8 `xml:"System>Opcode"`
TimeCreated TimeCreated `xml:"System>TimeCreated"`
RecordID uint64 `xml:"System>EventRecordID"`
Correlation Correlation `xml:"System>Correlation"`
Execution Execution `xml:"System>Execution"`
Channel string `xml:"System>Channel"`
Computer string `xml:"System>Computer"`
User SID `xml:"System>Security"`
EventData EventData `xml:"EventData"`
UserData UserData `xml:"UserData"`
// RenderingInfo
Message string `xml:"RenderingInfo>Message"`
Level string `xml:"RenderingInfo>Level"`
Task string `xml:"RenderingInfo>Task"`
Opcode string `xml:"RenderingInfo>Opcode"`
Keywords []string `xml:"RenderingInfo>Keywords>Keyword"`
// ProcessingErrorData
RenderErrorCode uint32 `xml:"ProcessingErrorData>ErrorCode"`
RenderErrorDataItemName string `xml:"ProcessingErrorData>DataItemName"`
RenderErr string
}
// Provider identifies the provider that logged the event. The Name and GUID
// attributes are included if the provider used an instrumentation manifest to
// define its events; otherwise, the EventSourceName attribute is included if a
// legacy event provider (using the Event Logging API) logged the event.
type Provider struct {
Name string `xml:"Name,attr"`
GUID string `xml:"Guid,attr"`
EventSourceName string `xml:"EventSourceName,attr"`
}
// Correlation contains activity identifiers that consumers can use to group
// related events together.
type Correlation struct {
ActivityID string `xml:"ActivityID,attr"`
RelatedActivityID string `xml:"RelatedActivityID,attr"`
}
// Execution contains information about the process and thread that logged the
// event.
type Execution struct {
ProcessID uint32 `xml:"ProcessID,attr"`
ThreadID uint32 `xml:"ThreadID,attr"`
// Only available for events logged to an event tracing log file (.etl file).
ProcessorID uint32 `xml:"ProcessorID,attr"`
SessionID uint32 `xml:"SessionID,attr"`
KernelTime uint32 `xml:"KernelTime,attr"`
UserTime uint32 `xml:"UserTime,attr"`
ProcessorTime uint32 `xml:"ProcessorTime,attr"`
}
// EventIdentifier is the identifer that the provider uses to identify a
// specific event type.
type EventIdentifier struct {
Qualifiers uint16 `xml:"Qualifiers,attr"`
ID uint32 `xml:",chardata"`
}
// TimeCreated contains the system time of when the event was logged.
type TimeCreated struct {
SystemTime time.Time
}
// UnmarshalXML unmarshals an XML dataTime string.
func (t *TimeCreated) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
attrs := struct {
SystemTime string `xml:"SystemTime,attr"`
RawTime uint64 `xml:"RawTime,attr"`
}{}
err := d.DecodeElement(&attrs, &start)
if err != nil {
return err
}
if attrs.SystemTime != "" {
// This works but XML dateTime is really ISO8601.
t.SystemTime, err = time.Parse(time.RFC3339Nano, attrs.SystemTime)
} else if attrs.RawTime != 0 {
// The units for RawTime are not specified in the documentation. I think
// it is only used in event tracing so this shouldn't be a problem.
err = fmt.Errorf("failed to unmarshal TimeCreated RawTime='%d'", attrs.RawTime)
}
return err
}
// EventData contains the event data. The EventData section is used if the
// message provider template does not contain a UserData section.
type EventData struct {
Pairs []KeyValue `xml:",any"`
}
// UserData contains the event data.
type UserData struct {
Name xml.Name
Pairs []KeyValue
}
// UnmarshalXML unmarshals UserData XML.
func (u *UserData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// Assume that UserData has the same general key-value structure as
// EventData does.
in := struct {
Pairs []KeyValue `xml:",any"`
}{}
// Read tokens until we find the first StartElement then unmarshal it.
for {
t, err := d.Token()
if err != nil {
return err
}
if se, ok := t.(xml.StartElement); ok {
err = d.DecodeElement(&in, &se)
if err != nil {
return err
}
u.Name = se.Name
u.Pairs = in.Pairs
d.Skip()
break
}
}
return nil
}
// KeyValue is a key value pair of strings.
type KeyValue struct {
Key string
Value string
}
// UnmarshalXML unmarshals an arbitrary XML element into a KeyValue. The key
// becomes the name of the element or value of the Name attribute if it exists.
// The value is the character data contained within the element.
func (kv *KeyValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
elem := struct {
XMLName xml.Name
Name string `xml:"Name,attr"`
Value string `xml:",chardata"`
}{}
err := d.DecodeElement(&elem, &start)
if err != nil {
return err
}
kv.Key = elem.XMLName.Local
if elem.Name != "" {
kv.Key = elem.Name
}
kv.Value = elem.Value
return nil
}