Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auditbeat file module improvements #4636

Merged
merged 3 commits into from
Jul 13, 2017

Conversation

andrewkroh
Copy link
Member

@andrewkroh andrewkroh commented Jul 10, 2017

Unify the behavior across operating systems.

  • Add tests.
  • Resolve UID/GID/SID into owner/group.
  • Log warning if a file watch cannot be added. Previously it would fail at startup.
  • Remove usage of fsevents on macOS and use kqueues instead. The data provided was inconsistent with the fsnotify. It was valuable data but the signal needs some refinement to make it consistent. The biggest issue is that multiple events are coalesced into one. Another issue is that the watches are recursive (this is great, but it's inconsistent) and we will need to allow a glob to be specified then match the incoming events against the glob (future enhancement).
  • Document hash fields
  • Initialize watches on Start() rather than at construction time.
  • Update data.json to include file owner and group names.
  • Add file type and symlink target path to the events.
  • Filter fsnotify events with empty paths (saw this once on Windows).

And add a simple dashboard:

image

Unify the behavior across operating systems.

- Add tests.
- Resolve UID/GID/SID into owner/group.
- Log warning if a file watch cannot be added. Previously it would fail at startup.
- Remove usage of fsevents on macOS and use kqueues instead. The data provided was inconsistent with the fsnotify. It was valuable data but the signal needs some refinement to make it consistent. The biggest issue is that multiple events are coalesced into one. Another issue is that the watches are recursive (this is great, but it's inconsistent) and we will need to allow a glob to be specified then match the incoming events against the glob (future enhancement).
- Document hash fields
- Initialize watches on Start() rather than at construction time.
- Update data.json to include file owner and group names.
- Add file type and symlink target path to the events.
- Filter fsnotify events with empty paths (saw this once on Windows).
@andrewkroh andrewkroh force-pushed the feature/ab/audit-file-tests branch from 9c6d0d2 to bb7e1dc Compare July 10, 2017 18:14
Copy link
Contributor

@ruflin ruflin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Most comments are not directly related to this PR and things that popped up in my head when reading it.

} else {
m["uid"] = info.UID
m["gid"] = info.GID
m["mode"] = fmt.Sprintf("%#o", uint32(info.Mode))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use # here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will "add leading 0 for octal (%#o)". https://golang.org/pkg/fmt/

I was wanting something like 0644, but maybe a different format string would be more appropriate because what I really want is a minimum of 4 octal digits.

}

for _, p := range paths {
if err := r.watcher.Add(p); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every time I see this I'm thinking if we should add a new prospector type in filebeat based on inotify which only works with "most" OS. Could make to code a lot simpler.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this fsnotify package seems to work pretty well. The only downside is that you can't do recursive monitoring. Recursive monitoring is supported by Windows but this isn't exposed by fsnotify (the other OSes don't support it).


func convertToFileEvent(e fsnotify.Event, maxFileSize int64) Event {
event := Event{
Timestamp: time.Now().UTC(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should introduce a helper in common to get time.Now() that always includes UTC. I think there are several places where it's missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That reminds me, I think I will open a PR to automatically convert all time.Time objects to UTC during event normalization. Then we won't need a helper because it won't matter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #4658.

if err != nil {
return errors.Wrap(err, "failed to stat file")
return nil, errors.Wrap(err, "failed to stat path")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to include the "failed" path in the error

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stat/Lstat return a *os.PathError that includes the path already so it would be redundant.

}

stat, ok := info.Sys().(*syscall.Stat_t)
if !ok {
return errors.Errorf("unexpected fileinfo sys type %T", info.Sys())
return nil, errors.Errorf("unexpected fileinfo sys type %T", info.Sys())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps also include the path?

GID: stat.Gid,
Mode: info.Mode(),
Size: info.Size(),
ATime: time.Unix(0, stat.Atimespec.Nano()).UTC(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it was in before, but I would assume Micro should be enough.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I follow... the time.Unix() function accepts nanoseconds which is why I'm using Nano().

if err != nil {
return errors.Wrap(err, "failed to stat file")
return nil, errors.Wrap(err, "failed to stat path")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments above for logging, also line 22.

}

return nil
switch {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like at least some of the code could be shared between linux and bsd (did not do the detailed comparison, devil is probably in the detail.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really could be, and I was debating this. The only difference between the BSD and Linux variants is that the stat_t structs use different member names for the time values. I could create a fileinfo_posix.go that's common to BSD + Linux. Then have a fileinfo_linux.go and fileinfo_bsd.go that provide a helper method for reading the time values from the stat_t objects. I'll try it out, but I'm kind of thinking that the complexity out weighs the value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to reduce duplication.

return
}

info1, err := os.Stat(f1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you use LStat here? if one of the params is a symlink to the file, do you expect this check to return true or false?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will fix.

- Change mode format to %#04o to always get a leading 0 and a minimum of 4 digits.
- Change Stat of Lstat in assertSameFile
- Reduce code duplication between linux and bsd platforms.
@andrewkroh
Copy link
Member Author

@ruflin I addressed the review feedback.

@ruflin ruflin merged commit 211d252 into elastic:master Jul 13, 2017
@andrewkroh andrewkroh deleted the feature/ab/audit-file-tests branch April 20, 2018 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants