mirror of
https://github.com/bitwarden/server.git
synced 2024-11-25 12:45:18 +01:00
docker setup
This commit is contained in:
parent
ee8b0a25a8
commit
9bc6ba554a
@ -28,7 +28,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Billing", "src\Billing\Bill
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity", "src\Identity\Identity.csproj", "{04148736-3C0B-445E-8B74-2020E7A53502}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Identity", "src\Identity\Identity.csproj", "{04148736-3C0B-445E-8B74-2020E7A53502}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "Docker", "docker\Docker.dcproj", "{026DDB58-F0DB-4089-8168-83015AF785AE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Setup", "util\Setup\Setup.csproj", "{EF2164EF-1FC0-4518-A2ED-CE02D3630B00}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -62,10 +62,10 @@ Global
|
|||||||
{04148736-3C0B-445E-8B74-2020E7A53502}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{04148736-3C0B-445E-8B74-2020E7A53502}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{04148736-3C0B-445E-8B74-2020E7A53502}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{04148736-3C0B-445E-8B74-2020E7A53502}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{04148736-3C0B-445E-8B74-2020E7A53502}.Release|Any CPU.Build.0 = Release|Any CPU
|
{04148736-3C0B-445E-8B74-2020E7A53502}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{026DDB58-F0DB-4089-8168-83015AF785AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{EF2164EF-1FC0-4518-A2ED-CE02D3630B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{026DDB58-F0DB-4089-8168-83015AF785AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EF2164EF-1FC0-4518-A2ED-CE02D3630B00}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{026DDB58-F0DB-4089-8168-83015AF785AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EF2164EF-1FC0-4518-A2ED-CE02D3630B00}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{026DDB58-F0DB-4089-8168-83015AF785AE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EF2164EF-1FC0-4518-A2ED-CE02D3630B00}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -77,6 +77,7 @@ Global
|
|||||||
{B78A6C74-1A24-48C6-802A-13BE3E4DAFF1} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
{B78A6C74-1A24-48C6-802A-13BE3E4DAFF1} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||||
{02BC2982-ED8D-4A6D-A41E-092B3DAEB98A} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
{02BC2982-ED8D-4A6D-A41E-092B3DAEB98A} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||||
{04148736-3C0B-445E-8B74-2020E7A53502} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
{04148736-3C0B-445E-8B74-2020E7A53502} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||||
|
{EF2164EF-1FC0-4518-A2ED-CE02D3630B00} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {E01CBF68-2E20-425F-9EDB-E0A6510CA92F}
|
SolutionGuid = {E01CBF68-2E20-425F-9EDB-E0A6510CA92F}
|
||||||
|
@ -7,3 +7,4 @@ echo "=================="
|
|||||||
& $dir\src\Api\build.ps1
|
& $dir\src\Api\build.ps1
|
||||||
& $dir\src\Identity\build.ps1
|
& $dir\src\Identity\build.ps1
|
||||||
& $dir\nginx\build.ps1
|
& $dir\nginx\build.ps1
|
||||||
|
& $dir\util\Setup\build.ps1
|
||||||
|
1
build.sh
1
build.sh
@ -9,3 +9,4 @@ echo -e "=================="
|
|||||||
$DIR/src/Api/build.sh
|
$DIR/src/Api/build.sh
|
||||||
$DIR/src/Identity/build.sh
|
$DIR/src/Identity/build.sh
|
||||||
$DIR/nginx/build.sh
|
$DIR/nginx/build.sh
|
||||||
|
$DIR/util/Setup/build.sh
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="15.0" Sdk="Microsoft.Docker.Sdk">
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectVersion>2.0</ProjectVersion>
|
|
||||||
<DockerTargetOS>Linux</DockerTargetOS>
|
|
||||||
<ProjectGuid>026ddb58-f0db-4089-8168-83015af785ae</ProjectGuid>
|
|
||||||
<DockerLaunchBrowser>True</DockerLaunchBrowser>
|
|
||||||
<DockerServiceUrl>http://localhost:{ServicePort}</DockerServiceUrl>
|
|
||||||
<DockerServiceName>api</DockerServiceName>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="docker-compose.yml" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
@ -4,12 +4,11 @@ services:
|
|||||||
mssql:
|
mssql:
|
||||||
volumes:
|
volumes:
|
||||||
- /etc/bitwarden/mssql_data:/var/opt/mssql/data
|
- /etc/bitwarden/mssql_data:/var/opt/mssql/data
|
||||||
api:
|
|
||||||
volumes:
|
|
||||||
- /etc/bitwarden/core:/etc/core
|
|
||||||
identity:
|
identity:
|
||||||
volumes:
|
volumes:
|
||||||
- /etc/bitwarden/core:/etc/core
|
- /etc/bitwarden/identity:/etc/bitwarden/identity
|
||||||
nginx:
|
nginx:
|
||||||
volumes:
|
volumes:
|
||||||
|
- /etc/bitwarden/nginx:/etc/bitwarden/nginx
|
||||||
- /etc/bitwarden/letsencrypt:/etc/letsencrypt
|
- /etc/bitwarden/letsencrypt:/etc/letsencrypt
|
||||||
|
- /etc/bitwarden/ssl:/etc/certificates
|
||||||
|
@ -4,8 +4,13 @@ services:
|
|||||||
mssql:
|
mssql:
|
||||||
volumes:
|
volumes:
|
||||||
- mssql_data:/var/opt/mssql/data
|
- mssql_data:/var/opt/mssql/data
|
||||||
|
identity:
|
||||||
|
volumes:
|
||||||
|
- c:/bitwarden/identity:/etc/bitwarden/identity
|
||||||
nginx:
|
nginx:
|
||||||
volumes:
|
volumes:
|
||||||
|
- c:/bitwarden/nginx:/etc/bitwarden/nginx
|
||||||
- c:/bitwarden/letsencrypt:/etc/letsencrypt
|
- c:/bitwarden/letsencrypt:/etc/letsencrypt
|
||||||
|
- c:/bitwarden/ssl:/etc/certificates
|
||||||
volumes:
|
volumes:
|
||||||
mssql_data:
|
mssql_data:
|
||||||
|
@ -4,14 +4,13 @@ services:
|
|||||||
mssql:
|
mssql:
|
||||||
volumes:
|
volumes:
|
||||||
- mssql_data:/var/opt/mssql/data
|
- mssql_data:/var/opt/mssql/data
|
||||||
api:
|
|
||||||
volumes:
|
|
||||||
- c:/bitwarden/core:/etc/core
|
|
||||||
identity:
|
identity:
|
||||||
volumes:
|
volumes:
|
||||||
- c:/bitwarden/core:/etc/core
|
- c:/bitwarden/identity:/etc/bitwarden/identity
|
||||||
nginx:
|
nginx:
|
||||||
volumes:
|
volumes:
|
||||||
|
- c:/bitwarden/nginx:/etc/bitwarden/nginx
|
||||||
- c:/bitwarden/letsencrypt:/etc/letsencrypt
|
- c:/bitwarden/letsencrypt:/etc/letsencrypt
|
||||||
|
- c:/bitwarden/ssl:/etc/certificates
|
||||||
volumes:
|
volumes:
|
||||||
mssql_data:
|
mssql_data:
|
||||||
|
@ -3,7 +3,6 @@ FROM nginx:stable
|
|||||||
RUN rm /etc/nginx/nginx.conf
|
RUN rm /etc/nginx/nginx.conf
|
||||||
COPY nginx.conf /etc/nginx/nginx.conf
|
COPY nginx.conf /etc/nginx/nginx.conf
|
||||||
|
|
||||||
RUN rm /etc/nginx/conf.d/default.conf
|
COPY entrypoint.sh /
|
||||||
COPY default.conf /etc/nginx/conf.d/default.conf
|
RUN chmod +x /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
listen [::]:80 default_server;
|
|
||||||
server_name bw.kylespearrin.com;
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
listen [::]:443 ssl http2;
|
|
||||||
server_name bw.kylespearrin.com;
|
|
||||||
|
|
||||||
ssl_certificate /etc/letsencrypt/live/bw.kylespearrin.com/fullchain.pem;
|
|
||||||
ssl_certificate_key /etc/letsencrypt/live/bw.kylespearrin.com/privkey.pem;
|
|
||||||
|
|
||||||
ssl_session_timeout 30m;
|
|
||||||
ssl_session_cache shared:SSL:20m;
|
|
||||||
ssl_session_tickets off;
|
|
||||||
|
|
||||||
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
|
|
||||||
ssl_dhparam /etc/letsencrypt/live/bw.kylespearrin.com/dhparam.pem;
|
|
||||||
|
|
||||||
# SSL protocols TLS v1~TLSv1.2 are allowed. Disabed SSLv3
|
|
||||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
||||||
# Disabled insecure ciphers suite. For example, MD5, DES, RC4, PSK
|
|
||||||
ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH";
|
|
||||||
# enables server-side protection from BEAST attacks
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
|
|
||||||
# OCSP Stapling ---
|
|
||||||
# fetch OCSP records from URL in ssl_certificate and cache them
|
|
||||||
ssl_stapling on;
|
|
||||||
ssl_stapling_verify on;
|
|
||||||
|
|
||||||
## verify chain of trust of OCSP response using Root CA and Intermediate certs
|
|
||||||
ssl_trusted_certificate /etc/letsencrypt/live/bw.kylespearrin.com/fullchain.pem;
|
|
||||||
|
|
||||||
resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=300s;
|
|
||||||
|
|
||||||
# Headers
|
|
||||||
|
|
||||||
# X-Frame-Options is to prevent from clickJacking attack
|
|
||||||
#add_header X-Frame-Options SAMEORIGIN;
|
|
||||||
|
|
||||||
# disable content-type sniffing on some browsers.
|
|
||||||
add_header X-Content-Type-Options nosniff;
|
|
||||||
|
|
||||||
# This header enables the Cross-site scripting (XSS) filter
|
|
||||||
add_header X-XSS-Protection "1; mode=block";
|
|
||||||
|
|
||||||
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
|
|
||||||
#add_header Strict-Transport-Security max-age=15768000;
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
proxy_pass http://api/;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Url-Scheme $scheme;
|
|
||||||
proxy_redirect off;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /identity/ {
|
|
||||||
proxy_pass http://identity/;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Url-Scheme $scheme;
|
|
||||||
proxy_redirect off;
|
|
||||||
}
|
|
||||||
}
|
|
4
nginx/entrypoint.sh
Normal file
4
nginx/entrypoint.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cp /etc/bitwarden/nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
nginx -g 'daemon off;'
|
@ -1,7 +1,8 @@
|
|||||||
$dockerDir="../docker"
|
$dir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$dockerDir="${dir}\..\docker"
|
||||||
|
|
||||||
docker --version
|
docker --version
|
||||||
docker-compose --version
|
docker-compose --version
|
||||||
|
|
||||||
docker-compose -f $dockerDir/docker-compose.yml -f $dockerDir/docker-compose.windows.yml down
|
docker-compose -f ${dockerDir}\docker-compose.yml -f ${dockerDir}\docker-compose.windows.yml down
|
||||||
docker-compose -f $dockerDir/docker-compose.yml -f $dockerDir/docker-compose.windows.yml up -d
|
docker-compose -f ${dockerDir}\docker-compose.yml -f ${dockerDir}\docker-compose.windows.yml up -d
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
param (
|
param (
|
||||||
[string]$outputDir = "c:/bitwarden",
|
[string]$outputDir = "c:/bitwarden",
|
||||||
[string]$domain = $( Read-Host "Please enter your domain name (i.e. bitwarden.company.com)" ),
|
[string]$domain = $( Read-Host "Please enter your domain name (i.e. bitwarden.company.com)" ),
|
||||||
[string]$email = $( Read-Host "Please enter your email address (used to generate an HTTPS certificate with LetsEncrypt)" )
|
[string]$email = $( Read-Host "Please enter your email address: " ),
|
||||||
|
[string]$letsencrypt = $( Read-Host "Generate Let's Encrypt Cert (y/n)" )
|
||||||
)
|
)
|
||||||
|
|
||||||
$dockerDir="../docker"
|
$dockerDir="../docker"
|
||||||
$certPassword=-join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_})
|
|
||||||
$databasePassword=-join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_})
|
$databasePassword=-join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_})
|
||||||
$duoKey=-join ((48..57) + (97..122) | Get-Random -Count 32 | % {[char]$_})
|
|
||||||
|
|
||||||
docker --version
|
docker --version
|
||||||
|
|
||||||
@ -15,23 +14,6 @@ docker --version
|
|||||||
#docker run -it --rm -p 80:80 -v $outputDir/letsencrypt:/etc/letsencrypt/ certbot/certbot certonly --standalone --noninteractive --preferred-challenges http --email $email --agree-tos -d $domain
|
#docker run -it --rm -p 80:80 -v $outputDir/letsencrypt:/etc/letsencrypt/ certbot/certbot certonly --standalone --noninteractive --preferred-challenges http --email $email --agree-tos -d $domain
|
||||||
#docker run -it --rm -v $outputDir/letsencrypt/live:/certificates/ bitwarden/openssl openssl dhparam -out /certificates/$domain/dhparam.pem 2048
|
#docker run -it --rm -v $outputDir/letsencrypt/live:/certificates/ bitwarden/openssl openssl dhparam -out /certificates/$domain/dhparam.pem 2048
|
||||||
|
|
||||||
mkdir -p $outputDir/core
|
docker run -it --rm -v ${outputDir}:/bitwarden bitwarden/setup dotnet Setup.dll -domain ${domain} -letsencrypt ${letsencrypt} -db_pass ${databasePassword}
|
||||||
docker run -it --rm -v $outputDir/core:/certificates bitwarden/openssl openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout /certificates/identity.key -out /certificates/identity.crt -subj "/CN=bitwarden IdentityServer" -days 10950
|
|
||||||
docker run -it --rm -v $outputDir/core:/certificates bitwarden/openssl openssl pkcs12 -export -out /certificates/identity.pfx -inkey /certificates/identity.key -in /certificates/identity.crt -certfile /certificates/identity.crt -passout pass:$certPassword
|
|
||||||
rm $outputDir/core/identity.key
|
|
||||||
rm $outputDir/core/identity.crt
|
|
||||||
|
|
||||||
Add-Content $dockerDir/global.override.env "
|
echo "Setup complete"
|
||||||
globalSettings:baseServiceUri:vault=https://$domain
|
|
||||||
globalSettings:baseServiceUri:api=https://$domain/api
|
|
||||||
globalSettings:baseServiceUri:identity=https://$domain/identity
|
|
||||||
globalSettings:sqlServer:connectionString=Server=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=$databasePassword;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;
|
|
||||||
globalSettings:identityServer:certificatePassword=$certPassword
|
|
||||||
globalSettings:duo:aKey=$duoKey
|
|
||||||
globalSettings:yubico:clientId=REPLACE
|
|
||||||
globalSettings:yubico:REPLACE"
|
|
||||||
|
|
||||||
Add-Content $dockerDir/mssql.override.env "
|
|
||||||
ACCEPT_EULA=Y
|
|
||||||
MSSQL_PID=Express
|
|
||||||
SA_PASSWORD=$databasePassword"
|
|
||||||
|
@ -7,10 +7,7 @@ echo -e "\nPlease enter your email address (used to generate an HTTPS certificat
|
|||||||
read EMAIL
|
read EMAIL
|
||||||
|
|
||||||
OUTPUT_DIR=./bitwarden
|
OUTPUT_DIR=./bitwarden
|
||||||
DOCKER_DIR=../docker
|
|
||||||
CERT_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)
|
|
||||||
DATABASE_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)
|
DATABASE_PASSWORD=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32)
|
||||||
DUO_KEY=$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 64)
|
|
||||||
|
|
||||||
docker --version
|
docker --version
|
||||||
|
|
||||||
@ -18,25 +15,6 @@ docker --version
|
|||||||
#docker run -it --rm -p 80:80 -v $OUTPUT_DIR/letsencrypt:/etc/letsencrypt/ certbot/certbot certonly --standalone --noninteractive --preferred-challenges http --email $EMAIL --agree-tos -d $DOMAIN
|
#docker run -it --rm -p 80:80 -v $OUTPUT_DIR/letsencrypt:/etc/letsencrypt/ certbot/certbot certonly --standalone --noninteractive --preferred-challenges http --email $EMAIL --agree-tos -d $DOMAIN
|
||||||
#docker run -it --rm -v $OUTPUT_DIR/letsencrypt/live:/certificates/ bitwarden/openssl openssl dhparam -out /certificates/$DOMAIN/dhparam.pem 2048
|
#docker run -it --rm -v $OUTPUT_DIR/letsencrypt/live:/certificates/ bitwarden/openssl openssl dhparam -out /certificates/$DOMAIN/dhparam.pem 2048
|
||||||
|
|
||||||
mkdir -p $OUTPUT_DIR/core
|
docker run -it --rm -v $OUTPUT_DIR:/bitwarden bitwarden/setup dotnet Setup.dll -domain $DOMAIN -letsencrypt y -db_pass $DATABASE_PASSWORD
|
||||||
docker run -it --rm -v $OUTPUT_DIR/core:/certificates bitwarden/openssl openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout /certificates/identity.key -out /certificates/identity.crt -subj "/CN=bitwarden IdentityServer" -days 10950
|
|
||||||
docker run -it --rm -v $OUTPUT_DIR/core:/certificates bitwarden/openssl openssl pkcs12 -export -out /certificates/identity.pfx -inkey /certificates/identity.key -in /certificates/identity.crt -certfile /certificates/identity.crt -passout pass:$CERT_PASSWORD
|
|
||||||
rm $OUTPUT_DIR/core/identity.key
|
|
||||||
rm $OUTPUT_DIR/core/identity.crt
|
|
||||||
|
|
||||||
cat >> $DOCKER_DIR/global.override.env << EOF
|
echo -e "\nSetup complete"
|
||||||
globalSettings:baseServiceUri:vault=https://$DOMAIN
|
|
||||||
globalSettings:baseServiceUri:api=https://$DOMAIN/api
|
|
||||||
globalSettings:baseServiceUri:identity=https://$DOMAIN/identity
|
|
||||||
globalSettings:sqlServer:connectionString=Server=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=$DATABASE_PASSWORD;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30;
|
|
||||||
globalSettings:identityServer:certificatePassword=$CERT_PASSWORD
|
|
||||||
globalSettings:duo:aKey=$DUO_KEY
|
|
||||||
globalSettings:yubico:clientId=REPLACE
|
|
||||||
globalSettings:yubico:REPLACE
|
|
||||||
EOF
|
|
||||||
|
|
||||||
cat >> $DOCKER_DIR/mssql.override.env << EOF
|
|
||||||
ACCEPT_EULA=Y
|
|
||||||
MSSQL_PID=Express
|
|
||||||
SA_PASSWORD=$DATABASE_PASSWORD
|
|
||||||
EOF
|
|
||||||
|
@ -92,7 +92,7 @@ namespace Bit.Api
|
|||||||
|
|
||||||
// Services
|
// Services
|
||||||
services.AddBaseServices();
|
services.AddBaseServices();
|
||||||
services.AddDefaultServices();
|
services.AddDefaultServices(globalSettings);
|
||||||
|
|
||||||
// Cors
|
// Cors
|
||||||
services.AddCors(config =>
|
services.AddCors(config =>
|
||||||
|
@ -45,7 +45,7 @@ namespace Bit.Billing
|
|||||||
|
|
||||||
// Services
|
// Services
|
||||||
services.AddBaseServices();
|
services.AddBaseServices();
|
||||||
services.AddDefaultServices();
|
services.AddDefaultServices(globalSettings);
|
||||||
|
|
||||||
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
||||||
|
@ -22,13 +22,22 @@ namespace Bit.Core.Utilities
|
|||||||
filter = (e) => true;
|
filter = (e) => true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var serilog = new LoggerConfiguration()
|
var config = new LoggerConfiguration()
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.Filter.ByIncludingOnly(filter)
|
.Filter.ByIncludingOnly(filter);
|
||||||
.WriteTo.AzureDocumentDB(new Uri(globalSettings.DocumentDb.Uri), globalSettings.DocumentDb.Key,
|
|
||||||
timeToLive: TimeSpan.FromDays(7))
|
|
||||||
.CreateLogger();
|
|
||||||
|
|
||||||
|
if(globalSettings.DocumentDb != null && !string.IsNullOrWhiteSpace(globalSettings.DocumentDb.Uri) &&
|
||||||
|
!string.IsNullOrWhiteSpace(globalSettings.DocumentDb.Key))
|
||||||
|
{
|
||||||
|
config.WriteTo.AzureDocumentDB(new Uri(globalSettings.DocumentDb.Uri), globalSettings.DocumentDb.Key,
|
||||||
|
timeToLive: TimeSpan.FromDays(7));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// local file sink
|
||||||
|
}
|
||||||
|
|
||||||
|
var serilog = config.CreateLogger();
|
||||||
factory.AddSerilog(serilog);
|
factory.AddSerilog(serilog);
|
||||||
appLifetime.ApplicationStopped.Register(Log.CloseAndFlush);
|
appLifetime.ApplicationStopped.Register(Log.CloseAndFlush);
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,19 @@ namespace Bit.Core.Utilities
|
|||||||
services.AddSingleton<IGroupService, GroupService>();
|
services.AddSingleton<IGroupService, GroupService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddDefaultServices(this IServiceCollection services)
|
public static void AddDefaultServices(this IServiceCollection services, GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IMailService, RazorViewMailService>();
|
services.AddSingleton<IMailService, RazorViewMailService>();
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(globalSettings.Mail.SendGridApiKey))
|
||||||
|
{
|
||||||
services.AddSingleton<IMailDeliveryService, SendGridMailDeliveryService>();
|
services.AddSingleton<IMailDeliveryService, SendGridMailDeliveryService>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<IMailDeliveryService, NoopMailDeliveryService>();
|
||||||
|
}
|
||||||
|
|
||||||
#if NET461
|
#if NET461
|
||||||
services.AddSingleton<IPushNotificationService, NotificationHubPushNotificationService>();
|
services.AddSingleton<IPushNotificationService, NotificationHubPushNotificationService>();
|
||||||
services.AddSingleton<IPushRegistrationService, NotificationHubPushRegistrationService>();
|
services.AddSingleton<IPushRegistrationService, NotificationHubPushRegistrationService>();
|
||||||
@ -59,9 +68,24 @@ namespace Bit.Core.Utilities
|
|||||||
services.AddSingleton<IPushNotificationService, NoopPushNotificationService>();
|
services.AddSingleton<IPushNotificationService, NoopPushNotificationService>();
|
||||||
services.AddSingleton<IPushRegistrationService, NoopPushRegistrationService>();
|
services.AddSingleton<IPushRegistrationService, NoopPushRegistrationService>();
|
||||||
#endif
|
#endif
|
||||||
|
if(!string.IsNullOrWhiteSpace(globalSettings.Storage.ConnectionString))
|
||||||
|
{
|
||||||
services.AddSingleton<IBlockIpService, AzureQueueBlockIpService>();
|
services.AddSingleton<IBlockIpService, AzureQueueBlockIpService>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<IBlockIpService, NoopBlockIpService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(globalSettings.Attachment.ConnectionString))
|
||||||
|
{
|
||||||
services.AddSingleton<IAttachmentStorageService, AzureAttachmentStorageService>();
|
services.AddSingleton<IAttachmentStorageService, AzureAttachmentStorageService>();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<IAttachmentStorageService, NoopAttachmentStorageService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void AddNoopServices(this IServiceCollection services)
|
public static void AddNoopServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
@ -151,11 +175,15 @@ namespace Bit.Core.Utilities
|
|||||||
globalSettings.IdentityServer.CertificatePassword);
|
globalSettings.IdentityServer.CertificatePassword);
|
||||||
identityServerBuilder.AddSigningCredential(identityServerCert);
|
identityServerBuilder.AddSigningCredential(identityServerCert);
|
||||||
}
|
}
|
||||||
else
|
else if(!string.IsNullOrWhiteSpace(globalSettings.IdentityServer.CertificateThumbprint))
|
||||||
{
|
{
|
||||||
var identityServerCert = CoreHelpers.GetCertificate(globalSettings.IdentityServer.CertificateThumbprint);
|
var identityServerCert = CoreHelpers.GetCertificate(globalSettings.IdentityServer.CertificateThumbprint);
|
||||||
identityServerBuilder.AddSigningCredential(identityServerCert);
|
identityServerBuilder.AddSigningCredential(identityServerCert);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("No identity certificate to use.");
|
||||||
|
}
|
||||||
|
|
||||||
services.AddScoped<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
|
services.AddScoped<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>();
|
||||||
services.AddScoped<IProfileService, ProfileService>();
|
services.AddScoped<IProfileService, ProfileService>();
|
||||||
@ -168,7 +196,9 @@ namespace Bit.Core.Utilities
|
|||||||
this IServiceCollection services, IHostingEnvironment env, GlobalSettings globalSettings)
|
this IServiceCollection services, IHostingEnvironment env, GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
#if NET461
|
#if NET461
|
||||||
if(!env.IsDevelopment() && !globalSettings.SelfHosted)
|
if(!env.IsDevelopment() && !globalSettings.SelfHosted &&
|
||||||
|
!string.IsNullOrWhiteSpace(globalSettings.Storage.ConnectionString) &&
|
||||||
|
!string.IsNullOrWhiteSpace(globalSettings.DataProtection.CertificateThumbprint))
|
||||||
{
|
{
|
||||||
var dataProtectionCert = CoreHelpers.GetCertificate(globalSettings.DataProtection.CertificateThumbprint);
|
var dataProtectionCert = CoreHelpers.GetCertificate(globalSettings.DataProtection.CertificateThumbprint);
|
||||||
var storageAccount = CloudStorageAccount.Parse(globalSettings.Storage.ConnectionString);
|
var storageAccount = CloudStorageAccount.Parse(globalSettings.Storage.ConnectionString);
|
||||||
|
@ -49,7 +49,7 @@ namespace Bit.Identity
|
|||||||
|
|
||||||
// Services
|
// Services
|
||||||
services.AddBaseServices();
|
services.AddBaseServices();
|
||||||
services.AddDefaultServices();
|
services.AddDefaultServices(globalSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Configure(
|
public void Configure(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
cp /etc/core/identity.pfx /app/identity.pfx
|
cp /etc/bitwarden/identity/identity.pfx /app/identity.pfx
|
||||||
|
|
||||||
dotnet /app/Identity.dll
|
dotnet /app/Identity.dll
|
||||||
|
10
util/Setup/Dockerfile
Normal file
10
util/Setup/Dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
FROM microsoft/dotnet:2.0.0-preview2-runtime
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
# Dependencies
|
||||||
|
openssl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY obj/Docker/publish .
|
91
util/Setup/Helpers.cs
Normal file
91
util/Setup/Helpers.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Setup
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return SecureRandomString(length, RandomStringCharacters(alpha, upper, lower, numeric, special));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(
|
||||||
|
string.Format("{0} may contain no more than {1} characters.", nameof(characters), byteSize),
|
||||||
|
nameof(characters));
|
||||||
|
}
|
||||||
|
|
||||||
|
var outOfRangeStart = byteSize - (byteSize % characters.Length);
|
||||||
|
using(var rng = RandomNumberGenerator.Create())
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var buffer = new byte[128];
|
||||||
|
while(sb.Length < length)
|
||||||
|
{
|
||||||
|
rng.GetBytes(buffer);
|
||||||
|
for(var i = 0; i < buffer.Length && sb.Length < length; ++i)
|
||||||
|
{
|
||||||
|
// 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])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(characters[buffer[i] % characters.Length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string RandomStringCharacters(bool alpha, bool upper, bool lower, bool numeric, bool special)
|
||||||
|
{
|
||||||
|
var characters = string.Empty;
|
||||||
|
if(alpha)
|
||||||
|
{
|
||||||
|
if(upper)
|
||||||
|
{
|
||||||
|
characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lower)
|
||||||
|
{
|
||||||
|
characters += "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numeric)
|
||||||
|
{
|
||||||
|
characters += "0123456789";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(special)
|
||||||
|
{
|
||||||
|
characters += "!@#$%^*&";
|
||||||
|
}
|
||||||
|
|
||||||
|
return characters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
225
util/Setup/Program.cs
Normal file
225
util/Setup/Program.cs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Setup
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
private static string[] _args = null;
|
||||||
|
private static IDictionary<string, string> _parameters = null;
|
||||||
|
private static string _domain = null;
|
||||||
|
private static string _certPassword = null;
|
||||||
|
private static bool _ssl = false;
|
||||||
|
private static bool _letsEncrypt = false;
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
_args = args;
|
||||||
|
_parameters = ParseParameters();
|
||||||
|
|
||||||
|
_domain = _parameters.ContainsKey("domain") ? _parameters["domain"].ToLowerInvariant() : "localhost";
|
||||||
|
_letsEncrypt = _parameters.ContainsKey("letsencrypt") ? _parameters["letsencrypt"].ToLowerInvariant() == "y" : false;
|
||||||
|
_ssl = _letsEncrypt || (_parameters.ContainsKey("ssl") ? _parameters["ssl"].ToLowerInvariant() == "y" : false);
|
||||||
|
_certPassword = Helpers.SecureRandomString(32, alpha: true, numeric: true);
|
||||||
|
|
||||||
|
MakeIdentityCert();
|
||||||
|
BuildNginxConfig();
|
||||||
|
BuildEnvironmentFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void MakeIdentityCert()
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("/bitwarden/identity/");
|
||||||
|
var identityCertResult = Exec("openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout identity.key " +
|
||||||
|
"-out identity.crt -subj \"/CN=bitwarden IdentityServer\" -days 10950");
|
||||||
|
var identityPfxResult = Exec("openssl pkcs12 -export -out /bitwarden/identity/identity.pfx -inkey identity.key " +
|
||||||
|
$"-in identity.crt -certfile identity.crt -passout pass:{_certPassword}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildNginxConfig()
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("/bitwarden/nginx/");
|
||||||
|
var sslCiphers = "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:" +
|
||||||
|
"DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:" +
|
||||||
|
"ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" +
|
||||||
|
"ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:" +
|
||||||
|
"AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH";
|
||||||
|
|
||||||
|
var dh = _letsEncrypt ||
|
||||||
|
(_parameters.ContainsKey("ssl_dh") ? _parameters["ssl_dh"].ToLowerInvariant() == "y" : false);
|
||||||
|
var trusted = _letsEncrypt ||
|
||||||
|
(_parameters.ContainsKey("ssl_trusted") ? _parameters["ssl_trusted"].ToLowerInvariant() == "y" : false);
|
||||||
|
var certPath = _letsEncrypt ? $"/etc/letsencrypt/live/{_domain}" : $"/etc/certificates/{_domain}";
|
||||||
|
|
||||||
|
using(var sw = File.CreateText("/bitwarden/nginx/default.conf"))
|
||||||
|
{
|
||||||
|
sw.WriteLine($@"server {{
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
server_name {_domain};");
|
||||||
|
|
||||||
|
if(_ssl)
|
||||||
|
{
|
||||||
|
sw.WriteLine($@" return 301 https://$server_name$request_uri;
|
||||||
|
}}
|
||||||
|
|
||||||
|
server {{
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name {_domain};
|
||||||
|
|
||||||
|
ssl_certificate {certPath}/fullchain.pem;
|
||||||
|
ssl_certificate_key {certPath}/privkey.pem;
|
||||||
|
|
||||||
|
ssl_session_timeout 30m;
|
||||||
|
ssl_session_cache shared:SSL:20m;
|
||||||
|
ssl_session_tickets off;");
|
||||||
|
|
||||||
|
if(dh)
|
||||||
|
{
|
||||||
|
sw.WriteLine($@"
|
||||||
|
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
|
||||||
|
ssl_dhparam {certPath}/dhparam.pem;");
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.WriteLine($@"
|
||||||
|
# SSL protocols TLS v1~TLSv1.2 are allowed. Disabed SSLv3
|
||||||
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||||
|
# Disabled insecure ciphers suite. For example, MD5, DES, RC4, PSK
|
||||||
|
ssl_ciphers ""{sslCiphers}"";
|
||||||
|
# enables server-side protection from BEAST attacks
|
||||||
|
ssl_prefer_server_ciphers on;");
|
||||||
|
|
||||||
|
if(trusted)
|
||||||
|
{
|
||||||
|
sw.WriteLine($@"
|
||||||
|
# OCSP Stapling ---
|
||||||
|
# fetch OCSP records from URL in ssl_certificate and cache them
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
|
|
||||||
|
## verify chain of trust of OCSP response using Root CA and Intermediate certs
|
||||||
|
ssl_trusted_certificate {certPath}/fullchain.pem;
|
||||||
|
|
||||||
|
resolver 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=300s;");
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.WriteLine($@"
|
||||||
|
# Headers
|
||||||
|
|
||||||
|
# X-Frame-Options is to prevent from clickJacking attack
|
||||||
|
#add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
|
||||||
|
# disable content-type sniffing on some browsers.
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
|
||||||
|
# This header enables the Cross-site scripting (XSS) filter
|
||||||
|
add_header X-XSS-Protection ""1; mode=block"";
|
||||||
|
|
||||||
|
# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack
|
||||||
|
#add_header Strict-Transport-Security max-age=15768000;");
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.WriteLine($@"
|
||||||
|
location /api/ {{
|
||||||
|
proxy_pass http://api/;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Url-Scheme $scheme;
|
||||||
|
proxy_redirect off;
|
||||||
|
}}
|
||||||
|
|
||||||
|
location /identity/ {{
|
||||||
|
proxy_pass http://identity/;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Url-Scheme $scheme;
|
||||||
|
proxy_redirect off;
|
||||||
|
}}
|
||||||
|
}}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildEnvironmentFiles()
|
||||||
|
{
|
||||||
|
var url = _ssl ? $"https://{_domain}" : $"http://{_domain}";
|
||||||
|
var dbPass = _parameters.ContainsKey("db_pass") ? _parameters["db_pass"].ToLowerInvariant() : "REPLACE";
|
||||||
|
var dbConnectionString = "Server=tcp:mssql,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;" +
|
||||||
|
$"Password={dbPass};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=True;" +
|
||||||
|
"Connection Timeout=30;";
|
||||||
|
|
||||||
|
using(var sw = File.CreateText("/bitwarden/global.override.env"))
|
||||||
|
{
|
||||||
|
sw.Write($@"globalSettings:baseServiceUri:vault={url}
|
||||||
|
globalSettings:baseServiceUri:api={url}/api
|
||||||
|
globalSettings:baseServiceUri:identity={url}/identity
|
||||||
|
globalSettings:sqlServer:connectionString={dbConnectionString}
|
||||||
|
globalSettings:identityServer:certificatePassword={_certPassword}
|
||||||
|
globalSettings:duo:aKey={Helpers.SecureRandomString(32, alpha: true, numeric: true)}
|
||||||
|
globalSettings:yubico:clientId=REPLACE
|
||||||
|
globalSettings:yubico:REPLACE");
|
||||||
|
}
|
||||||
|
|
||||||
|
using(var sw = File.CreateText("/bitwarden/mssql.override.env"))
|
||||||
|
{
|
||||||
|
sw.Write($@"ACCEPT_EULA=Y
|
||||||
|
MSSQL_PID=Express
|
||||||
|
SA_PASSWORD={dbPass}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IDictionary<string, string> ParseParameters()
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, string>();
|
||||||
|
for(var i = 0; i < _args.Length; i = i + 2)
|
||||||
|
{
|
||||||
|
if(!_args[i].StartsWith("-"))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dict.Add(_args[i].Substring(1), _args[i + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Exec(string cmd)
|
||||||
|
{
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
var escapedArgs = cmd.Replace("\"", "\\\"");
|
||||||
|
process.StartInfo.FileName = "/bin/bash";
|
||||||
|
process.StartInfo.Arguments = $"-c \"{escapedArgs}\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process.StartInfo.FileName = "powershell";
|
||||||
|
process.StartInfo.Arguments = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
string result = process.StandardOutput.ReadToEnd();
|
||||||
|
process.WaitForExit();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
util/Setup/Setup.csproj
Normal file
13
util/Setup/Setup.csproj
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
11
util/Setup/build.ps1
Normal file
11
util/Setup/build.ps1
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
$dir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
|
||||||
|
echo "`n# Building Setup"
|
||||||
|
|
||||||
|
echo "`nBuilding app"
|
||||||
|
echo ".NET Core version $(dotnet --version)"
|
||||||
|
dotnet publish $dir\Setup.csproj -f netcoreapp2.0 -c "Release" -o $dir\obj\Docker\publish
|
||||||
|
|
||||||
|
echo "`nBuilding docker image"
|
||||||
|
docker --version
|
||||||
|
docker build -t bitwarden/setup $dir\.
|
14
util/Setup/build.sh
Normal file
14
util/Setup/build.sh
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(dirname $(readlink -f $0))"
|
||||||
|
|
||||||
|
echo -e "\n# Building Setup"
|
||||||
|
|
||||||
|
echo -e "\nBuilding app"
|
||||||
|
echo -e ".NET Core version $(dotnet --version)"
|
||||||
|
dotnet publish $DIR/Setup.csproj -f netcoreapp2.0 -c "Release" -o $DIR/obj/Docker/publish
|
||||||
|
|
||||||
|
echo -e "\nBuilding docker image"
|
||||||
|
docker --version
|
||||||
|
docker build -t bitwarden/setup $DIR/.
|
Loading…
Reference in New Issue
Block a user