From 31ec463f73e157ed7950907e8724195264f419be Mon Sep 17 00:00:00 2001 From: Rebecca Mahany-Horton Date: Thu, 12 Sep 2024 14:52:21 -0400 Subject: [PATCH] Proof-of-concept for Windows Hello desktop triggers Windows Hello Fix timeout, small refactor Tidy up names, add documentation Retrieve key credential status Retrieve pubkey Get attestation windows arm64 fixes, upgrade winio and thrift (#1858) Fix `autoupdate_managed` table value for MacOS 15 (#1862) james/remove wmi unneeded releases (#1863) Check windows service manager settings prior to setting them (#1859) Co-authored-by: Michael <60191460+lurky@users.noreply.github.com> Co-authored-by: seph Co-authored-by: Rebecca Mahany-Horton Update function signature Move to ee --- cmd/launcher/desktop.go | 3 + cmd/launcher/svc_config_windows.go | 38 +- ee/presencedetection/hello_other.go | 13 + ee/presencedetection/hello_windows.go | 430 ++++++++++++++++++ .../macos_software_update/SUSharedPrefs.h | 2 +- .../software_update_table.go | 4 +- ee/tables/macos_software_update/sus.h | 1 + ee/tables/macos_software_update/sus.m | 8 +- ee/wmi/wmi.go | 13 +- go.mod | 38 +- go.sum | 62 +-- 11 files changed, 557 insertions(+), 55 deletions(-) create mode 100644 ee/presencedetection/hello_other.go create mode 100644 ee/presencedetection/hello_windows.go diff --git a/cmd/launcher/desktop.go b/cmd/launcher/desktop.go index a397fadb00..ceddacc187 100644 --- a/cmd/launcher/desktop.go +++ b/cmd/launcher/desktop.go @@ -19,6 +19,7 @@ import ( "github.com/kolide/launcher/ee/desktop/user/notify" userserver "github.com/kolide/launcher/ee/desktop/user/server" "github.com/kolide/launcher/ee/desktop/user/universallink" + "github.com/kolide/launcher/ee/presencedetection" "github.com/kolide/launcher/pkg/authedclient" "github.com/kolide/launcher/pkg/log/multislogger" "github.com/kolide/launcher/pkg/rungroup" @@ -182,6 +183,8 @@ func runDesktop(_ *multislogger.MultiSlogger, args []string) error { } }() + go presencedetection.WindowsHello(context.TODO(), slogger.With("component", "windows_hello")) + // blocks until shutdown called m.Init() diff --git a/cmd/launcher/svc_config_windows.go b/cmd/launcher/svc_config_windows.go index cbc009c1fb..24d6e8d0ca 100644 --- a/cmd/launcher/svc_config_windows.go +++ b/cmd/launcher/svc_config_windows.go @@ -94,7 +94,7 @@ func checkServiceConfiguration(logger *slog.Logger, opts *launcher.Options) { checkRestartActions(logger, launcherService) - setRecoveryActions(context.TODO(), logger, launcherService) + checkRecoveryActions(context.TODO(), logger, launcherService) } // checkDelayedAutostart checks the current value of `DelayedAutostart` (whether to wait ~2 minutes @@ -192,9 +192,20 @@ func checkRestartActions(logger *slog.Logger, service *mgr.Service) { logger.Log(context.TODO(), slog.LevelInfo, "successfully set RecoveryActionsOnNonCrashFailures flag") } -// setRecoveryActions sets the recovery actions for the launcher service. +// checkRecoveryActions checks if the recovery actions for the launcher service are set. +// sets if one or more of the recovery actions are not set. // previously defined via wix ServicConfig Element (Util Extension) https://wixtoolset.org/docs/v3/xsd/util/serviceconfig/ -func setRecoveryActions(ctx context.Context, logger *slog.Logger, service *mgr.Service) { +func checkRecoveryActions(ctx context.Context, logger *slog.Logger, service *mgr.Service) { + curRecoveryActions, err := service.RecoveryActions() + if err != nil { + logger.Log(context.TODO(), slog.LevelError, + "querying for current RecoveryActions", + "err", err, + ) + + return + } + recoveryActions := []mgr.RecoveryAction{ { // first failure @@ -213,6 +224,11 @@ func setRecoveryActions(ctx context.Context, logger *slog.Logger, service *mgr.S }, } + // If the recovery actions are already set, we don't need to do anything + if recoveryActionsAreSet(curRecoveryActions, recoveryActions) { + return + } + if err := service.SetRecoveryActions(recoveryActions, 24*60*60); err != nil { // 24 hours logger.Log(ctx, slog.LevelError, "setting RecoveryActions", @@ -220,3 +236,19 @@ func setRecoveryActions(ctx context.Context, logger *slog.Logger, service *mgr.S ) } } + +// recoveryActionsAreSet checks if the current recovery actions are set to the desired recovery actions +func recoveryActionsAreSet(curRecoveryActions, recoveryActions []mgr.RecoveryAction) bool { + if curRecoveryActions == nil || len(curRecoveryActions) != len(recoveryActions) { + return false + } + for i := range curRecoveryActions { + if curRecoveryActions[i].Type != recoveryActions[i].Type { + return false + } + if curRecoveryActions[i].Delay != recoveryActions[i].Delay { + return false + } + } + return true +} diff --git a/ee/presencedetection/hello_other.go b/ee/presencedetection/hello_other.go new file mode 100644 index 0000000000..1846bf8d5a --- /dev/null +++ b/ee/presencedetection/hello_other.go @@ -0,0 +1,13 @@ +//go:build !windows +// +build !windows + +package presencedetection + +import ( + "context" + "log/slog" +) + +func WindowsHello(_ context.Context, _ *slog.Logger) { + return +} diff --git a/ee/presencedetection/hello_windows.go b/ee/presencedetection/hello_windows.go new file mode 100644 index 0000000000..68abdf75f2 --- /dev/null +++ b/ee/presencedetection/hello_windows.go @@ -0,0 +1,430 @@ +//go:build windows +// +build windows + +package presencedetection + +import ( + "context" + "errors" + "fmt" + "log/slog" + "syscall" + "time" + "unsafe" + + ole "github.com/go-ole/go-ole" + "github.com/kolide/kit/ulid" + "github.com/saltosystems/winrt-go" + "github.com/saltosystems/winrt-go/windows/foundation" + "github.com/saltosystems/winrt-go/windows/storage/streams" +) + +// GUIDs retrieved from: +// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/winrt/windows.security.credentials.idl +var ( + keyCredentialManagerGuid = ole.NewGUID("6AAC468B-0EF1-4CE0-8290-4106DA6A63B5") + keyCredentialRetrievalResultGuid = ole.NewGUID("58CD7703-8D87-4249-9B58-F6598CC9644E") + keyCredentialGuid = ole.NewGUID("9585EF8D-457B-4847-B11A-FA960BBDB138") + keyCredentialAttestationResultGuid = ole.NewGUID("78AAB3A1-A3C1-4103-B6CC-472C44171CBB") +) + +// Signatures were generated following the guidance in +// https://learn.microsoft.com/en-us/uwp/winrt-cref/winrt-type-system#guid-generation-for-parameterized-types. +// The GUIDs themselves came from the same source as above (windows.security.credentials.idl). +// The GUIDs must be lowercase in the parameterized types. +const ( + keyCredentialRetrievalResultSignature = "rc(Windows.Security.Credentials.KeyCredentialRetrievalResult;{58cd7703-8d87-4249-9b58-f6598cc9644e})" + keyCredentialAttestationResultSignature = "rc(Windows.Security.Credentials.KeyCredentialAttestationResult;{78aab3a1-a3c1-4103-b6cc-472c44171cbb})" + booleanSignature = "b1" +) + +// KeyCredentialManager is defined here: +// https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager?view=winrt-26100 +type KeyCredentialManager struct { + ole.IInspectable +} + +func (v *KeyCredentialManager) VTable() *KeyCredentialManagerVTable { + return (*KeyCredentialManagerVTable)(unsafe.Pointer(v.RawVTable)) +} + +type KeyCredentialManagerVTable struct { + ole.IInspectableVtbl + IsSupportedAsync uintptr + RenewAttestationAsync uintptr + RequestCreateAsync uintptr + OpenAsync uintptr + DeleteAsync uintptr +} + +// KeyCredentialRetrievalResult is defined here: +// https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialretrievalresult?view=winrt-26100 +type KeyCredentialRetrievalResult struct { + ole.IInspectable +} + +func (v *KeyCredentialRetrievalResult) VTable() *KeyCredentialRetrievalResultVTable { + return (*KeyCredentialRetrievalResultVTable)(unsafe.Pointer(v.RawVTable)) +} + +type KeyCredentialRetrievalResultVTable struct { + ole.IInspectableVtbl + GetCredential uintptr + GetStatus uintptr +} + +// KeyCredential is defined here: +// https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredential?view=winrt-26100 +type KeyCredential struct { + ole.IInspectable +} + +func (v *KeyCredential) VTable() *KeyCredentialVTable { + return (*KeyCredentialVTable)(unsafe.Pointer(v.RawVTable)) +} + +type KeyCredentialVTable struct { + ole.IInspectableVtbl + GetName uintptr + RetrievePublicKeyWithDefaultBlobType uintptr + RetrievePublicKeyWithBlobType uintptr + RequestSignAsync uintptr + GetAttestationAsync uintptr +} + +type KeyCredentialAttestationResult struct { + ole.IInspectable +} + +func (v *KeyCredentialAttestationResult) VTable() *KeyCredentialAttestationResultVTable { + return (*KeyCredentialAttestationResultVTable)(unsafe.Pointer(v.RawVTable)) +} + +type KeyCredentialAttestationResultVTable struct { + ole.IInspectableVtbl + GetCertificateChainBuffer uintptr + GetAttestationBuffer uintptr + GetStatus uintptr +} + +// windowsHello is a proof-of-concept that exercises prompting the user via Hello. +// TODO RM: +// * the syscalls panic easily; we will probably need to wrap this in a recovery routine +// * for readability, we should refactor individual calls into functions hanging off the appropriate structs above +func WindowsHello(ctx context.Context, slogger *slog.Logger) { + if err := ole.RoInitialize(1); err != nil { + slogger.Log(ctx, slog.LevelError, "could not initialize", "err", err) + return + } + + // Get access to the KeyCredentialManager + factory, err := ole.RoGetActivationFactory("Windows.Security.Credentials.KeyCredentialManager", ole.IID_IInspectable) + if err != nil { + slogger.Log(ctx, slog.LevelError, "could not get activation factory for KeyCredentialManager", "err", err) + return + } + defer factory.Release() + managerObj, err := factory.QueryInterface(keyCredentialManagerGuid) + if err != nil { + slogger.Log(ctx, slog.LevelError, "could not get KeyCredentialManager from factory", "err", err) + return + } + defer managerObj.Release() + keyCredentialManager := (*KeyCredentialManager)(unsafe.Pointer(managerObj)) + + // Check to see if Hello is an option + isHelloSupported, err := isSupported(keyCredentialManager) + if err != nil { + slogger.Log(ctx, slog.LevelError, "could not determine whether Hello is supported", "err", err) + return + } + if !isHelloSupported { + slogger.Log(ctx, slog.LevelError, "Hello is not supported") + return + } + + // Create a credential that will be tied to the current user and this application + credentialName := ulid.New() + pubkeyBytes, keyCredentialObj, err := requestCreate(keyCredentialManager, credentialName) + defer func() { + if keyCredentialObj != nil { + keyCredentialObj.Release() + } + }() + if err != nil { + slogger.Log(ctx, slog.LevelError, "could not create credential", "err", err) + return + } + slogger.Log(ctx, slog.LevelInfo, "created credential for user", "credential_name", credentialName, "pubkey_len", len(pubkeyBytes)) + + credential := (*KeyCredential)(unsafe.Pointer(keyCredentialObj)) + attestationBytes, err := getAttestationAsync(credential) + if err != nil { + slogger.Log(ctx, slog.LevelError, "could not get attestation from credential", "err", err) + return + } + + slogger.Log(ctx, slog.LevelInfo, "got attestation", "attestation_len", len(attestationBytes)) +} + +// isSupported calls Windows.Security.Credentials.KeyCredentialManager.IsSupportedAsync. +// It determines whether the current device and user is capable of provisioning a key credential. +// See: https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager.issupportedasync?view=winrt-26100 +func isSupported(keyCredentialManager *KeyCredentialManager) (bool, error) { + var isSupportedAsyncOperation *foundation.IAsyncOperation + ret, _, _ := syscall.SyscallN( + keyCredentialManager.VTable().IsSupportedAsync, + 0, // Because this is a static function, we don't pass in a reference to `this` + uintptr(unsafe.Pointer(&isSupportedAsyncOperation)), // Windows.Foundation.IAsyncOperation + ) + if ret != 0 { + return false, fmt.Errorf("calling IsSupportedAsync: %w", ole.NewError(ret)) + } + + // IsSupportedAsync returns Windows.Foundation.IAsyncOperation + iid := winrt.ParameterizedInstanceGUID(foundation.GUIDAsyncOperationCompletedHandler, booleanSignature) + statusChan := make(chan foundation.AsyncStatus) + handler := foundation.NewAsyncOperationCompletedHandler(ole.NewGUID(iid), func(instance *foundation.AsyncOperationCompletedHandler, asyncInfo *foundation.IAsyncOperation, asyncStatus foundation.AsyncStatus) { + statusChan <- asyncStatus + }) + defer handler.Release() + isSupportedAsyncOperation.SetCompleted(handler) + + select { + case operationStatus := <-statusChan: + if operationStatus != foundation.AsyncStatusCompleted { + return false, fmt.Errorf("IsSupportedAsync operation did not complete: status %d", operationStatus) + } + case <-time.After(5 * time.Second): + return false, errors.New("timed out waiting for IsSupportedAsync operation to complete") + } + + res, err := isSupportedAsyncOperation.GetResults() + if err != nil { + return false, fmt.Errorf("getting results of IsSupportedAsync: %w", err) + } + + return uintptr(res) > 0, nil +} + +// requestCreate calls Windows.Security.Credentials.KeyCredentialManager.RequestCreateAsync. +// It creates a new key credential for the current user and application. +// See: https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager.requestcreateasync?view=winrt-26100 +func requestCreate(keyCredentialManager *KeyCredentialManager, credentialName string) ([]byte, *ole.IDispatch, error) { + credentialNameHString, err := ole.NewHString(credentialName) + if err != nil { + return nil, nil, fmt.Errorf("creating credential name hstring: %w", err) + } + defer ole.DeleteHString(credentialNameHString) + + var requestCreateAsyncOperation *foundation.IAsyncOperation + requestCreateReturn, _, _ := syscall.SyscallN( + keyCredentialManager.VTable().RequestCreateAsync, + 0, // Because this is a static function, we don't pass in a reference to `this` + uintptr(unsafe.Pointer(&credentialNameHString)), // The name of the key credential to create + 0, // KeyCredentialCreationOption -- 0 indicates to replace any existing key credentials, 1 indicates to fail if a key credential already exists + uintptr(unsafe.Pointer(&requestCreateAsyncOperation)), // Windows.Foundation.IAsyncOperation + ) + if requestCreateReturn != 0 { + return nil, nil, fmt.Errorf("calling RequestCreateAsync: %w", ole.NewError(requestCreateReturn)) + } + + // RequestCreateAsync returns Windows.Foundation.IAsyncOperation + iid := winrt.ParameterizedInstanceGUID(foundation.GUIDAsyncOperationCompletedHandler, keyCredentialRetrievalResultSignature) + statusChan := make(chan foundation.AsyncStatus) + handler := foundation.NewAsyncOperationCompletedHandler(ole.NewGUID(iid), func(instance *foundation.AsyncOperationCompletedHandler, asyncInfo *foundation.IAsyncOperation, asyncStatus foundation.AsyncStatus) { + statusChan <- asyncStatus + }) + defer handler.Release() + requestCreateAsyncOperation.SetCompleted(handler) + + select { + case operationStatus := <-statusChan: + if operationStatus != foundation.AsyncStatusCompleted { + return nil, nil, fmt.Errorf("RequestCreateAsync operation did not complete: status %d", operationStatus) + } + case <-time.After(1 * time.Minute): + return nil, nil, errors.New("timed out waiting for RequestCreateAsync operation to complete") + } + + // Retrieve the results from the async operation + resPtr, err := requestCreateAsyncOperation.GetResults() + if err != nil { + return nil, nil, fmt.Errorf("getting results of RequestCreateAsync: %w", err) + } + + if uintptr(resPtr) == 0x0 { + return nil, nil, errors.New("no response to RequestCreateAsync") + } + + resultObj, err := (*ole.IUnknown)(resPtr).QueryInterface(keyCredentialRetrievalResultGuid) + if err != nil { + return nil, nil, fmt.Errorf("could not get KeyCredentialRetrievalResult from result of RequestCreateAsync: %w", err) + } + defer resultObj.Release() + result := (*KeyCredentialRetrievalResult)(unsafe.Pointer(resultObj)) + + // Now, retrieve the KeyCredential from the KeyCredentialRetrievalResult + var credentialPointer unsafe.Pointer + getCredentialReturn, _, _ := syscall.SyscallN( + result.VTable().GetCredential, + uintptr(unsafe.Pointer(result)), // Since we're retrieving an object property, we need a reference to `this` + uintptr(unsafe.Pointer(&credentialPointer)), + ) + if getCredentialReturn != 0 { + return nil, nil, fmt.Errorf("calling GetCredential on KeyCredentialRetrievalResult: %w", ole.NewError(getCredentialReturn)) + } + + keyCredentialObj, err := (*ole.IUnknown)(credentialPointer).QueryInterface(keyCredentialGuid) + if err != nil { + return nil, nil, fmt.Errorf("could not get KeyCredential from KeyCredentialRetrievalResult: %w", err) + } + defer keyCredentialObj.Release() + credential := (*KeyCredential)(unsafe.Pointer(keyCredentialObj)) + + // All right, things are going swimmingly. Let's retrieve the public key. + var pubkeyBufferPointer unsafe.Pointer + retrievePubKeyReturn, _, _ := syscall.SyscallN( + credential.VTable().RetrievePublicKeyWithDefaultBlobType, + uintptr(unsafe.Pointer(credential)), // Not a static method, so we need a reference to `this` + uintptr(unsafe.Pointer(&pubkeyBufferPointer)), + ) + if retrievePubKeyReturn != 0 { + return nil, nil, fmt.Errorf("calling RetrievePublicKey on KeyCredential: %w", ole.NewError(retrievePubKeyReturn)) + } + + pubkeyBufferObj, err := (*ole.IUnknown)(pubkeyBufferPointer).QueryInterface(ole.NewGUID(streams.GUIDIBuffer)) + if err != nil { + return nil, nil, fmt.Errorf("could not get buffer from result of RetrievePublicKey: %w", err) + } + defer pubkeyBufferObj.Release() + pubkeyBuffer := (*streams.IBuffer)(unsafe.Pointer(pubkeyBufferObj)) + + pubkeyBufferLen, err := pubkeyBuffer.GetLength() + if err != nil { + return nil, nil, fmt.Errorf("could not get length of pubkey buffer: %w", err) + } + pubkeyReader, err := streams.DataReaderFromBuffer(pubkeyBuffer) + if err != nil { + return nil, nil, fmt.Errorf("could not create data reader for pubkey buffer: %w", err) + } + pubkeyBytes, err := pubkeyReader.ReadBytes(pubkeyBufferLen) + if err != nil { + return nil, nil, fmt.Errorf("reading from pubkey buffer: %w", err) + } + + return pubkeyBytes, keyCredentialObj, nil + +} + +// getAttestationAsync calls Windows.Security.Credentials.KeyCredential.GetAttestationAsync. +// It gets an attestation for a key credential. +// See: https://learn.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredential.getattestationasync?view=winrt-26100 +func getAttestationAsync(credential *KeyCredential) ([]byte, error) { + // Now it's time to get the attestation. This is another async operation. + var getAttestationAsyncOperation *foundation.IAsyncOperation + getAttestationReturn, _, _ := syscall.SyscallN( + credential.VTable().GetAttestationAsync, + uintptr(unsafe.Pointer(credential)), // Not a static method, so we need a reference to `this` + uintptr(unsafe.Pointer(&getAttestationAsyncOperation)), // Windows.Foundation.IAsyncOperation + ) + if getAttestationReturn != 0 { + return nil, fmt.Errorf("calling GetAttestationAsync: %w", ole.NewError(getAttestationReturn)) + } + + // GetAttestationAsync returns Windows.Foundation.IAsyncOperation + attestionResultIid := winrt.ParameterizedInstanceGUID(foundation.GUIDAsyncOperationCompletedHandler, keyCredentialAttestationResultSignature) + attestationStatusChan := make(chan foundation.AsyncStatus) + attestationHandler := foundation.NewAsyncOperationCompletedHandler(ole.NewGUID(attestionResultIid), func(instance *foundation.AsyncOperationCompletedHandler, asyncInfo *foundation.IAsyncOperation, asyncStatus foundation.AsyncStatus) { + attestationStatusChan <- asyncStatus + }) + defer attestationHandler.Release() + getAttestationAsyncOperation.SetCompleted(attestationHandler) + + select { + case operationStatus := <-attestationStatusChan: + if operationStatus != foundation.AsyncStatusCompleted { + return nil, fmt.Errorf("GetAttestationAsync operation did not complete: status %d", operationStatus) + } + case <-time.After(1 * time.Minute): + return nil, errors.New("timed out waiting for GetAttestationAsync operation to complete") + } + + // Retrieve the results from the async attestation operation + attestationResPtr, err := getAttestationAsyncOperation.GetResults() + if err != nil { + return nil, fmt.Errorf("getting results of GetAttestationAsync: %w", err) + } + + if uintptr(attestationResPtr) == 0x0 { + return nil, errors.New("no response to GetAttestationAsync") + } + + attestationResultObj, err := (*ole.IUnknown)(attestationResPtr).QueryInterface(keyCredentialAttestationResultGuid) + if err != nil { + return nil, fmt.Errorf("could not get KeyCredentialAttestationResult from result of GetAttestationAsync: %w", err) + } + defer attestationResultObj.Release() + attestationResult := (*KeyCredentialAttestationResult)(unsafe.Pointer(attestationResultObj)) + + // From here, we can retrieve both the attestation (via GetAttestationBuffer) and the certificate chain (via GetCertificateChainBuffer). + // Both of these operations should look identical to our IBuffer usage above, so I'm just going to grab the attestation here + // for now and fill in the certificate chain if we happen to need it later. + var attestationBufferPointer unsafe.Pointer + getAttestationBufferReturn, _, _ := syscall.SyscallN( + attestationResult.VTable().GetAttestationBuffer, + uintptr(unsafe.Pointer(attestationResult)), // Not a static method, so we need a reference to `this` + uintptr(unsafe.Pointer(&attestationBufferPointer)), + ) + if getAttestationBufferReturn != 0 { + return nil, fmt.Errorf("calling GetAttestationBuffer on KeyCredentialAttestationResult: %w", ole.NewError(getAttestationBufferReturn)) + } + + attestationBufferObj, err := (*ole.IUnknown)(attestationBufferPointer).QueryInterface(ole.NewGUID(streams.GUIDIBuffer)) + if err != nil { + return nil, fmt.Errorf("could not get buffer from result of GetAttestationBuffer: %w", err) + } + defer attestationBufferObj.Release() + attestationBuffer := (*streams.IBuffer)(unsafe.Pointer(attestationBufferObj)) + + attestationBufferLen, err := attestationBuffer.GetLength() + if err != nil { + return nil, fmt.Errorf("could not get length of attestation buffer: %w", err) + } + attestationReader, err := streams.DataReaderFromBuffer(attestationBuffer) + if err != nil { + return nil, fmt.Errorf("could not create data reader for attestation buffer: %w", err) + } + attestationBytes, err := attestationReader.ReadBytes(attestationBufferLen) + if err != nil { + return nil, fmt.Errorf("reading from attestation buffer: %w", err) + } + + return attestationBytes, nil +} + +// waitForAsyncOperation should allow us to abstract away the details of waiting for an async operation, +// but right now it only works for IsSupportedAsync; it results in an error 3 being returned from RequestCreateAsync. +// TODO RM -- fix. +func waitForAsyncOperation(signature string, timeout time.Duration, asyncOperation *foundation.IAsyncOperation) (unsafe.Pointer, error) { + statusChan := make(chan foundation.AsyncStatus) + + iid := winrt.ParameterizedInstanceGUID(foundation.GUIDAsyncOperationCompletedHandler, signature) + handler := foundation.NewAsyncOperationCompletedHandler(ole.NewGUID(iid), func(instance *foundation.AsyncOperationCompletedHandler, asyncInfo *foundation.IAsyncOperation, asyncStatus foundation.AsyncStatus) { + statusChan <- asyncStatus + }) + defer handler.Release() + + asyncOperation.SetCompleted(handler) + + select { + case operationStatus := <-statusChan: + if operationStatus != foundation.AsyncStatusCompleted { + return nil, fmt.Errorf("async operation did not complete: status %d", operationStatus) + } + case <-time.After(timeout): + return nil, errors.New("timed out waiting for operation to complete") + } + + return asyncOperation.GetResults() +} diff --git a/ee/tables/macos_software_update/SUSharedPrefs.h b/ee/tables/macos_software_update/SUSharedPrefs.h index 373ea024ef..f7646fd7ac 100644 --- a/ee/tables/macos_software_update/SUSharedPrefs.h +++ b/ee/tables/macos_software_update/SUSharedPrefs.h @@ -62,6 +62,7 @@ - (BOOL)bridgeOSUpdatesEnabled; - (BOOL)skipAPFSSnapshotting; - (BOOL)doesAllowBGStageWithoutInactivity; +- (BOOL)isMacOSAutoUpdateManaged; - (BOOL)isAutomaticallyCheckForUpdatesManaged; - (BOOL)isAutomaticallyCheckForUpdatesEnabled; - (BOOL)adminDeferredInstallEnabled; @@ -108,4 +109,3 @@ - (void)reloadPreferences; @end - diff --git a/ee/tables/macos_software_update/software_update_table.go b/ee/tables/macos_software_update/software_update_table.go index e39bff50e1..5b3a7901ad 100644 --- a/ee/tables/macos_software_update/software_update_table.go +++ b/ee/tables/macos_software_update/software_update_table.go @@ -49,6 +49,7 @@ func (table *osUpdateTable) generateMacUpdate(ctx context.Context, queryContext } var ( version = C.int(table.macOSBuildVersionPrefix) + isMacOSAutoUpdateManaged = C.int(0) isAutomaticallyCheckForUpdatesManaged = C.int(0) isAutomaticallyCheckForUpdatesEnabled = C.int(0) doesBackgroundDownload = C.int(0) @@ -59,6 +60,7 @@ func (table *osUpdateTable) generateMacUpdate(ctx context.Context, queryContext ) C.getSoftwareUpdateConfiguration( version, + &isMacOSAutoUpdateManaged, &isAutomaticallyCheckForUpdatesManaged, &isAutomaticallyCheckForUpdatesEnabled, &doesBackgroundDownload, @@ -70,7 +72,7 @@ func (table *osUpdateTable) generateMacUpdate(ctx context.Context, queryContext resp := []map[string]string{ { - "autoupdate_managed": fmt.Sprintf("%d", isAutomaticallyCheckForUpdatesManaged), + "autoupdate_managed": fmt.Sprintf("%d", max(isMacOSAutoUpdateManaged, isAutomaticallyCheckForUpdatesManaged)), "autoupdate_enabled": fmt.Sprintf("%d", isAutomaticallyCheckForUpdatesEnabled), "download": fmt.Sprintf("%d", doesBackgroundDownload), "app_updates": fmt.Sprintf("%d", doesAppStoreAutoUpdates), diff --git a/ee/tables/macos_software_update/sus.h b/ee/tables/macos_software_update/sus.h index d4c115e602..68cdfa0253 100644 --- a/ee/tables/macos_software_update/sus.h +++ b/ee/tables/macos_software_update/sus.h @@ -7,6 +7,7 @@ extern void productNestedKeyValueFound(unsigned int, char*, char*, char*); // Gets software update config flags from SUSharedPrefs API void getSoftwareUpdateConfiguration(int os_version, + int* isMacOSAutoUpdateManaged, int* isAutomaticallyCheckForUpdatesManaged, int* isAutomaticallyCheckForUpdatesEnabled, int* doesBackgroundDownload, diff --git a/ee/tables/macos_software_update/sus.m b/ee/tables/macos_software_update/sus.m index 80bf248f88..f7e0502881 100644 --- a/ee/tables/macos_software_update/sus.m +++ b/ee/tables/macos_software_update/sus.m @@ -6,6 +6,7 @@ #import void getSoftwareUpdateConfiguration(int os_version, + int* isMacOSAutoUpdateManaged, int* isAutomaticallyCheckForUpdatesManaged, int* isAutomaticallyCheckForUpdatesEnabled, int* doesBackgroundDownload, @@ -22,7 +23,12 @@ void getSoftwareUpdateConfiguration(int os_version, Class SUSharedPrefs = [bundle classNamed:@"SUSharedPrefs"]; id manager = [SUSharedPrefs sharedPrefManager]; - BOOL val = [manager isAutomaticallyCheckForUpdatesManaged]; + BOOL val = [manager isMacOSAutoUpdateManaged]; + if (val) { + *isMacOSAutoUpdateManaged = 1; + } + + val = [manager isAutomaticallyCheckForUpdatesManaged]; if (val) { *isAutomaticallyCheckForUpdatesManaged = 1; } diff --git a/ee/wmi/wmi.go b/ee/wmi/wmi.go index b46a5edb80..8caae577ae 100644 --- a/ee/wmi/wmi.go +++ b/ee/wmi/wmi.go @@ -153,8 +153,17 @@ func Query(ctx context.Context, slogger *slog.Logger, className string, properti } defer serviceRaw.Clear() + // In testing, we find we do not need to `service.Release()`. The memory of result is released + // by `defer serviceRaw.Clear()` above, furthermore on windows arm64 machines, calling + // `service.Clear()` after `serviceRaw.Release()` causes a panic. + // + // Looking at the `serviceRaw.ToIDispatch()` implementation, it's just a cast that returns + // a pointer to the same memory. Which would explain why calling `serviceRaw.Release()` after + // `service.Clear()` causes a panic. It's unclear why this causes a panic on arm64 machines and + // not on amd64 machines. + // + // This also applies to the `resultRaw` and `results` variables below. service := serviceRaw.ToIDispatch() - defer service.Release() slogger.Log(ctx, slog.LevelDebug, "running WMI query", @@ -168,8 +177,8 @@ func Query(ctx context.Context, slogger *slog.Logger, className string, properti } defer resultRaw.Clear() + // see above comment about `service.Release()` to explain why `result.Release()` isn't called result := resultRaw.ToIDispatch() - defer result.Release() if err := oleutil.ForEach(result, handler.HandleVariant); err != nil { return nil, fmt.Errorf("ole foreach: %w", err) diff --git a/go.mod b/go.mod index 487b7d14d6..c272ed5950 100644 --- a/go.mod +++ b/go.mod @@ -2,15 +2,15 @@ module github.com/kolide/launcher require ( github.com/Masterminds/semver v1.4.2 - github.com/Microsoft/go-winio v0.6.1 + github.com/Microsoft/go-winio v0.6.2 github.com/clbanning/mxj v1.8.4 github.com/go-ini/ini v1.61.0 github.com/go-kit/kit v0.9.0 - github.com/go-ole/go-ole v1.2.6 + github.com/go-ole/go-ole v1.3.0 github.com/godbus/dbus/v5 v5.1.0 github.com/golang/protobuf v1.5.3 github.com/google/fscrypt v0.3.3 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.4.2 github.com/groob/plist v0.0.0-20190114192801-a99fbe489d03 github.com/knightsc/system_policy v1.1.1-0.20211029142728-5f4c0d5419cc @@ -20,12 +20,12 @@ require ( github.com/mattn/go-sqlite3 v1.14.19 github.com/mixer/clock v0.0.0-20170901150240-b08e6b4da7ea github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 - github.com/osquery/osquery-go v0.0.0-20231006172600-d6f325f636a9 - github.com/peterbourgon/ff/v3 v3.0.0 + github.com/osquery/osquery-go v0.0.0-20231130195733-61ac79279aaa + github.com/peterbourgon/ff/v3 v3.1.2 github.com/pkg/errors v0.9.1 github.com/scjalliance/comshim v0.0.0-20190308082608-cf06d2532c4e github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/theupdateframework/go-tuf v0.5.2 github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect @@ -36,7 +36,7 @@ require ( golang.org/x/image v0.18.0 golang.org/x/net v0.25.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.20.0 + golang.org/x/sys v0.25.0 golang.org/x/text v0.16.0 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 google.golang.org/grpc v1.58.3 @@ -46,12 +46,14 @@ require ( ) require ( - github.com/apache/thrift v0.16.0 + github.com/apache/thrift v0.20.0 github.com/golang-jwt/jwt/v5 v5.0.0 github.com/golang-migrate/migrate/v4 v4.16.2 + github.com/golang/snappy v0.0.4 github.com/kolide/goleveldb v0.0.0-20240514204455-8d30cd4d31c6 github.com/kolide/systray v0.0.0-20240530130728-8265cd4e35db github.com/kolide/toast v1.0.2 + github.com/saltosystems/winrt-go v0.0.0-20240510082706-db61b37f5877 github.com/shirou/gopsutil/v3 v3.23.3 github.com/spf13/pflag v1.0.5 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 @@ -63,7 +65,6 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect - github.com/golang/snappy v0.0.4 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -92,13 +93,12 @@ require ( github.com/BurntSushi/toml v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logfmt/logfmt v0.4.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/go-tpm v0.3.3 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect - github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -107,19 +107,21 @@ require ( github.com/secure-systems-lab/go-securesystemslib v0.5.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/smartystreets/goconvey v1.6.4 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tevino/abool v1.2.0 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/otel v1.30.0 + go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/sdk v1.30.0 + go.opentelemetry.io/otel/trace v1.30.0 google.golang.org/protobuf v1.33.0 gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) -go 1.21 +go 1.22 + +toolchain go1.22.2 diff --git a/go.sum b/go.sum index 0486726421..57f22c5b97 100644 --- a/go.sum +++ b/go.sum @@ -5,14 +5,14 @@ github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.4.9/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= +github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/apache/thrift v0.13.1-0.20200603211036-eac4d0c79a5f/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/apache/thrift v0.20.0 h1:631+KvYbsBZxmuJjYwhezVsrfc/TbqtZV4QcxOX1fOI= +github.com/apache/thrift v0.20.0/go.mod h1:hOk1BQqcp2OLzGsyVXdfMk7YFlMxK3aoEVhjD06QhB8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -60,15 +60,17 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -89,7 +91,6 @@ github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -136,8 +137,8 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= @@ -182,7 +183,6 @@ github.com/kolide/systray v0.0.0-20240530130728-8265cd4e35db/go.mod h1:FwK9yUmU3 github.com/kolide/toast v1.0.2 h1:BQlIfO3wbKIEWfF0c8v4UkdhSIZYnSWaKkZl+Yarptk= github.com/kolide/toast v1.0.2/go.mod h1:OguLiOUf57YSEuZqjfk4uP4KdT0QOblGoySOI8F1I0Y= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -227,12 +227,12 @@ github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/osquery/osquery-go v0.0.0-20210622151333-99b4efa62ec5/go.mod h1:JKR5QhjsYdnIPY7hakgas5sxf8qlA/9wQnLqaMfWdcg= -github.com/osquery/osquery-go v0.0.0-20231006172600-d6f325f636a9 h1:+7IDjPDpcEwVqphCBCi/VWMF6sSSrqzJ3lq09K9cnAU= -github.com/osquery/osquery-go v0.0.0-20231006172600-d6f325f636a9/go.mod h1:mLJRc1Go8uP32LRALGvWj2lVJ+hDYyIfxDzVa+C5Yo8= +github.com/osquery/osquery-go v0.0.0-20231130195733-61ac79279aaa h1:bDsjvyU27AQGD/I23v6TUemEffCX0MnL2HVezsotJas= +github.com/osquery/osquery-go v0.0.0-20231130195733-61ac79279aaa/go.mod h1:mLJRc1Go8uP32LRALGvWj2lVJ+hDYyIfxDzVa+C5Yo8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= -github.com/peterbourgon/ff/v3 v3.0.0 h1:eQzEmNahuOjQXfuegsKQTSTDbf4dNvr/eNLrmJhiH7M= -github.com/peterbourgon/ff/v3 v3.0.0/go.mod h1:UILIFjRH5a/ar8TjXYLTkIvSvekZqPm5Eb/qbGk6CT0= +github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM= +github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -258,6 +258,8 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/saltosystems/winrt-go v0.0.0-20240510082706-db61b37f5877 h1:h+mGFGCgqpe2xqFpYtXSqDg3uJ1nYugFb5VQhTHvyL4= +github.com/saltosystems/winrt-go v0.0.0-20240510082706-db61b37f5877/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/samber/slog-multi v1.0.2 h1:6BVH9uHGAsiGkbbtQgAOQJMpKgV8unMrHhhJaw+X1EQ= @@ -297,8 +299,9 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= @@ -308,8 +311,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= github.com/theupdateframework/go-tuf v0.5.2 h1:habfDzTmpbzBLIFGWa2ZpVhYvFBoK0C1onC3a4zuPRA= @@ -339,18 +342,18 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= +go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -438,10 +441,11 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=