예제 #1
0
파일: wineventlog.go 프로젝트: jarpy/beats
// newWinEventLog creates and returns a new EventLog for reading event logs
// using the Windows Event Log.
func newWinEventLog(c Config) (EventLog, error) {
	eventMetadataHandle := func(providerName, sourceName string) eventlogging.MessageFiles {
		mf := eventlogging.MessageFiles{SourceName: sourceName}
		h, err := sys.OpenPublisherMetadata(0, sourceName, 0)
		if err != nil {
			mf.Err = err
			return mf
		}

		mf.Handles = []eventlogging.FileHandle{eventlogging.FileHandle{Handle: uintptr(h)}}
		return mf
	}

	freeHandle := func(handle uintptr) error {
		return sys.Close(sys.EvtHandle(handle))
	}

	ctx, err := sys.CreateRenderContext(nil, sys.EvtRenderContextSystem)
	if err != nil {
		return nil, err
	}

	return &winEventLog{
		channelName:   c.Name,
		remoteServer:  c.RemoteAddress,
		maxRead:       defaultMaxNumRead,
		renderBuf:     make([]byte, renderBufferSize),
		systemCtx:     ctx,
		cache:         newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle),
		logPrefix:     fmt.Sprintf("WinEventLog[%s]", c.Name),
		eventMetadata: c.EventMetadata,
	}, nil
}
예제 #2
0
파일: wineventlog.go 프로젝트: jarpy/beats
func (l *winEventLog) Open(recordNumber uint64) error {
	bookmark, err := sys.CreateBookmark(l.channelName, recordNumber)
	if err != nil {
		return err
	}
	defer sys.Close(bookmark)

	// Using a pull subscription to receive events. See:
	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa385771(v=vs.85).aspx#pull
	signalEvent, err := windows.CreateEvent(nil, 0, 0, nil)
	if err != nil {
		return nil
	}

	subscriptionHandle, err := sys.Subscribe(
		0, // null session (used for connecting to remote event logs)
		signalEvent,
		l.channelName,
		"",       // Query - nil means all events
		bookmark, // Bookmark - for resuming from a specific event
		sys.EvtSubscribeStartAfterBookmark)
	if err != nil {
		return err
	}

	l.subscription = subscriptionHandle
	return nil
}
예제 #3
0
func (l *winEventLog) Open(recordNumber uint64) error {
	bookmark, err := win.CreateBookmark(l.channelName, recordNumber)
	if err != nil {
		return err
	}
	defer win.Close(bookmark)

	// Using a pull subscription to receive events. See:
	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa385771(v=vs.85).aspx#pull
	signalEvent, err := windows.CreateEvent(nil, 0, 0, nil)
	if err != nil {
		return nil
	}

	debugf("%s using subscription query=%s", l.logPrefix, l.query)
	subscriptionHandle, err := win.Subscribe(
		0, // Session - nil for localhost
		signalEvent,
		"",       // Channel - empty b/c channel is in the query
		l.query,  // Query - nil means all events
		bookmark, // Bookmark - for resuming from a specific event
		win.EvtSubscribeStartAfterBookmark)
	if err != nil {
		return err
	}

	l.subscription = subscriptionHandle
	return nil
}
예제 #4
0
파일: wineventlog.go 프로젝트: jarpy/beats
func (l *winEventLog) Read() ([]Record, error) {
	handles, err := sys.EventHandles(l.subscription, l.maxRead)
	if err == sys.ERROR_NO_MORE_ITEMS {
		detailf("%s No more events", l.logPrefix)
		return nil, nil
	}
	if err != nil {
		logp.Warn("%s EventHandles returned error %v Errno: %d", l.logPrefix, err)
		return nil, err
	}
	defer func() {
		for _, h := range handles {
			sys.Close(h)
		}
	}()
	detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles))

	var records []Record
	for _, h := range handles {
		e, err := sys.RenderEvent(h, l.systemCtx, 0, l.renderBuf, l.cache.get)
		if err != nil {
			logp.Err("%s Dropping event with rendering error. %v", l.logPrefix, err)
			continue
		}

		r := Record{
			API:           winEventLogAPIName,
			EventLogName:  e.Channel,
			SourceName:    e.ProviderName,
			ComputerName:  e.Computer,
			RecordNumber:  e.RecordID,
			EventID:       uint32(e.EventID),
			Level:         e.Level,
			Category:      e.Task,
			Message:       e.Message,
			MessageErr:    e.MessageErr,
			EventMetadata: l.eventMetadata,
		}

		if e.TimeCreated != nil {
			r.TimeGenerated = *e.TimeCreated
		}

		if e.UserSID != nil {
			r.User = &User{
				Identifier: e.UserSID.Identifier,
				Name:       e.UserSID.Name,
				Domain:     e.UserSID.Domain,
				Type:       e.UserSID.Type.String(),
			}
		}

		records = append(records, r)
	}

	debugf("%s Read() is returning %d records", l.logPrefix, len(records))
	return records, nil
}
예제 #5
0
func (l *winEventLog) Read() ([]Record, error) {
	handles, err := win.EventHandles(l.subscription, l.maxRead)
	if err == win.ERROR_NO_MORE_ITEMS {
		detailf("%s No more events", l.logPrefix)
		return nil, nil
	}
	if err != nil {
		logp.Warn("%s EventHandles returned error %v", l.logPrefix, err)
		return nil, err
	}
	defer func() {
		for _, h := range handles {
			win.Close(h)
		}
	}()
	detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles))

	var records []Record
	for _, h := range handles {
		x, err := l.render(h)
		if bufErr, ok := err.(sys.InsufficientBufferError); ok {
			detailf("%s Increasing render buffer size to %d", l.logPrefix,
				bufErr.RequiredSize)
			l.renderBuf = make([]byte, bufErr.RequiredSize)
			x, err = l.render(h)
		}
		if err != nil && x == "" {
			logp.Err("%s Dropping event with rendering error. %v", l.logPrefix, err)
			reportDrop(err)
			continue
		}

		r, err := l.buildRecordFromXML(x, err)
		if err != nil {
			logp.Err("%s Dropping event. %v", l.logPrefix, err)
			reportDrop("unmarshal")
			continue
		}
		records = append(records, r)
	}

	debugf("%s Read() is returning %d records", l.logPrefix, len(records))
	return records, nil
}
예제 #6
0
// newWinEventLog creates and returns a new EventLog for reading event logs
// using the Windows Event Log.
func newWinEventLog(options map[string]interface{}) (EventLog, error) {
	var c winEventLogConfig
	if err := readConfig(options, &c, winEventLogConfigKeys); err != nil {
		return nil, err
	}

	query, err := win.Query{
		Log:         c.Name,
		IgnoreOlder: c.SimpleQuery.IgnoreOlder,
		Level:       c.SimpleQuery.Level,
		EventID:     c.SimpleQuery.EventID,
		Provider:    c.SimpleQuery.Provider,
	}.Build()
	if err != nil {
		return nil, err
	}

	eventMetadataHandle := func(providerName, sourceName string) sys.MessageFiles {
		mf := sys.MessageFiles{SourceName: sourceName}
		h, err := win.OpenPublisherMetadata(0, sourceName, 0)
		if err != nil {
			mf.Err = err
			return mf
		}

		mf.Handles = []sys.FileHandle{sys.FileHandle{Handle: uintptr(h)}}
		return mf
	}

	freeHandle := func(handle uintptr) error {
		return win.Close(win.EvtHandle(handle))
	}

	return &winEventLog{
		config:        c,
		query:         query,
		channelName:   c.Name,
		maxRead:       defaultMaxNumRead,
		renderBuf:     make([]byte, renderBufferSize),
		cache:         newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle),
		logPrefix:     fmt.Sprintf("WinEventLog[%s]", c.Name),
		eventMetadata: c.EventMetadata,
	}, nil
}
예제 #7
0
파일: wineventlog.go 프로젝트: urso/beats
func (l *winEventLog) Read() ([]Record, error) {
	handles, _, err := l.eventHandles(l.maxRead)
	if err != nil || len(handles) == 0 {
		return nil, err
	}
	defer func() {
		for _, h := range handles {
			win.Close(h)
		}
	}()
	detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles))

	var records []Record
	for _, h := range handles {
		l.outputBuf.Reset()
		err := l.render(h, l.outputBuf)
		if bufErr, ok := err.(sys.InsufficientBufferError); ok {
			detailf("%s Increasing render buffer size to %d", l.logPrefix,
				bufErr.RequiredSize)
			l.renderBuf = make([]byte, bufErr.RequiredSize)
			l.outputBuf.Reset()
			err = l.render(h, l.outputBuf)
		}
		if err != nil && l.outputBuf.Len() == 0 {
			logp.Err("%s Dropping event with rendering error. %v", l.logPrefix, err)
			incrementMetric(dropReasons, err)
			continue
		}

		r, err := l.buildRecordFromXML(l.outputBuf.Bytes(), err)
		if err != nil {
			logp.Err("%s Dropping event. %v", l.logPrefix, err)
			incrementMetric(dropReasons, err)
			continue
		}
		records = append(records, r)
		l.lastRead = r.RecordID
	}

	debugf("%s Read() is returning %d records", l.logPrefix, len(records))
	return records, nil
}
예제 #8
0
파일: wineventlog.go 프로젝트: jarpy/beats
func (l *winEventLog) Close() error {
	debugf("%s Closing handle", l.logPrefix)
	return sys.Close(l.subscription)
}
예제 #9
0
// newWinEventLog creates and returns a new EventLog for reading event logs
// using the Windows Event Log.
func newWinEventLog(options map[string]interface{}) (EventLog, error) {
	c := defaultWinEventLogConfig
	if err := readConfig(options, &c, winEventLogConfigKeys); err != nil {
		return nil, err
	}

	query, err := win.Query{
		Log:         c.Name,
		IgnoreOlder: c.SimpleQuery.IgnoreOlder,
		Level:       c.SimpleQuery.Level,
		EventID:     c.SimpleQuery.EventID,
		Provider:    c.SimpleQuery.Provider,
	}.Build()
	if err != nil {
		return nil, err
	}

	eventMetadataHandle := func(providerName, sourceName string) sys.MessageFiles {
		mf := sys.MessageFiles{SourceName: sourceName}
		h, err := win.OpenPublisherMetadata(0, sourceName, 0)
		if err != nil {
			mf.Err = err
			return mf
		}

		mf.Handles = []sys.FileHandle{{Handle: uintptr(h)}}
		return mf
	}

	freeHandle := func(handle uintptr) error {
		return win.Close(win.EvtHandle(handle))
	}

	l := &winEventLog{
		config:        c,
		query:         query,
		channelName:   c.Name,
		maxRead:       c.BatchReadSize,
		renderBuf:     make([]byte, renderBufferSize),
		cache:         newMessageFilesCache(c.Name, eventMetadataHandle, freeHandle),
		logPrefix:     fmt.Sprintf("WinEventLog[%s]", c.Name),
		eventMetadata: c.EventMetadata,
	}

	// Forwarded events should be rendered using RenderEventXML. It is more
	// efficient and does not attempt to use local message files for rendering
	// the event's message.
	switch {
	case c.Forwarded == nil && c.Name == "ForwardedEvents",
		c.Forwarded != nil && *c.Forwarded == true:
		l.render = func(event win.EvtHandle) (string, error) {
			return win.RenderEventXML(event, l.renderBuf)
		}
	default:
		l.render = func(event win.EvtHandle) (string, error) {
			return win.RenderEvent(event, 0, l.renderBuf, l.cache.get)
		}
	}

	return l, nil
}
예제 #10
0
func (l *eventLog) Close() error {
	return sys.Close(l.subscription)
}