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

Continuation of #8561 - add windows.service.start_name and windows.service.path_name #11877

Merged
merged 9 commits into from
Apr 26, 2019
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Add SSL support for Metricbeat HTTP server. {pull}11482[11482] {issue}11457[11457]
- The `elasticsearch.index` metricset (with `xpack.enabled: true`) now collects `refresh.external_total_time_in_millis` fields from Elasticsearch. {pull}11616[11616]
- Allow module configurations to have variants {pull}9118[9118]
- Added `path_name` and `start_name` to service metricset on windows module {issue}8364[8364]
- Added new disk states and raid level to the system/raid metricset. {pull}11613[11613]

*Packetbeat*
Expand Down
24 changes: 24 additions & 0 deletions metricbeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -26717,6 +26717,30 @@ type: keyword
The startup type of the service. The possible values are `Automatic`, `Boot`, `Disabled`, `Manual`, and `System`.


--

*`windows.service.start_name`*::
+
--
type: keyword

example: NT AUTHORITY\LocalService

Account name under which a service runs.


--

*`windows.service.path_name`*::
+
--
type: keyword

example: C:\WINDOWS\system32\svchost.exe -k LocalService -p

Fully qualified path to the file that implements the service, including arguments.


--

*`windows.service.state`*::
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/module/windows/fields.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions metricbeat/module/windows/service/_meta/fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@
The startup type of the service. The possible values are `Automatic`,
`Boot`, `Disabled`, `Manual`, and `System`.

- name: start_name
type: keyword
example: NT AUTHORITY\LocalService
description: >
Account name under which a service runs.

- name: path_name
type: keyword
example: C:\WINDOWS\system32\svchost.exe -k LocalService -p
description: >
Fully qualified path to the file that implements the service,
including arguments.

- name: state
type: keyword
description: >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type Win32Service struct {
ProcessId uint32
DisplayName string
State string
StartName string
PathName string
}

func TestData(t *testing.T) {
Expand All @@ -58,7 +60,8 @@ func TestReadService(t *testing.T) {

var wmiSrc []Win32Service

// Get services from WMI.
// Get services from WMI, set NonePtrZero so nil fields are turned to empty strings
wmi.DefaultClient.NonePtrZero = true
err = wmi.Query("SELECT * FROM Win32_Service ", &wmiSrc)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -87,6 +90,15 @@ func TestReadService(t *testing.T) {
assert.Equal(t, w.DisplayName, s["display_name"],
"Display name of service %v does not match", w.Name)
}
// some services come back without PathName or StartName from WMI, just skip them
if s["path_name"] != nil && w.PathName != "" {
assert.Equal(t, w.PathName, s["path_name"],
"Path name of service %v does not match", w.Name)
}
if s["start_name"] != nil && w.StartName != "" {
assert.Equal(t, w.StartName, s["start_name"],
"Start name of service %v does not match", w.Name)
}
// Some services have changed state before the second retrieval.
if w.State != s["state"] {
changed := s
Expand Down
33 changes: 26 additions & 7 deletions metricbeat/module/windows/service/service_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,15 @@ var errorNames = map[uint32]string{
}

type ServiceStatus struct {
DisplayName string
ServiceName string
CurrentState string
StartType ServiceStartType
PID uint32 // ID of the associated process.
Uptime time.Duration
ExitCode uint32 // Exit code for stopped services.
DisplayName string
ServiceName string
CurrentState string
StartType ServiceStartType
PID uint32 // ID of the associated process.
Uptime time.Duration
ExitCode uint32 // Exit code for stopped services.
ServiceStartName string
BinaryPathName string
}

type ServiceReader struct {
Expand Down Expand Up @@ -373,6 +375,21 @@ func getAdditionalServiceInfo(serviceHandle ServiceHandle, service *ServiceStatu
}
serviceQueryConfig := (*QueryServiceConfig)(unsafe.Pointer(&buffer[0]))
service.StartType = ServiceStartType(serviceQueryConfig.DwStartType)
serviceStartNameOffset := uintptr(unsafe.Pointer(serviceQueryConfig.LpServiceStartName)) - (uintptr)(unsafe.Pointer(&buffer[0]))
binaryPathNameOffset := uintptr(unsafe.Pointer(serviceQueryConfig.LpBinaryPathName)) - (uintptr)(unsafe.Pointer(&buffer[0]))

strBuf := new(bytes.Buffer)
if err := sys.UTF16ToUTF8Bytes(buffer[serviceStartNameOffset:], strBuf); err != nil {
return err
}
service.ServiceStartName = strBuf.String()

strBuf.Reset()
if err := sys.UTF16ToUTF8Bytes(buffer[binaryPathNameOffset:], strBuf); err != nil {
return err
}
service.BinaryPathName = strBuf.String()

break
}

Expand Down Expand Up @@ -476,6 +493,8 @@ func (reader *ServiceReader) Read() ([]common.MapStr, error) {
"name": service.ServiceName,
"state": service.CurrentState,
"start_type": service.StartType.String(),
"start_name": service.ServiceStartName,
"path_name": service.BinaryPathName,
}

if service.CurrentState == "Stopped" {
Expand Down