Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vscode devcontainers #3080

Merged
merged 23 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ae65640
add devcontainers for `server`
tangowithfoxtrot Jul 3, 2023
a99cfd7
run db migrations automatically in dev environment
tangowithfoxtrot Jul 3, 2023
43d417b
remove curl
tangowithfoxtrot Jul 3, 2023
44e6f6a
remove trailing comma; causes parsing with `jq`
tangowithfoxtrot Jul 3, 2023
f7223e2
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Jul 4, 2023
6a29e44
use existing .env
tangowithfoxtrot Jul 8, 2023
7e22472
add initializeCommand
tangowithfoxtrot Jul 8, 2023
ede2b7b
use better search string
tangowithfoxtrot Jul 8, 2023
a6a606c
restructure common files
tangowithfoxtrot Jul 9, 2023
3f8b863
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Jul 9, 2023
8063269
chmod +x scripts
tangowithfoxtrot Jul 9, 2023
34e184b
remove problematic env config scripts
tangowithfoxtrot Jul 10, 2023
65775cb
add mention of var that is needed for devcontainer
tangowithfoxtrot Jul 10, 2023
a432770
remove ref to deleted script
tangowithfoxtrot Jul 10, 2023
9b40fa7
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Oct 10, 2023
82eb447
Update .devcontainer/community_dev/devcontainer.json
tangowithfoxtrot Oct 26, 2023
985f0e5
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Oct 26, 2023
dcbd674
Update .devcontainer/internal_dev/devcontainer.json
tangowithfoxtrot Oct 26, 2023
4107a66
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Nov 2, 2023
ac2b0ba
use dev image for `6.0.416` SDK
tangowithfoxtrot Nov 6, 2023
71732d1
revert to manual DB migrations
tangowithfoxtrot Nov 6, 2023
c16fb16
Merge branch 'master' into vscode-devcontainers
tangowithfoxtrot Nov 6, 2023
1382566
reuse SQL connection string var
tangowithfoxtrot Nov 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .devcontainer/bitwarden_common/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: '3'

services:
bitwarden_server:
image: mcr.microsoft.com/devcontainers/dotnet:0-6.0
volumes:
- ../../:/workspace:cached
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity

bitwarden_mssql:
image: mcr.microsoft.com/azure-sql-edge:latest
restart: unless-stopped
env_file:
../../dev/.env
environment:
ACCEPT_EULA: "Y"
MSSQL_PID: Developer
volumes:
- edgesql_dev_data:/var/opt/mssql
- ../../util/Migrator:/mnt/migrator/
- ../../dev/helpers/mssql:/mnt/helpers
- ../../dev/.data/mssql:/mnt/data
network_mode: service:bitwarden_server

bitwarden_mail:
image: sj26/mailcatcher:latest
restart: unless-stopped
network_mode: service:bitwarden_server

volumes:
edgesql_dev_data:
14 changes: 14 additions & 0 deletions .devcontainer/community_dev/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Bitwarden Community Dev",
"dockerComposeFile": "../../.devcontainer/bitwarden_common/docker-compose.yml",
"service": "bitwarden_server",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"settings": {},
"features": {},
"extensions": ["ms-dotnettools.csharp"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I sat on this to long the C# Dev Kit has come out and we should probably use that instead.

Suggested change
"extensions": ["ms-dotnettools.csharp"]
"extensions": ["ms-dotnettools.csdevkit"]

}
},
"postCreateCommand": "bash .devcontainer/community_dev/postCreateCommand.sh"
}
57 changes: 57 additions & 0 deletions .devcontainer/community_dev/postCreateCommand.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
export DEV_DIR=/workspace/dev
export CONTAINER_CONFIG=/workspace/.devcontainer/community_dev
git config --global --add safe.directory /workspace

get_installation_id_and_key() {
pushd ./dev >/dev/null || exit
echo "Please enter your installation id and key from https://bitwarden.com/host:"
read -r -p "Installation id: " INSTALLATION_ID
read -r -p "Installation key: " INSTALLATION_KEY
jq ".globalSettings.installation.id = \"$INSTALLATION_ID\" |
.globalSettings.installation.key = \"$INSTALLATION_KEY\"" \
secrets.json.example >secrets.json # create/overwrite secrets.json
popd >/dev/null || exit
}

