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

[Windows] Adding property in installer to support driver rollback #26711

Merged
merged 21 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions release.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@
"JMXFETCH_HASH": "6c5d4ae2f858aa57fac7f92d6615931bf95f9a99c92979090f2de9d4b3c1f0d3",
"MACOS_BUILD_VERSION": "master",
"WINDOWS_DDNPM_DRIVER": "release-signed",
"WINDOWS_DDNPM_VERSION": "2.6.0",
"WINDOWS_DDNPM_SHASUM": "b1611ad4ceb8366c88767aeb638abefb226081efbf546b8b886952dd1b18ec05",
"WINDOWS_DDNPM_VERSION": "2.6.1",
"WINDOWS_DDNPM_SHASUM": "31b90a301e499200c10afc0e15c5b7e0d8c1a85ac3c0f0e0745cb80855b10748",
"SECURITY_AGENT_POLICIES_VERSION": "master",
"WINDOWS_DDPROCMON_DRIVER": "release-signed",
"WINDOWS_DDPROCMON_VERSION": "1.0.1",
"WINDOWS_DDPROCMON_SHASUM": "7c13ba75f7a30704a6a4082e4cffc819c846fd6061c53372c8b9908fee11d621",
"WINDOWS_DDPROCMON_VERSION": "1.0.2",
"WINDOWS_DDPROCMON_SHASUM": "cf55e5163659dbbfac0c0cced6559a3042107da9e4df8140bea17067278061ab",
"WINDOWS_APMINJECT_COMMENT": "The WINDOWS_APMINJECT entries below should NOT be added to the release targets",
"WINDOWS_APMINJECT_MODULE": "release-signed",
"WINDOWS_APMINJECT_VERSION": "1.1.1",
"WINDOWS_APMINJECT_SHASUM": "c5c228f6030ce2e19b8bfb28bd054dc246c7f1c799431e73018e6cb46ee59d2f"
"WINDOWS_APMINJECT_VERSION": "1.1.2",
"WINDOWS_APMINJECT_SHASUM": "27d85ab3a26c123b2655a838b0bec099268de2f2b86d2b8a74232e65f4f8f05f"
},
"nightly-a7": {
"INTEGRATIONS_CORE_VERSION": "master",
Expand All @@ -32,16 +32,16 @@
"JMXFETCH_HASH": "6c5d4ae2f858aa57fac7f92d6615931bf95f9a99c92979090f2de9d4b3c1f0d3",
"MACOS_BUILD_VERSION": "master",
"WINDOWS_DDNPM_DRIVER": "release-signed",
"WINDOWS_DDNPM_VERSION": "2.6.0",
"WINDOWS_DDNPM_SHASUM": "b1611ad4ceb8366c88767aeb638abefb226081efbf546b8b886952dd1b18ec05",
"WINDOWS_DDNPM_VERSION": "2.6.1",
"WINDOWS_DDNPM_SHASUM": "31b90a301e499200c10afc0e15c5b7e0d8c1a85ac3c0f0e0745cb80855b10748",
"SECURITY_AGENT_POLICIES_VERSION": "master",
"WINDOWS_DDPROCMON_DRIVER": "release-signed",
"WINDOWS_DDPROCMON_VERSION": "1.0.1",
"WINDOWS_DDPROCMON_SHASUM": "7c13ba75f7a30704a6a4082e4cffc819c846fd6061c53372c8b9908fee11d621",
"WINDOWS_DDPROCMON_VERSION": "1.0.2",
"WINDOWS_DDPROCMON_SHASUM": "cf55e5163659dbbfac0c0cced6559a3042107da9e4df8140bea17067278061ab",
"WINDOWS_APMINJECT_COMMENT": "The WINDOWS_APMINJECT entries below should NOT be added to the release targets",
"WINDOWS_APMINJECT_MODULE": "release-signed",
"WINDOWS_APMINJECT_VERSION": "1.1.1",
"WINDOWS_APMINJECT_SHASUM": "c5c228f6030ce2e19b8bfb28bd054dc246c7f1c799431e73018e6cb46ee59d2f"
"WINDOWS_APMINJECT_VERSION": "1.1.2",
"WINDOWS_APMINJECT_SHASUM": "27d85ab3a26c123b2655a838b0bec099268de2f2b86d2b8a74232e65f4f8f05f"
},
"release-a6": {
"INTEGRATIONS_CORE_VERSION": "7.55.0-rc.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Each section from every release note are combined when the
# CHANGELOG.rst is rendered. So the text needs to be worded so that
# it does not depend on any information only available in another
# section. This may mean repeating some details, but each section
# must be readable independently of the other.
#
# Each section note must be formatted as reStructuredText.
---
fixes:
- |
Windows: Added driver rollback properties to ensure that all services and drivers are uninstalled or rolled back after an installation or upgrade failure.
21 changes: 15 additions & 6 deletions test/new-e2e/tests/windows/install-test/installtester.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,7 @@ func (t *Tester) TestUninstallExpectations(tt *testing.T) {
assert.NoError(tt, err, "uninstall should not remove agent user")

for _, serviceName := range servicetest.ExpectedInstalledServices() {
conf, err := windows.GetServiceConfig(t.host, serviceName)
if err == nil && windows.IsKernelModeServiceType(conf.ServiceType) {
// TODO WKINT-410: kernel mode services are not removed on install rollback
tt.Logf("WKINT-410: Skipping known failure, kernel mode service not removed: %s", serviceName)
continue
}
_, err := windows.GetServiceConfig(t.host, serviceName)
assert.Errorf(tt, err, "uninstall should remove service %s", serviceName)
}

Expand All @@ -252,6 +247,20 @@ func (t *Tester) TestUninstallExpectations(tt *testing.T) {
// Only do some basic checks on the agent since it's a previous version
func (t *Tester) testPreviousVersionExpectations(tt *testing.T) {
RequireAgentRunningWithNoErrors(tt, t.InstallTestClient)

serviceTester, err := servicetest.NewTester(t.host,
servicetest.WithExpectedAgentUser(t.expectedUserDomain, t.expectedUserName),
servicetest.WithExpectedInstallPath(t.expectedInstallPath),
servicetest.WithExpectedConfigRoot(t.expectedConfigRoot),
)
require.NoError(tt, err)
tt.Run("service config", func(tt *testing.T) {
actual, err := windows.GetServiceConfigMap(t.host, servicetest.ExpectedInstalledServices())
require.NoError(tt, err)
expected, err := serviceTester.ExpectedServiceConfig()
require.NoError(tt, err)
servicetest.AssertEqualServiceConfigValues(tt, expected, actual)
})
}

// More in depth checks on current version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class InstallStateTestSetup : SessionTestBaseSetup
public Mock<IRegistryServices> RegistryServices { get; } = new();
public Mock<IServiceController> ServiceController { get; } = new();

public Mock<INativeMethods> NativeMethods { get; } = new();

public InstallStateTestSetup()
{
ServiceController.SetupGet(s => s.Services).Returns(new WindowsService[] { });
Expand All @@ -25,7 +27,8 @@ public InstallStateCustomActions Create()
return new InstallStateCustomActions(
Session.Object,
RegistryServices.Object,
ServiceController.Object);
ServiceController.Object,
NativeMethods.Object);
}

public InstallStateTestSetup WithRegistryKey(Registries registry, string path, Dictionary<string, object> keys)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ public void ReadInstallState_Default_Values()
"DDAGENTUSER_NAME",
"PROJECTLOCATION",
"APPLICATIONDATADIRECTORY",
"DDAGENT_WINDOWSBUILD");
"DDAGENT_WINDOWSBUILD").And
.Contain("DDDRIVERROLLBACK_NPM", "1").And
.Contain("DDDRIVERROLLBACK_PROCMON", "1");
}

