go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/services/ps1getservice.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package services
     5  
     6  import (
     7  	"encoding/json"
     8  	"io"
     9  
    10  	"go.mondoo.com/cnquery/providers/os/connection/shared"
    11  	"go.mondoo.com/cnquery/providers/os/resources/powershell"
    12  )
    13  
    14  // WindowsService calls powershell Get-Service
    15  //
    16  // Get-Service | Select-Object -Property *
    17  // Name                : defragsvc
    18  // RequiredServices    : {RPCSS}
    19  // CanPauseAndContinue : False
    20  // CanShutdown         : False
    21  // CanStop             : False
    22  // DisplayName         : Optimize drives
    23  // DependentServices   : {}
    24  // MachineName         : .
    25  // ServiceName         : defragsvc
    26  // ServicesDependedOn  : {RPCSS}
    27  // ServiceHandle       : SafeServiceHandle
    28  // Status              : Stopped
    29  // ServiceType         : Win32OwnProcess
    30  // StartType           : Manual
    31  // Site                :
    32  // Container           :
    33  type WindowsService struct {
    34  	Status      int
    35  	Name        string
    36  	DisplayName string
    37  	StartType   int
    38  }
    39  
    40  // State returns the State value for a Windows service
    41  //
    42  // int values of the services have the following values:
    43  // 1: Stopped
    44  // 2: Starting
    45  // 3: Stopping
    46  // 4: Running
    47  // 5: Continue Pending
    48  // 6: Pause Pending
    49  // 7: Paused
    50  //
    51  // those are documented in https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
    52  func (s WindowsService) State() State {
    53  	res := ServiceUnknown
    54  	switch s.Status {
    55  	case 1:
    56  		res = ServiceStopped
    57  	case 2:
    58  		res = ServiceStartPending
    59  	case 3:
    60  		res = ServiceStopped
    61  	case 4:
    62  		res = ServiceRunning
    63  	case 5:
    64  		res = ServiceContinuePending
    65  	case 6:
    66  		res = ServicePausePending
    67  	case 7:
    68  		res = ServicePaused
    69  	}
    70  	return res
    71  }
    72  
    73  func (s WindowsService) IsRunning() bool {
    74  	return s.State() == ServiceRunning
    75  }
    76  
    77  // Modes are documented in https://docs.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicestartmode?view=netframework-4.8
    78  // NOTE: only newer powershell versions support this approach, we may need WMI fallback later
    79  // see: https://mikefrobbins.com/2015/12/17/starttype-property-added-to-get-service-in-powershell-version-5-build-10586-on-windows-10-version-1511/
    80  // 0: Boot
    81  // 1: System
    82  // 2: Automatic
    83  // 3: Manual
    84  // 4: Disabled
    85  func (s WindowsService) Enabled() bool {
    86  	if s.StartType <= 3 {
    87  		return true
    88  	}
    89  	return false
    90  }
    91  
    92  func (s WindowsService) Service() *Service {
    93  	return &Service{
    94  		Name:        s.Name,
    95  		Description: s.DisplayName,
    96  		Installed:   true,
    97  		Running:     s.IsRunning(),
    98  		Enabled:     s.Enabled(),
    99  		State:       s.State(),
   100  		Type:        "windows",
   101  	}
   102  }
   103  
   104  func ParseWindowsService(r io.Reader) ([]*Service, error) {
   105  	data, err := io.ReadAll(r)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  
   110  	var srvs []WindowsService
   111  	err = json.Unmarshal(data, &srvs)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	res := make([]*Service, len(srvs))
   117  	for i := range srvs {
   118  		res[i] = srvs[i].Service()
   119  	}
   120  
   121  	return res, nil
   122  }
   123  
   124  type WindowsServiceManager struct {
   125  	conn shared.Connection
   126  }
   127  
   128  func (s *WindowsServiceManager) Name() string {
   129  	return "Windows Service Manager"
   130  }
   131  
   132  func (s *WindowsServiceManager) List() ([]*Service, error) {
   133  	c, err := s.conn.RunCommand(powershell.Wrap("Get-Service | Select-Object -Property Status, Name, DisplayName, StartType | ConvertTo-Json"))
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	return ParseWindowsService(c.Stdout)
   138  }