From bdcfbb3b43af601ba8abcdf80234822ff051f1f5 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Fri, 2 Jul 2021 10:52:34 -0400 Subject: [PATCH] Allow for changing database name (#1397) * Remove hard coded database name * Update permissions on build scripts * Update Setup project and run scripts for configuring database name * Remove hyphen from database name flag * Update with suggested changes, still needs testing * Revert SQL statements to concatenantion for testing * Fix typo * Update util/Setup/EnvironmentFileBuilder.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Update SQL commands to prevent SQL injection attacks Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> --- bitwarden_license/src/Portal/build.sh | 0 bitwarden_license/src/Sso/build.sh | 0 scripts/run.ps1 | 34 +++++++++++++++++---------- scripts/run.sh | 11 ++++++++- util/Migrator/DbMigrator.cs | 17 ++++++++++---- util/MsSql/backup-db.sql | 14 ++++++++--- util/MsSql/entrypoint.sh | 7 ++++++ util/Setup/Context.cs | 1 + util/Setup/EnvironmentFileBuilder.cs | 4 ++-- util/Setup/Program.cs | 12 ++++++---- 10 files changed, 73 insertions(+), 27 deletions(-) mode change 100644 => 100755 bitwarden_license/src/Portal/build.sh mode change 100644 => 100755 bitwarden_license/src/Sso/build.sh diff --git a/bitwarden_license/src/Portal/build.sh b/bitwarden_license/src/Portal/build.sh old mode 100644 new mode 100755 diff --git a/bitwarden_license/src/Sso/build.sh b/bitwarden_license/src/Sso/build.sh old mode 100644 new mode 100755 diff --git a/scripts/run.ps1 b/scripts/run.ps1 index 23ae2adf3b..8ff0ea3451 100644 --- a/scripts/run.ps1 +++ b/scripts/run.ps1 @@ -21,15 +21,15 @@ $qFlag = "" $quietPullFlag = "" $certbotHttpPort = "80" $certbotHttpsPort = "443" -if($env:BITWARDEN_QUIET -eq "true") { +if ($env:BITWARDEN_QUIET -eq "true") { $setupQuiet = 1 $qFlag = " -q" $quietPullFlag = " --quiet-pull" } -if("${env:BITWARDEN_CERTBOT_HTTP_PORT}" -ne "") { +if ("${env:BITWARDEN_CERTBOT_HTTP_PORT}" -ne "") { $certbotHttpPort = $env:BITWARDEN_CERTBOT_HTTP_PORT } -if("${env:BITWARDEN_CERTBOT_HTTPS_PORT}" -ne "") { +if ("${env:BITWARDEN_CERTBOT_HTTPS_PORT}" -ne "") { $certbotHttpsPort = $env:BITWARDEN_CERTBOT_HTTPS_PORT } @@ -53,7 +53,7 @@ function Install() { if ($letsEncrypt -eq "y") { Write-Host "(!) " -f cyan -nonewline [string]$email = $( Read-Host ("Enter your email address (Let's Encrypt will send you certificate " + - "expiration reminders)") ) + "expiration reminders)") ) echo "" $letsEncryptPath = "${outputDir}/letsencrypt" @@ -61,18 +61,26 @@ function Install() { New-Item -ItemType directory -Path $letsEncryptPath | Out-Null } Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " +` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " +` - "certonly{0} --standalone --noninteractive --agree-tos --preferred-challenges http " +` + $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` + "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` + "certonly{0} --standalone --noninteractive --agree-tos --preferred-challenges http " + ` "--email ${email} -d ${domain} --logs-dir /etc/letsencrypt/logs" Invoke-Expression ($certbotExp -f $qFlag) } } + + Write-Host "(!) " -f cyan -nonewline + [string]$database = $( Read-Host "Enter the database name for your Bitwarden instance (ex. vault): ") + echo "" + + if ($database -eq "") { + $database = "vault" + } Pull-Setup docker run -it --rm --name setup -v ${outputDir}:/bitwarden bitwarden/setup:$coreVersion ` dotnet Setup.dll -install 1 -domain ${domain} -letsencrypt ${letsEncrypt} ` - -os win -corev $coreVersion -webv $webVersion -q $setupQuiet + -os win -corev $coreVersion -webv $webVersion -q $setupQuiet -dbname "$database" } function Docker-Compose-Up { @@ -137,8 +145,8 @@ function Docker-Prune { function Update-Lets-Encrypt { if (Test-Path -Path "${outputDir}\letsencrypt\live") { Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " +` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " +` + $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` + "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` "renew{0} --logs-dir /etc/letsencrypt/logs" -f $qFlag Invoke-Expression $certbotExp } @@ -147,8 +155,8 @@ function Update-Lets-Encrypt { function Force-Update-Lets-Encrypt { if (Test-Path -Path "${outputDir}\letsencrypt\live") { Invoke-Expression ("docker pull{0} certbot/certbot" -f "") #TODO: qFlag - $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " +` - "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " +` + $certbotExp = "docker run -it --rm --name certbot -p ${certbotHttpsPort}:443 -p ${certbotHttpPort}:80 " + ` + "-v ${outputDir}/letsencrypt:/etc/letsencrypt/ certbot/certbot " + ` "renew{0} --logs-dir /etc/letsencrypt/logs --force-renew" -f $qFlag Invoke-Expression $certbotExp } @@ -200,7 +208,7 @@ function Pull-Setup { } function Write-Line($str) { - if($env:BITWARDEN_QUIET -ne "true") { + if ($env:BITWARDEN_QUIET -ne "true") { Write-Host $str } } diff --git a/scripts/run.sh b/scripts/run.sh index 566ca25c50..8228060391 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -75,12 +75,21 @@ function install() { --email $EMAIL -d $DOMAIN --logs-dir /etc/letsencrypt/logs fi fi + + echo -e -n "${CYAN}(!)${NC} Enter the database name for your Bitwarden instance (ex. vault): " + read DATABASE + echo "" + + if [ "$DATABASE" == "" ] + then + DATABASE="vault" + fi pullSetup docker run -it --rm --name setup -v $OUTPUT_DIR:/bitwarden \ --env-file $ENV_DIR/uid.env bitwarden/setup:$COREVERSION \ dotnet Setup.dll -install 1 -domain $DOMAIN -letsencrypt $LETS_ENCRYPT -os $OS \ - -corev $COREVERSION -webv $WEBVERSION + -corev $COREVERSION -webv $WEBVERSION -dbname "$DATABASE" } function dockerComposeUp() { diff --git a/util/Migrator/DbMigrator.cs b/util/Migrator/DbMigrator.cs index 29dd1b813f..ddfa19a004 100644 --- a/util/Migrator/DbMigrator.cs +++ b/util/Migrator/DbMigrator.cs @@ -34,15 +34,24 @@ namespace Bit.Migrator using (var connection = new SqlConnection(_masterConnectionString)) { + var databaseName = new SqlConnectionStringBuilder(_connectionString).InitialCatalog; + if (string.IsNullOrWhiteSpace(databaseName)) + { + databaseName = "vault"; + } + var commandBuilder = new SqlCommandBuilder(); + var databaseNameQuoted = new SqlCommandBuilder().QuoteIdentifier(databaseName); var command = new SqlCommand( - "IF ((SELECT COUNT(1) FROM sys.databases WHERE [name] = 'vault') = 0) " + - "CREATE DATABASE [vault];", connection); + "IF ((SELECT COUNT(1) FROM sys.databases WHERE [name] = '@DatabaseName') = 0) " + + "CREATE DATABASE " + databaseNameQuoted + ";", connection); + command.Parameters.Add("@DatabaseName", System.Data.SqlDbType.VarChar); + command.Parameters["@DatabaseName"].Value = databaseName; command.Connection.Open(); command.ExecuteNonQuery(); command.CommandText = "IF ((SELECT DATABASEPROPERTYEX([name], 'IsAutoClose') " + - "FROM sys.databases WHERE [name] = 'vault') = 1) " + - "ALTER DATABASE [vault] SET AUTO_CLOSE OFF;"; + "FROM sys.databases WHERE [name] = '@DatabaseName') = 1) " + + "ALTER DATABASE " + databaseNameQuoted + " SET AUTO_CLOSE OFF;"; command.ExecuteNonQuery(); } diff --git a/util/MsSql/backup-db.sql b/util/MsSql/backup-db.sql index d838700ec2..99a5578e5a 100644 --- a/util/MsSql/backup-db.sql +++ b/util/MsSql/backup-db.sql @@ -1,10 +1,18 @@ +-- Database name which is set from the backup-db.sh script. +DECLARE @DatabaseName varchar(100) +SET @DatabaseName = 'vault' + +-- Database name without spaces for saving the backup files. +DELCARE @DatabaseNameSafe varchar(100) +SET @DatabaseNameSafe = 'vault' + DECLARE @BackupFile varchar(100) -SET @BackupFile = '/etc/bitwarden/mssql/backups/vault_FULL_$(now).BAK' +SET @BackupFile = '/etc/bitwarden/mssql/backups/' + @DatabaseNameSafe + '_FULL_$(now).BAK' DECLARE @BackupName varchar(100) -SET @BackupName = 'vault full backup for $(now)' +SET @BackupName = @DatabaseName + ' full backup for $(now)' DECLARE @BackupCommand NVARCHAR(1000) -SET @BackupCommand = 'BACKUP DATABASE [vault] TO DISK = ''' + @BackupFile + ''' WITH INIT, NAME= ''' + @BackupName + ''', NOSKIP, NOFORMAT' +SET @BackupCommand = 'BACKUP DATABASE [' + @DatabaseName + '] TO DISK = ''' + @BackupFile + ''' WITH INIT, NAME= ''' + @BackupName + ''', NOSKIP, NOFORMAT' EXEC(@BackupCommand) diff --git a/util/MsSql/entrypoint.sh b/util/MsSql/entrypoint.sh index cf490c01b1..141320059d 100644 --- a/util/MsSql/entrypoint.sh +++ b/util/MsSql/entrypoint.sh @@ -40,6 +40,13 @@ then export SA_PASSWORD=$(cat $SA_PASSWORD_FILE) fi +# Replace database name in backup-db.sql +if [ ! -z "$DATABASE" ] +then + sed -i -e "/@DatabaseName /s/vault/$DATABASE/" backup-db.sql + sed -i -e "/@DatabaseNameSafe /s/vault/${DATABASE// /-}/" backup-db.sql +fi + # The rest... mkdir -p /etc/bitwarden/mssql/backups diff --git a/util/Setup/Context.cs b/util/Setup/Context.cs index 0f6c7b707e..f6ded4a2aa 100644 --- a/util/Setup/Context.cs +++ b/util/Setup/Context.cs @@ -149,6 +149,7 @@ namespace Bit.Setup public bool SelfSignedCert { get; set; } public string IdentityCertPassword { get; set; } public string Domain { get; set; } + public string Database { get; set; } } } } diff --git a/util/Setup/EnvironmentFileBuilder.cs b/util/Setup/EnvironmentFileBuilder.cs index 8711fdfe6d..4f86ff4b2f 100644 --- a/util/Setup/EnvironmentFileBuilder.cs +++ b/util/Setup/EnvironmentFileBuilder.cs @@ -62,7 +62,7 @@ namespace Bit.Setup var dbConnectionString = new SqlConnectionStringBuilder { DataSource = "tcp:mssql,1433", - InitialCatalog = "vault", + InitialCatalog = _context.Install?.Database, UserID = "sa", Password = dbPassword, MultipleActiveResultSets = false, @@ -75,7 +75,7 @@ namespace Bit.Setup _globalOverrideValues = new Dictionary { ["globalSettings__baseServiceUri__vault"] = _context.Config.Url, - ["globalSettings__sqlServer__connectionString"] = $"\"{dbConnectionString}\"", + ["globalSettings__sqlServer__connectionString"] = $"'{dbConnectionString}'", ["globalSettings__identityServer__certificatePassword"] = _context.Install?.IdentityCertPassword, ["globalSettings__internalIdentityKey"] = _context.Stub ? "RANDOM_IDENTITY_KEY" : Helpers.SecureRandomString(64, alpha: true, numeric: true), diff --git a/util/Setup/Program.cs b/util/Setup/Program.cs index 112f634071..c5f0d1bb05 100644 --- a/util/Setup/Program.cs +++ b/util/Setup/Program.cs @@ -75,6 +75,10 @@ namespace Bit.Setup { _context.Install.Domain = _context.Parameters["domain"].ToLowerInvariant(); } + if (_context.Parameters.ContainsKey("dbname")) + { + _context.Install.Database = _context.Parameters["dbname"]; + } if (_context.Stub) { @@ -201,16 +205,16 @@ namespace Bit.Setup { var installationId = string.Empty; var installationKey = string.Empty; - + if (_context.Parameters.ContainsKey("install-id")) { installationId = _context.Parameters["install-id"].ToLowerInvariant(); } else { - installationId = Helpers.ReadInput("Enter your installation id (get at https://bitwarden.com/host)"); + installationId = Helpers.ReadInput("Enter your installation id (get at https://bitwarden.com/host)"); } - + if (!Guid.TryParse(installationId.Trim(), out var installationidGuid)) { Console.WriteLine("Invalid installation id."); @@ -225,7 +229,7 @@ namespace Bit.Setup { installationKey = Helpers.ReadInput("Enter your installation key"); } - + _context.Install.InstallationId = installationidGuid; _context.Install.InstallationKey = installationKey;