[Theory]
Expand Down Expand Up @@ -55,5 +57,27 @@ public void ReadInstallState_Can_Read_Registry_Keys()
.Contain("DDAGENT_WINDOWSBUILD", "z_1234567890");
}

[Theory]
[InlineData("7.54", "", "")]
[InlineData("6.53", "", "")]
[InlineData("7.50", "", "1")]
[InlineData("6.58", "1", "1")]
[InlineData("7.56", "1", "1")]
public void ReadDD_Driver_Rollback_Upgrade(string version, string NPMExpectedRollback, string procmonExopectedRollback)
{
var productCode = "{123-456-789}";
Test.Session.Setup(session => session["WIX_UPGRADE_DETECTED"]).Returns(productCode);
Test.NativeMethods.Setup(n => n.GetVersionString(productCode)).Returns(version);

Test.Create()
.ReadInstallState()
.Should()
.Be(ActionResult.Success);

Test.Properties.Should()
.Contain("DDDRIVERROLLBACK_NPM", NPMExpectedRollback).And
.Contain("DDDRIVERROLLBACK_PROCMON", procmonExopectedRollback);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,26 @@ public class InstallStateCustomActions
private readonly IRegistryServices _registryServices;
private readonly IServiceController _serviceController;

private readonly INativeMethods _nativeMethods;

public InstallStateCustomActions(
ISession session,
IRegistryServices registryServices,
IServiceController serviceController)
IServiceController serviceController,
INativeMethods nativeMethods)
{
_session = session;
_registryServices = registryServices;
_serviceController = serviceController;
_nativeMethods = nativeMethods;
}

