|
using System; |
|
using System.Collections.Generic; |
|
using System.Diagnostics; |
|
using System.Runtime.InteropServices; |
|
using System.Security; |
|
using System.Security.Principal; |
|
using System.Threading.Tasks; |
|
|
|
namespace SuessLabs.Tools; |
|
|
|
public class SampleUsage |
|
{ |
|
/// <summary>Sample command to execute with elevated user access.</summary> |
|
public const string DockerStopContainerCommand = "docker container stop MyContainer"; |
|
|
|
/// <summary>Execute using SUDO. Stop a Docker container.</summary> |
|
/// <returns>True on success.</returns> |
|
public static async Task<bool> DockerStopContainerAsync() |
|
{ |
|
var result = true; |
|
|
|
try |
|
{ |
|
var process = Bash.RunAs(DockerStopContainerCommand.Split(' ')); |
|
await process?.WaitForExitAsync(); |
|
} |
|
catch |
|
{ |
|
result = false; |
|
} |
|
|
|
return result; |
|
} |
|
|
|
/// <summary>Execute basic BASH command as the current user</summary> |
|
public static string ReadLogFromConsole(string containerName) |
|
{ |
|
// Sample command: string.format("ifconfig {0} {1} netmask {2} up", networkType, ipAddress, subnet); |
|
var log = Bash.Command($"iotedge logs {containerName}"); |
|
return log ?? string.Empty; |
|
} |
|
|
|
/// <summary>Execute basic BASH command as the current user</summary> |
|
public static string ReadLogFromDockerFilestring containerName() |
|
{ |
|
var log = Bash.Command("docker inspect --format=\"{{.LogPath}}\" " + containerName, true); |
|
return log ?? string.Empty; |
|
} |
|
} |
|
|
|
public class Bash |
|
{ |
|
/// <summary>Sample default admin password to use (BASE 64 encoded).</summary> |
|
private const string DefaultPass = "TXlQYXNzdzByZCE"; |
|
|
|
/// <summary>Sample default admin user name to use (BASE 64 encoded).</summary> |
|
private const string DefaultUser = "TXlVc2VyTmFtZQ"; |
|
|
|
/// <summary>Get Effective User Id (Linux only).</summary> |
|
/// <returns>Returns 0 when running as root.</returns> |
|
/// <remarks>Reference, <![CDATA[Mono.Unix.Native.Syscall.geteuid() == 0;]]>, <![CDATA[Mono.Unix.UserEnvironment.EffectiveUserId]]>.</remarks> |
|
[DllImport("libc", SetLastError = true, EntryPoint = "geteuid")] |
|
public static extern uint GetEuid(); |
|
|
|
/// <summary>Gets a value indicating whether the application was launched with admin privileges or not.</summary> |
|
public static bool IsAdministrator => |
|
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? |
|
new WindowsPrincipal(WindowsIdentity.GetCurrent()) |
|
.IsInRole(WindowsBuiltInRole.Administrator) : |
|
GetEuid() == 0; |
|
|
|
/// <summary> |
|
/// Execute BASH command. For SUDO commands, the app must be started with elevated privileges. |
|
/// </summary> |
|
/// <param name="command">Command to execute.</param> |
|
/// <param name="isSudo">Execute with SUDO.</param> |
|
/// <returns>Return results.</returns> |
|
public static string? Command(string command, bool isSudo = false) |
|
{ |
|
var output = string.Empty; |
|
var escapedArgs = command.Replace("\"", "\\\""); |
|
|
|
if (isSudo) |
|
escapedArgs = $"sudo {escapedArgs}"; |
|
|
|
var bashCommand = $@"-c ""{escapedArgs}"""; |
|
|
|
try |
|
{ |
|
var psi = new ProcessStartInfo |
|
{ |
|
FileName = "/bin/bash", |
|
Arguments = bashCommand, |
|
UseShellExecute = false, |
|
CreateNoWindow = true, |
|
RedirectStandardError = true, |
|
RedirectStandardInput = true, |
|
RedirectStandardOutput = true, |
|
}; |
|
|
|
if (isSudo) |
|
{ |
|
psi.UserName = TextDecode(DefaultUser); |
|
psi.PasswordInClearText = TextDecode(DefaultPass); |
|
} |
|
|
|
using var process = Process.Start(psi); |
|
output = process?.StandardOutput.ReadToEnd(); |
|
process?.WaitForExit(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
var title = "Error Loading Logs"; |
|
var message = $"An error occurred pulling logs.\nCommand: {bashCommand}\n\n{ex}"; |
|
Console.WriteLine($"{title} - {message}"); |
|
Debug.WriteLine($"{title} - {message}"); |
|
} |
|
|
|
return output; |
|
} |
|
|
|
/// <summary>Execute command as specified user, or leave blank for default account.</summary> |
|
/// <param name="command">Command to execute.</param> |
|
/// <param name="user">User name.</param> |
|
/// <param name="password">Password.</param> |
|
/// <returns>Process.</returns> |
|
/// <remarks> |
|
/// Note, the user must be apart of the `docker` group. |
|
/// <c><![CDATA[sudo addgroup --system docker; sudo adduser $USER docker]]></c>. |
|
/// </remarks> |
|
public static Process RunAs(IEnumerable<string> command, string user = "", string password = "") |
|
{ |
|
if (string.IsNullOrEmpty(user) && string.IsNullOrEmpty(password)) |
|
{ |
|
user = TextDecode(DefaultUser); |
|
password = TextDecode(DefaultPass); |
|
} |
|
|
|
var sudoArgs = new List<string>() |
|
{ |
|
"-k", // don't use cached credentials |
|
"-S", // read password from stdin |
|
"-u", user, // user |
|
"-p", string.Empty, // empty password prompt |
|
"--", // command separator |
|
}; |
|
|
|
sudoArgs.AddRange(command); |
|
|
|
var psi = new ProcessStartInfo() |
|
{ |
|
FileName = "sudo", |
|
RedirectStandardInput = true, // for writing the password |
|
}; |
|
|
|
sudoArgs.ForEach(arg => psi.ArgumentList.Add(arg)); |
|
Process process = Process.Start(psi)!; |
|
|
|
process.StandardInput.WriteLine(password); |
|
|
|
return process; |
|
} |
|
|
|
private static SecureString ConvertToSecureString(string password) |
|
{ |
|
if (password == null) |
|
throw new ArgumentNullException("Password"); |
|
|
|
unsafe |
|
{ |
|
fixed (char* passwordChars = password) |
|
{ |
|
var securePassword = new SecureString(passwordChars, password.Length); |
|
securePassword.MakeReadOnly(); |
|
return securePassword; |
|
} |
|
} |
|
} |
|
|
|
private static string TextDecode(string base64EncodedData) |
|
{ |
|
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); |
|
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); |
|
} |
|
|
|
private static string TextEncode(string plainText) |
|
{ |
|
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); |
|
return System.Convert.ToBase64String(plainTextBytes); |
|
} |
|
} |