1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-24 12:35:25 +01:00
bitwarden-server/util/Setup/Helpers.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

235 lines
6.9 KiB
C#
Raw Normal View History

using System.Diagnostics;
2018-08-30 17:35:44 +02:00
using System.Reflection;
2017-12-21 04:31:30 +01:00
using System.Runtime.InteropServices;
2017-08-07 22:31:00 +02:00
using System.Security.Cryptography;
using System.Text;
2017-09-08 17:45:20 +02:00
namespace Bit.Setup;
2022-08-29 22:06:55 +02:00
2017-08-07 22:31:00 +02:00
public static class Helpers
{
public static string SecureRandomString(int length, bool alpha = true, bool upper = true, bool lower = true,
bool numeric = true, bool special = false)
2022-08-29 22:06:55 +02:00
{
2017-08-07 22:31:00 +02:00
return SecureRandomString(length, RandomStringCharacters(alpha, upper, lower, numeric, special));
2022-08-29 22:06:55 +02:00
}
2017-08-07 22:31:00 +02:00
// ref https://stackoverflow.com/a/8996788/1090359 with modifications
public static string SecureRandomString(int length, string characters)
{
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length), "length cannot be less than zero.");
}
if ((characters?.Length ?? 0) == 0)
{
throw new ArgumentOutOfRangeException(nameof(characters), "characters invalid.");
}
const int byteSize = 0x100;
if (byteSize < characters.Length)
{
2017-08-07 22:31:00 +02:00
throw new ArgumentException(
string.Format("{0} may contain no more than {1} characters.", nameof(characters), byteSize),
nameof(characters));
}
2017-08-07 22:31:00 +02:00
var outOfRangeStart = byteSize - (byteSize % characters.Length);
using (var rng = RandomNumberGenerator.Create())
2022-08-29 22:06:55 +02:00
{
2017-08-07 22:31:00 +02:00
var sb = new StringBuilder();
var buffer = new byte[128];
while (sb.Length < length)
2017-08-07 22:31:00 +02:00
{
rng.GetBytes(buffer);
for (var i = 0; i < buffer.Length && sb.Length < length; ++i)
2017-08-07 22:31:00 +02:00
{
// Divide the byte into charSet-sized groups. If the random value falls into the last group and the
// last group is too small to choose from the entire allowedCharSet, ignore the value in order to
// avoid biasing the result.
if (outOfRangeStart <= buffer[i])
2017-08-07 22:31:00 +02:00
{
continue;
}
2022-08-29 20:53:16 +02:00
2017-08-07 22:31:00 +02:00
sb.Append(characters[buffer[i] % characters.Length]);
2022-08-29 22:06:55 +02:00
}
}
2022-08-29 22:06:55 +02:00
2017-08-07 22:31:00 +02:00
return sb.ToString();
}
2022-08-29 22:06:55 +02:00
}
2017-08-07 22:31:00 +02:00
private static string RandomStringCharacters(bool alpha, bool upper, bool lower, bool numeric, bool special)
2022-08-29 22:06:55 +02:00
{
var characters = string.Empty;
if (alpha)
2017-08-07 22:31:00 +02:00
{
if (upper)
2017-08-07 22:31:00 +02:00
{
characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
}
if (lower)
2022-08-29 20:53:16 +02:00
{
2017-08-07 22:31:00 +02:00
characters += "abcdefghijklmnopqrstuvwxyz";
}
2022-08-29 22:06:55 +02:00
}
if (numeric)
2022-08-29 22:06:55 +02:00
{
characters += "0123456789";
2017-08-07 22:31:00 +02:00
}
2018-10-18 17:41:49 +02:00
if (special)
{
characters += "!@#$%^*&";
}
return characters;
}
2018-10-18 17:41:49 +02:00
public static string GetValueFromEnvFile(string envFile, string key)
2022-08-29 22:06:55 +02:00
{
if (!File.Exists($"/bitwarden/env/{envFile}.override.env"))
2022-08-29 22:06:55 +02:00
{
return null;
}
2017-12-21 04:31:30 +01:00
var lines = File.ReadAllLines($"/bitwarden/env/{envFile}.override.env");
foreach (var line in lines)
{
2018-03-30 15:40:14 +02:00
if (line.StartsWith($"{key}="))
{
return line.Split(new char[] { '=' }, 2)[1].Trim('"').Replace("\\\"", "\"");
}
}
return null;
2022-08-29 22:06:55 +02:00
}
2018-03-30 15:40:14 +02:00
public static string Exec(string cmd, bool returnStdout = false)
2022-08-29 22:06:55 +02:00
{
2018-03-30 15:40:14 +02:00
var process = new Process
{
StartInfo = new ProcessStartInfo
{
2017-12-21 04:31:30 +01:00
RedirectStandardOutput = true,
2018-03-30 15:40:14 +02:00
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
}
2018-03-30 15:40:14 +02:00
};
2022-08-29 22:06:55 +02:00
2017-08-24 17:16:01 +02:00
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
2022-08-29 22:06:55 +02:00
{
2017-08-24 17:16:01 +02:00
var escapedArgs = cmd.Replace("\"", "\\\"");
process.StartInfo.FileName = "/bin/bash";
2018-03-30 15:40:14 +02:00
process.StartInfo.Arguments = $"-c \"{escapedArgs}\"";
2022-08-29 22:06:55 +02:00
}
else
{
2018-03-30 15:40:14 +02:00
process.StartInfo.FileName = "powershell";
process.StartInfo.Arguments = cmd;
}
2022-08-29 20:53:16 +02:00
2019-03-12 15:26:14 +01:00
process.Start();
2017-12-21 04:31:30 +01:00
var result = returnStdout ? process.StandardOutput.ReadToEnd() : null;
2018-03-30 15:40:14 +02:00
process.WaitForExit();
return result;
2022-08-29 22:06:55 +02:00
}
2019-03-12 15:26:14 +01:00
public static string ReadInput(string prompt)
2022-08-29 22:06:55 +02:00
{
2019-03-12 15:26:14 +01:00
Console.ForegroundColor = ConsoleColor.Cyan;
2018-03-30 15:40:14 +02:00
Console.Write("(!) ");
Console.ResetColor();
Console.Write(prompt);
if (prompt.EndsWith("?"))
2022-08-29 20:53:16 +02:00
{
Console.Write(" (y/N)");
2022-08-29 20:53:16 +02:00
}
2018-03-30 15:40:14 +02:00
Console.Write(": ");
var input = Console.ReadLine();
2018-08-30 17:35:44 +02:00
Console.WriteLine();
2018-03-30 15:40:14 +02:00
return input;
2022-08-29 22:06:55 +02:00
}
2018-08-30 17:35:44 +02:00
2017-08-07 22:31:00 +02:00
public static bool ReadQuestion(string prompt)
2022-08-29 22:06:55 +02:00
{
2018-03-30 15:40:14 +02:00
var input = ReadInput(prompt).ToLowerInvariant().Trim();
return input == "y" || input == "yes";
2022-08-29 22:06:55 +02:00
}
public static void ShowBanner(Context context, string title, string message, ConsoleColor? color = null)
2022-08-29 22:06:55 +02:00
{
if (!context.PrintToScreen())
2018-08-30 17:35:44 +02:00
{
return;
}
if (color != null)
2022-08-29 22:06:55 +02:00
{
2018-08-30 17:35:44 +02:00
Console.ForegroundColor = color.Value;
2022-08-29 22:06:55 +02:00
}
2018-08-30 17:35:44 +02:00
Console.WriteLine($"!!!!!!!!!! {title} !!!!!!!!!!");
Console.WriteLine(message);
Console.WriteLine();
Console.ResetColor();
2022-08-29 22:06:55 +02:00
}
2019-03-12 15:26:14 +01:00
public static HandlebarsDotNet.HandlebarsTemplate<object, object> ReadTemplate(string templateName)
2022-08-29 22:06:55 +02:00
{
2019-03-12 15:26:14 +01:00
var assembly = typeof(Helpers).GetTypeInfo().Assembly;
var fullTemplateName = $"Bit.Setup.Templates.{templateName}.hbs";
if (!assembly.GetManifestResourceNames().Any(f => f == fullTemplateName))
2019-03-12 15:26:14 +01:00
{
return null;
2019-03-12 15:26:14 +01:00
}
using (var s = assembly.GetManifestResourceStream(fullTemplateName))
using (var sr = new StreamReader(s))
2019-03-12 15:26:14 +01:00
{
2018-08-30 17:35:44 +02:00
var templateText = sr.ReadToEnd();
2019-03-12 15:26:14 +01:00
return HandlebarsDotNet.Handlebars.Compile(templateText);
}
2022-08-29 22:06:55 +02:00
}
2019-03-12 15:26:14 +01:00
public static void WriteLine(Context context, string format = null, object arg0 = null, object arg1 = null,
object arg2 = null)
2022-08-29 22:06:55 +02:00
{
if (!context.PrintToScreen())
2019-03-12 15:26:14 +01:00
{
return;
}
if (format != null && arg0 != null && arg1 != null && arg2 != null)
{
2019-03-12 15:26:14 +01:00
Console.WriteLine(format, arg0, arg1, arg2);
}
else if (format != null && arg0 != null && arg1 != null)
{
2019-03-12 15:26:14 +01:00
Console.WriteLine(format, arg0, arg1);
}
else if (format != null && arg0 != null)
{
2019-03-12 15:26:14 +01:00
Console.WriteLine(format, arg0);
}
else if (format != null)
{
2019-03-12 15:26:14 +01:00
Console.WriteLine(format);
}
else
{
2019-03-12 15:26:14 +01:00
Console.WriteLine();
}
2017-08-07 22:31:00 +02:00
}
public static void WriteError(string errorMessage)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("(!) ");
Console.ResetColor();
Console.Write(errorMessage);
Console.WriteLine();
}
2017-08-07 22:31:00 +02:00
}