src/library/EndpointManagement/LinuxEndpointManagerLauncher.cs (51 lines of code) (raw):
using Microsoft.BridgeToKubernetes.Common;
using Microsoft.BridgeToKubernetes.Common.Exceptions;
using Microsoft.BridgeToKubernetes.Common.IO;
using Microsoft.BridgeToKubernetes.Common.Logging;
using System;
using System.Threading;
using static Microsoft.BridgeToKubernetes.Common.Constants;
namespace Microsoft.BridgeToKubernetes.Library.EndpointManagement
{
internal class LinuxEndpointManagerLauncher : EndpointManagerLauncherBase
{
public LinuxEndpointManagerLauncher(
IEnvironmentVariables environmentVariables,
IFileSystem fileSystem,
ILog log,
IOperationContext operationContext,
IPlatform platform) : base(
environmentVariables,
fileSystem,
log,
operationContext,
platform,
false)
{
}
public override void LaunchEndpointManager(string currentUserName, string socketFilePath, string logFileDirectory, CancellationToken cancellationToken)
{
EnsureLauncherExists();
var quotedLaunchPathAndArguments = $"\\\"{_launcherPath}\\\" \\\"{currentUserName}\\\" \\\"{socketFilePath}\\\" \\\"{logFileDirectory}\\\" \\\"{_operationContext.CorrelationId}\\\"";
// Try to use pkexec to show a GUI prompt for the user's password so we can run EndpointManager as root.
// If we are already running as root, then pkexec will not show a prompt.
// When running in Codespaces the user is setup to run sudo without needing to enter password.
var fileName = _environmentVariables.IsCodespaces ? "sudo" : "pkexec";
var command = $"env HOME=\"{_fileSystem.HomeDirectoryPath}\" bash -c \"{quotedLaunchPathAndArguments} &> /dev/null &\"";
_log.Info($"Launch {EndpointManager.ProcessName}: {fileName} {command}");
var launchExitCode = LaunchExecutable(fileName, command, cancellationToken);
if (launchExitCode == 126)
{
// User cancellation
throw new InvalidUsageException(_log.OperationContext, Resources.LaunchProcessCancelled, EndpointManager.ProcessName);
}
// pkexec allows an authorized user to execute PROGRAM as another user. Refer - https://linux.die.net/man/1/pkexec
// if pkexec failed then launchExitCode will not be zero, so giving user another chance to try with sudo.
// But this might fail for users who don't have sudo access. This is specifically for Linux.
if (launchExitCode != 0 && !_environmentVariables.IsCodespaces)
{
_log.Info($"pkexec failed with exitCode {launchExitCode}, retrying with sudo");
fileName = "sudo"; // replace pkexec with sudo
_log.Info($"Launch {EndpointManager.ProcessName}: {fileName} {command}");
launchExitCode = LaunchExecutable(fileName, command, cancellationToken);
}
if (launchExitCode != 0)
{
throw new InvalidOperationException($"{EndpointManager.ProcessName} exited with exit code {launchExitCode}");
}
}
}
}