configure_other_vars() {
pushd ./dev >/dev/null || exit
cp secrets.json .secrets.json.tmp
# set DB_PASSWORD equal to .services.mssql.environment.MSSQL_SA_PASSWORD, accounting for quotes
DB_PASSWORD="$(grep -oP 'MSSQL_SA_PASSWORD=["'"'"']?\K[^"'"'"'\s]+' $DEV_DIR/.env)"
CERT_OUTPUT="$(./create_certificates_linux.sh)"
#shellcheck disable=SC2086
IDENTITY_SERVER_FINGERPRINT="$(echo $CERT_OUTPUT | awk -F 'Identity Server Dev: ' '{match($2, /[[:alnum:]]+/); print substr($2, RSTART, RLENGTH)}')"
#shellcheck disable=SC2086
DATA_PROTECTION_FINGERPRINT="$(echo $CERT_OUTPUT | awk -F 'Data Protection Dev: ' '{match($2, /[[:alnum:]]+/); print substr($2, RSTART, RLENGTH)}')"
echo "Identity Server Dev: $IDENTITY_SERVER_FINGERPRINT"
echo "Data Protection Dev: $DATA_PROTECTION_FINGERPRINT"
jq \
".globalSettings.sqlServer.connectionString = \"Server=localhost;Database=vault_dev;User Id=SA;Password=$DB_PASSWORD;Encrypt=True;TrustServerCertificate=True\" |
.globalSettings.postgreSql.connectionString = \"Host=localhost;Username=postgres;Password=$DB_PASSWORD;Database=vault_dev;Include Error Detail=true\" |
.globalSettings.mySql.connectionString = \"server=localhost;uid=root;pwd=$DB_PASSWORD;database=vault_dev\" |
.globalSettings.identityServer.certificateThumbprint = \"$IDENTITY_SERVER_FINGERPRINT\" |
.globalSettings.dataProtection.certificateThumbprint = \"$DATA_PROTECTION_FINGERPRINT\"" \
.secrets.json.tmp >secrets.json
rm -f .secrets.json.tmp
popd >/dev/null || exit
}

one_time_setup() {
read -r -p \
"Would you like to configure your secrets and certificates for the first time?
WARNING: This will overwrite any existing secrets.json and certificate files.
Proceed? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "Running one-time setup script..."
sleep 1
get_installation_id_and_key
configure_other_vars
pushd ./dev >/dev/null || exit
pwsh ./setup_secrets.ps1 || true
popd >/dev/null || exit
fi
}

# main
one_time_setup
16 changes: 16 additions & 0 deletions .devcontainer/internal_dev/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "Bitwarden Dev",
"dockerComposeFile": [
"../../.devcontainer/bitwarden_common/docker-compose.yml",
"../../.devcontainer/internal_dev/docker-compose.override.yml"
], "service": "bitwarden_server",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"settings": {},
"features": {},
"extensions": ["ms-dotnettools.csharp"]
}
},
"postCreateCommand": "bash .devcontainer/internal_dev/postCreateCommand.sh"
}
9 changes: 9 additions & 0 deletions .devcontainer/internal_dev/docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: '3'

services:
bitwarden_storage:
image: mcr.microsoft.com/azure-storage/azurite:latest
restart: unless-stopped
volumes:
- ../../dev/.data/azurite:/data
network_mode: service:bitwarden_server
80 changes: 80 additions & 0 deletions .devcontainer/internal_dev/postCreateCommand.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
export DEV_DIR=/workspace/dev
export CONTAINER_CONFIG=/workspace/.devcontainer/internal_dev
git config --global --add safe.directory /workspace

get_installation_id_and_key() {
pushd ./dev >/dev/null || exit
echo "Please enter your installation id and key from https://bitwarden.com/host:"
read -r -p "Installation id: " INSTALLATION_ID
read -r -p "Installation key: " INSTALLATION_KEY
jq ".globalSettings.installation.id = \"$INSTALLATION_ID\" |
.globalSettings.installation.key = \"$INSTALLATION_KEY\"" \
secrets.json.example >secrets.json # create/overwrite secrets.json
popd >/dev/null || exit
}

remove_comments() {
# jq will not parse files with comments
file="$1"

if [[ -f "$file" ]]; then
sed -e '/^\/\//d' -e 's@[[:blank:]]\{1,\}//.*@@' "$file" >"$file.tmp"
mv "$file.tmp" "$file"
fi
}