public InstallStateCustomActions(ISession session)
: this(
session,
new RegistryServices(),
new ServiceController())
new ServiceController(),
new Win32NativeMethods())
{
}

Expand Down Expand Up @@ -122,6 +127,7 @@ public ActionResult ReadInstallState()
}

GetWindowsBuildVersion();
SetDDDriverRollback();
}
catch (Exception e)
{
Expand Down Expand Up @@ -154,6 +160,61 @@ public void GetWindowsBuildVersion()
}
}

public void SetDDDriverRollback()
{
var upgradeDetected = _session["WIX_UPGRADE_DETECTED"];

if (!string.IsNullOrEmpty(upgradeDetected))
{
var versionString = _nativeMethods.GetVersionString(upgradeDetected);
// Using Version class
// https://learn.microsoft.com/en-us/dotnet/api/system.version?view=net-8.0
var currentVersion = new Version(versionString);
Version version_53;
Version minimumVersion;

// Check major version
if (versionString[0] == '7')
{
version_53 = new Version("7.53");
minimumVersion = new Version("7.56");
}
else
{
version_53 = new Version("6.53");
minimumVersion = new Version("6.56");
}

var compareResult = currentVersion.CompareTo(minimumVersion);
if (compareResult < 0) // currentVersion is less than minimumVersion
{
clarkb7 marked this conversation as resolved.
Show resolved Hide resolved
_session["DDDRIVERROLLBACK_NPM"] = "";

var compare_53 = currentVersion.CompareTo(version_53);
if (compare_53 < 0) //currentVersion is less than 6.53/7.53
{
clarkb7 marked this conversation as resolved.
Show resolved Hide resolved
_session["DDDRIVERROLLBACK_PROCMON"] = "1";
}
else
{
_session["DDDRIVERROLLBACK_PROCMON"] = "";
}
}
else // currentVersion is not less than minimumVersion
{
_session["DDDRIVERROLLBACK_NPM"] = "1";
_session["DDDRIVERROLLBACK_PROCMON"] = "1";
}
}
else // This is a fresh install
clarkb7 marked this conversation as resolved.
Show resolved Hide resolved
{
_session["DDDRIVERROLLBACK_NPM"] = "1";
_session["DDDRIVERROLLBACK_PROCMON"] = "1";
}
_session.Log($"DDDriverRollback_NPM: {_session["DDDRIVERROLLBACK_NPM"]}");
_session.Log($"DDDriverRollback_Procmon: {_session["DDDRIVERROLLBACK_PROCMON"]}");
}

[CustomAction]
public static ActionResult ReadInstallState(Session session)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ bool LookupAccountName(
void EnablePrivilege(string privilegeName);

void GetCurrentUser(out string name, out SecurityIdentifier sid);

string GetVersionString(string product);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,15 @@ static extern int DsGetDcName
out IntPtr pDOMAIN_CONTROLLER_INFO
);

[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern Int32 MsiGetProductInfo
(
string product,
string property,
[Out] StringBuilder valueBuf,
ref Int32 len
);

#endregion
#region Public interface

Expand Down Expand Up @@ -914,6 +923,16 @@ public void GetCurrentUser(out string name, out SecurityIdentifier sid)
}
}

public string GetVersionString(string product)
{
var len = 512;
var builder = new System.Text.StringBuilder(len);

MsiGetProductInfo(product, "VersionString", builder, ref len);

return builder.ToString();
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public Project ConfigureProject()
{
AttributesDefinition = "Secure=yes"
},
// set this property to anything to indicate to the merge module that on install rollback, it should
// execute the install custom action rollback; otherwise it won't.
new Property("DDDRIVERROLLBACK_NPM", "1"),
new Property("DDDRIVERROLLBACK_PROCMON", "1"),
// Add a checkbox at the end of the setup to launch the Datadog Agent Manager
new LaunchCustomApplicationFromExitDialog(
_agentBinaries.TrayId,
Expand Down
Loading