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

[Fleet installer] Add additional pre-verification check for IIS variables #6697

Merged
merged 2 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
66 changes: 66 additions & 0 deletions tracer/src/Datadog.FleetInstaller/AppHostHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,53 @@ public static bool RemoveAllEnvironmentVariables(ILogger log)
return ModifyEnvironmentVariablesWithRetry(log, envVars, RemoveEnvVars);
}

public static bool GetAppPoolEnvironmentVariable(ILogger log, string environmentVariable, out string? value)
{
using var serverManager = new ServerManager();
var appPoolsSection = GetApplicationPoolsSection(log, serverManager);
if (appPoolsSection is null)
{
value = null;
return false;
}

var (applicationPoolDefaults, applicationPoolsCollection) = appPoolsSection.Value;

// Check defaults
log.WriteInfo($"Checking applicationPoolDefaults for environment variable: {environmentVariable}");
if (TryGetEnvVar(applicationPoolDefaults.GetCollection("environmentVariables"), environmentVariable) is { } envValue)
{
value = envValue;
return true;
}

foreach (var appPoolElement in applicationPoolsCollection)
{
if (string.Equals(appPoolElement.ElementTagName, "add", StringComparison.OrdinalIgnoreCase))
{
// An app pool element
var poolName = appPoolElement.GetAttributeValue("name") as string;
if (poolName is null)
{
// poolName can never be null, if it is, weirdness is afoot, so bail out
log.WriteInfo("Found app pool element without a name, skipping");
continue;
}

log.WriteInfo($"Checking app pool '{poolName}' for environment variable: {environmentVariable}");
if (TryGetEnvVar(appPoolElement.GetCollection("environmentVariables"), environmentVariable) is { } poolEnvValue)
{
value = poolEnvValue;
return true;
}
}
}

log.WriteInfo($"{environmentVariable} variable not found in any app pools");
value = null;
return false;
}

private static bool ModifyEnvironmentVariablesWithRetry(
ILogger log,
ReadOnlyDictionary<string, string> envVars,
Expand Down Expand Up @@ -275,4 +322,23 @@ private static void RemoveEnvVars(ConfigurationElementCollection envVars, ReadOn
envVars.Remove(element);
}
}

private static string? TryGetEnvVar(ConfigurationElementCollection envVars, string variable)
{
foreach (var envVarEle in envVars)
{
if (!string.Equals(envVarEle.ElementTagName, "add", StringComparison.OrdinalIgnoreCase))
{
continue;
}

if (envVarEle.GetAttributeValue("name") is string key
&& key.Equals(variable, StringComparison.OrdinalIgnoreCase))
{
return envVarEle["value"] as string;
}
}

return null;
}
}
40 changes: 40 additions & 0 deletions tracer/src/Datadog.FleetInstaller/Commands/InstallCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
Expand Down Expand Up @@ -55,6 +56,37 @@ internal static ReturnCode Execute(
{
log.WriteInfo("Installing .NET tracer");

bool tryIisRollback;

try
{
log.WriteInfo("Checking IIS app pools for pre-existing instrumentation variable");
if (AppHostHelper.GetAppPoolEnvironmentVariable(log, Defaults.InstrumentationInstallTypeKey, out var value))
{
var expectedValue = Defaults.InstrumentationInstallTypeValue;
if (expectedValue.Equals(value, StringComparison.Ordinal))
{
log.WriteInfo($"Found existing instrumentation install type with value {expectedValue}. Won't rollback IIS instrumentation if install fails");
tryIisRollback = false;
}
else
{
log.WriteInfo($"Found instrumentation install type {value}, but did not have expected value {expectedValue}. Will rollback IIS instrumentation if install fails");
tryIisRollback = true;
}
}
else
{
log.WriteInfo("No existing fleet installer instrumentation install type found. Will rollback IIS instrumentation if install fails");
tryIisRollback = true;
}
}
catch (Exception ex)
{
log.WriteError(ex, "Error reading IIS app pools, installation failed");
return ReturnCode.ErrorReadingIisConfiguration;
}

if (!FileHelper.CreateLogDirectory(log, tracerLogDirectory))
{
// This probably isn't a reason to bail out
Expand All @@ -69,6 +101,14 @@ internal static ReturnCode Execute(
if (!AppHostHelper.SetAllEnvironmentVariables(log, tracerValues))
{
// hard to be sure exactly of the state at this point
if (tryIisRollback)
{
log.WriteInfo("Attempting IIS variable rollback");

// We ignore failures here
AppHostHelper.RemoveAllEnvironmentVariables(log);
}

return ReturnCode.ErrorSettingAppPoolVariables;
}

Expand Down
2 changes: 2 additions & 0 deletions tracer/src/Datadog.FleetInstaller/Defaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Datadog.FleetInstaller;
internal class Defaults
{
public const string CrashTrackingRegistryKey = @"Software\Microsoft\Windows\Windows Error Reporting\RuntimeExceptionHelperModules";
public const string InstrumentationInstallTypeKey = "DD_INSTRUMENTATION_INSTALL_TYPE";
public const string InstrumentationInstallTypeValue = "windows_fleet_installer";

public static string TracerLogDirectory
=> Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Datadog .NET Tracer", "logs");
Expand Down
1 change: 1 addition & 0 deletions tracer/src/Datadog.FleetInstaller/ReturnCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ internal enum ReturnCode
ErrorRemovingAppPoolVariables,
ErrorRemovingNativeLoaderFiles,
ErrorRemovingCrashTrackerKey,
ErrorReadingIisConfiguration,
Copy link
Contributor

@bmermet bmermet Feb 21, 2025

Choose a reason for hiding this comment

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

Not directly related to this change, but can we set the value for ErrorRemovingNativeLoaderFiles explicitly so that it doesn't accidentally get changed?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, coming up in a separate PR 🙂

}
2 changes: 1 addition & 1 deletion tracer/src/Datadog.FleetInstaller/TracerValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public TracerValues(string tracerHomeDirectory)
{ "DD_DOTNET_TRACER_HOME", TracerHomeDirectory },
{ "COR_ENABLE_PROFILING", "1" },
{ "CORECLR_ENABLE_PROFILING", "1" },
{ "DD_INSTRUMENTATION_INSTALL_TYPE", "windows_fleet_installer" },
{ Defaults.InstrumentationInstallTypeKey, Defaults.InstrumentationInstallTypeValue },
});
FilesToAddToGac =
[
Expand Down
Loading