configure_other_vars() {
pushd ./dev >/dev/null || exit
cp secrets.json .secrets.json.tmp
# set DB_PASSWORD equal to .services.mssql.environment.MSSQL_SA_PASSWORD, accounting for quotes
DB_PASSWORD="$(grep -oP 'MSSQL_SA_PASSWORD=["'"'"']?\K[^"'"'"'\s]+' $DEV_DIR/.env)"
CERT_OUTPUT="$(./create_certificates_linux.sh)"
#shellcheck disable=SC2086
IDENTITY_SERVER_FINGERPRINT="$(echo $CERT_OUTPUT | awk -F 'Identity Server Dev: ' '{match($2, /[[:alnum:]]+/); print substr($2, RSTART, RLENGTH)}')"
#shellcheck disable=SC2086
DATA_PROTECTION_FINGERPRINT="$(echo $CERT_OUTPUT | awk -F 'Data Protection Dev: ' '{match($2, /[[:alnum:]]+/); print substr($2, RSTART, RLENGTH)}')"
echo "Identity Server Dev: $IDENTITY_SERVER_FINGERPRINT"
echo "Data Protection Dev: $DATA_PROTECTION_FINGERPRINT"
jq \
".globalSettings.sqlServer.connectionString = \"Server=localhost;Database=vault_dev;User Id=SA;Password=$DB_PASSWORD;Encrypt=True;TrustServerCertificate=True\" |
.globalSettings.postgreSql.connectionString = \"Host=localhost;Username=postgres;Password=$DB_PASSWORD;Database=vault_dev;Include Error Detail=true\" |
.globalSettings.mySql.connectionString = \"server=localhost;uid=root;pwd=$DB_PASSWORD;database=vault_dev\" |
.globalSettings.identityServer.certificateThumbprint = \"$IDENTITY_SERVER_FINGERPRINT\" |
.globalSettings.dataProtection.certificateThumbprint = \"$DATA_PROTECTION_FINGERPRINT\"" \
.secrets.json.tmp >secrets.json
rm .secrets.json.tmp
popd >/dev/null || exit
}

one_time_setup() {
read -r -p \
"Would you like to configure your secrets and certificates for the first time?
WARNING: This will overwrite any existing secrets.json and certificate files.
Proceed? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "Running one-time setup script..."
sleep 1
read -r -p \
"Place the secrets.json and dev.pfx files from our shared Collection in the ./dev directory.
Press <Enter> to continue."
remove_comments ./dev/secrets.json
configure_other_vars
echo "Installing Az module. This will take ~a minute..."
pwsh -Command "Install-Module -Name Az -Scope CurrentUser -Repository PSGallery -Force"
pwsh ./dev/setup_azurite.ps1

dotnet tool install dotnet-certificate-tool -g >/dev/null

read -r -s -p "Paste the \"Licensing Certificate - Dev\" password: " CERT_PASSWORD
echo
pushd ./dev >/dev/null || exit
certificate-tool add --file ./dev.pfx --password "$CERT_PASSWORD"
echo "Injecting dotnet secrets..."
pwsh ./setup_secrets.ps1 || true
popd >/dev/null || exit
fi
}

# main
one_time_setup
4 changes: 4 additions & 0 deletions dev/.env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
COMPOSE_PROJECT_NAME=bitwardenserver
# Ensure the MSSQL_PASSWORD is complex and follows the password policy defined at
# https://docs.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver15

# The MSSQL*_PASSWORD variables can be the same value; MSSQL_SA_PASSWORD is used for VS Code devcontainers
# and MSSQL_PASSWORD is used for docker-compose for traditional dev configurations.
MSSQL_PASSWORD=SET_A_PASSWORD_HERE_123
MSSQL_SA_PASSWORD=SET_A_PASSWORD_HERE_123
MAILCATCHER_PORT=1080

# Alternative databases
Expand Down
2 changes: 1 addition & 1 deletion src/Admin/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void ConfigureServices(IServiceCollection services)
// Jobs service
Jobs.JobsHostedService.AddJobsServices(services, globalSettings.SelfHosted);
services.AddHostedService<Jobs.JobsHostedService>();
if (globalSettings.SelfHosted)
if (globalSettings.SelfHosted || Environment.IsDevelopment())
{
services.AddHostedService<HostedServices.DatabaseMigrationHostedService>();
}
Expand Down