Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
85 changes: 85 additions & 0 deletions dev/docker-compose-seeder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
services:
# Identity Service
identity:
build:
context: ..
dockerfile: ./src/Identity/Dockerfile
environment:
ASPNETCORE_ENVIRONMENT: Development
globalSettings__selfHosted: "false"
globalSettings__baseServiceUri__vault: "http://localhost:8080"
globalSettings__baseServiceUri__api: "http://api:5000"
globalSettings__baseServiceUri__identity: "http://identity:5000"
globalSettings__databaseProvider: "sqlite"
globalSettings__sqlite__connectionString: "Data Source=/etc/bitwarden/db/vault_dev.db"
globalSettings__licenseDirectory: "/etc/bitwarden/core/licenses"
globalSettings__attachment__baseDirectory: "/etc/bitwarden/core/attachments"
globalSettings__dataProtection__directory: "/etc/bitwarden/core/aspnet-dataprotection"
globalSettings__developmentDirectory: "/etc/bitwarden/dev"
globalSettings__logDirectory: "/etc/bitwarden/logs"
ports:
- "33656:5000"
volumes:
- ./.data/db:/etc/bitwarden/db
- ./.data/dev:/etc/bitwarden/dev
networks:
- bitwarden

# API Service
api:
build:
context: ..
dockerfile: ./src/Api/Dockerfile
environment:
ASPNETCORE_ENVIRONMENT: Development
globalSettings__selfHosted: "false"
globalSettings__baseServiceUri__vault: "http://localhost:8080"
globalSettings__baseServiceUri__api: "http://api:5000"
globalSettings__baseServiceUri__identity: "http://identity:5000"
globalSettings__databaseProvider: "sqlite"
globalSettings__sqlite__connectionString: "Data Source=/etc/bitwarden/db/vault_dev.db"
globalSettings__licenseDirectory: "/etc/bitwarden/core/licenses"
globalSettings__attachment__baseDirectory: "/etc/bitwarden/core/attachments"
globalSettings__dataProtection__directory: "/etc/bitwarden/core/aspnet-dataprotection"
globalSettings__logDirectory: "/etc/bitwarden/logs"
ports:
- "4000:5000"
volumes:
- ./.data/api:/etc/bitwarden
- ./.data/db:/etc/bitwarden/db
depends_on:
- identity
networks:
- bitwarden

# Seeder API Service
seeder:
build:
context: ..
dockerfile: ./util/SeederApi/Dockerfile
environment:
ASPNETCORE_ENVIRONMENT: Development
globalSettings__selfHosted: "false"
globalSettings__baseServiceUri__vault: "http://localhost:8080"
globalSettings__baseServiceUri__api: "http://api:5000"
globalSettings__baseServiceUri__identity: "http://identity:5000"
globalSettings__databaseProvider: "sqlite"
globalSettings__sqlite__connectionString: "Data Source=/etc/bitwarden/db/vault_dev.db"
globalSettings__licenseDirectory: "/etc/bitwarden/core/licenses"
globalSettings__attachment__baseDirectory: "/etc/bitwarden/core/attachments"
globalSettings__dataProtection__directory: "/etc/bitwarden/core/aspnet-dataprotection"
globalSettings__logDirectory: "/etc/bitwarden/logs"
ports:
- "5100:5000"
volumes:
- ./.data/seeder:/etc/bitwarden
- ./.data/db:/etc/bitwarden/db
depends_on:
- api
- identity
networks:
- bitwarden

networks:
bitwarden:
driver: bridge
4 changes: 2 additions & 2 deletions util/RustSdk/RustSdk.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<Content Include="./rust/target/release/libsdk*.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
<Link>runtimes/linux-x64/native/libsdk.so</Link>
<Link>runtimes/linux-arm64/native/libsdk.so</Link>
</Content>
<Content Include="./rust/target/release/libsdk*.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand All @@ -49,7 +49,7 @@
<Content Include="./rust/target/release/libsdk*.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
<Link>runtimes/linux-x64/native/libsdk.so</Link>
<Link>runtimes/linux-arm64/native/libsdk.so</Link>
</Content>
<Content Include="./rust/target/release/libsdk*.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
83 changes: 83 additions & 0 deletions util/SeederApi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
###############################################

Check failure

Code scanning / Checkmarx One

(CVE-2005-2541) Critical

(CVE-2005-2541)

Check failure

Code scanning / Checkmarx One

(CVE-2019-1010022) Critical

(CVE-2019-1010022)

Check failure

Code scanning / Checkmarx One

(CVE-2023-45853) Critical

(CVE-2023-45853)

Check failure

Code scanning / Checkmarx One

(CVE-2025-13151) High

(CVE-2025-13151)

Check failure

Code scanning / Checkmarx One

(CVE-2024-28757) High

(CVE-2024-28757)

Check failure

Code scanning / Checkmarx One

(CVE-2025-55247) High

(CVE-2025-55247)

Check failure

Code scanning / Checkmarx One

(CVE-2025-48384) High

(CVE-2025-48384)

Check failure

Code scanning / Checkmarx One

(CVE-2026-0861) High

(CVE-2026-0861)

Check failure

Code scanning / Checkmarx One

(CVE-2025-0725) High

(CVE-2025-0725)

Check failure

Code scanning / Checkmarx One

(CVE-2024-38095) High

(CVE-2024-38095)

Check failure

Code scanning / Checkmarx One

(CVE-2025-15281) High

(CVE-2025-15281)

Check failure

Code scanning / Checkmarx One

(CVE-2015-3276) High

(CVE-2015-3276)

Check failure

Code scanning / Checkmarx One

(CVE-2017-18018) High

(CVE-2017-18018)

Check failure

Code scanning / Checkmarx One

(CVE-2025-55247) High

(CVE-2025-55247)

Check failure

Code scanning / Checkmarx One

(CVE-2025-55247) High

(CVE-2025-55247)

Check failure

Code scanning / Checkmarx One

(CVE-2022-24975) High

(CVE-2022-24975)

Check failure

Code scanning / Checkmarx One

(CVE-2024-26461) High

(CVE-2024-26461)

Check failure

Code scanning / Checkmarx One

(CVE-2019-9192) High

(CVE-2019-9192)

Check failure

Code scanning / Checkmarx One

(CVE-2018-5709) High

(CVE-2018-5709)

Check failure

Code scanning / Checkmarx One

(CVE-2025-6297) High

(CVE-2025-6297)

Check failure

Code scanning / Checkmarx One

(CVE-2026-24882) High

(CVE-2026-24882)

Check failure

Code scanning / Checkmarx One

(CVE-2018-6829) High

(CVE-2018-6829)

Check failure

Code scanning / Checkmarx One

(CVE-2025-26646) High

(CVE-2025-26646)

Check failure

Code scanning / Checkmarx One

(CVE-2025-26646) High

(CVE-2025-26646)

Check failure

Code scanning / Checkmarx One

(CVE-2025-9086) High

(CVE-2025-9086)

Check failure

Code scanning / Checkmarx One

(CVE-2018-20796) High

(CVE-2018-20796)

Check failure

Code scanning / Checkmarx One

(CVE-2025-59375) High

(CVE-2025-59375)

Check failure

Code scanning / Checkmarx One

(CVE-2025-15281) High

(CVE-2025-15281)

Check failure

Code scanning / Checkmarx One

(CVE-2025-46835) High

(CVE-2025-46835)

Check failure

Code scanning / Checkmarx One

(CVE-2025-48385) High

(CVE-2025-48385)

Check failure

Code scanning / Checkmarx One

(CVE-2023-2953) High

(CVE-2023-2953)

Check failure

Code scanning / Checkmarx One

(CVE-2024-52005) High

(CVE-2024-52005)

Check failure

Code scanning / Checkmarx One

(CVE-2026-0861) High

(CVE-2026-0861)

Check failure

Code scanning / Checkmarx One

(CVE-2017-17740) High

(CVE-2017-17740)

Check failure

Code scanning / Checkmarx One

(CVE-2023-31486) High

(CVE-2023-31486)

Check failure

Code scanning / Checkmarx One

(CVE-2023-45853) Critical

(CVE-2023-45853)

Check failure

Code scanning / Checkmarx One

(CVE-2019-1010022) Critical

(CVE-2019-1010022)

Check failure

Code scanning / Checkmarx One

(CVE-2005-2541) Critical

(CVE-2005-2541)

Check failure

Code scanning / Checkmarx One

(CVE-2023-31486) High

(CVE-2023-31486)

Check failure

Code scanning / Checkmarx One

(CVE-2019-9192) High

(CVE-2019-9192)

Check failure

Code scanning / Checkmarx One

(CVE-2018-6829) High

(CVE-2018-6829)

Check failure

Code scanning / Checkmarx One

(CVE-2026-24882) High

(CVE-2026-24882)

Check failure

Code scanning / Checkmarx One

(CVE-2025-6297) High

(CVE-2025-6297)

Check failure

Code scanning / Checkmarx One

(CVE-2025-13151) High

(CVE-2025-13151)

Check failure

Code scanning / Checkmarx One

(CVE-2017-18018) High

(CVE-2017-18018)

Check failure

Code scanning / Checkmarx One

(CVE-2018-20796) High

(CVE-2018-20796)

Check warning

Code scanning / Checkmarx One

(CVE-2024-10524) Medium

(CVE-2024-10524)

Check warning

Code scanning / Checkmarx One

(CVE-2023-31438) Medium

(CVE-2023-31438)

Check warning

Code scanning / Checkmarx One

(CVE-2018-1000021) Medium

(CVE-2018-1000021)

Check warning

Code scanning / Checkmarx One

(CVE-2025-10148) Medium

(CVE-2025-10148)

Check warning

Code scanning / Checkmarx One

(CVE-2024-26458) Medium

(CVE-2024-26458)

Check warning

Code scanning / Checkmarx One

(CVE-2011-3389) Medium

(CVE-2011-3389)

Check warning

Code scanning / Checkmarx One

(CVE-2013-4392) Medium

(CVE-2013-4392)

Check warning

Code scanning / Checkmarx One

(CVE-2025-68972) Medium

(CVE-2025-68972)

Check warning

Code scanning / Checkmarx One

(CVE-2023-31437) Medium

(CVE-2023-31437)

Check warning

Code scanning / Checkmarx One

(CVE-2024-10041) Medium

(CVE-2024-10041)

Check warning

Code scanning / Checkmarx One

(CVE-2024-2236) Medium

(CVE-2024-2236)

Check warning

Code scanning / Checkmarx One

(CVE-2020-15719) Medium

(CVE-2020-15719)

Check warning

Code scanning / Checkmarx One

(CVE-2019-1010023) Medium

(CVE-2019-1010023)

Check warning

Code scanning / Checkmarx One

(CVE-2025-14524) Medium

(CVE-2025-14524)

Check warning

Code scanning / Checkmarx One

(CVE-2010-4756) Medium

(CVE-2010-4756)

Check warning

Code scanning / Checkmarx One

(CVE-2022-27943) Medium

(CVE-2022-27943)

Check warning

Code scanning / Checkmarx One

(CVE-2019-1010024) Medium

(CVE-2019-1010024)

Check warning

Code scanning / Checkmarx One

(CVE-2023-31439) Medium

(CVE-2023-31439)

Check warning

Code scanning / Checkmarx One

(CVE-2025-27587) Medium

(CVE-2025-27587)

Check warning

Code scanning / Checkmarx One

(CVE-2021-31879) Medium

(CVE-2021-31879)

Check warning

Code scanning / Checkmarx One

(CVE-2024-2379) Medium

(CVE-2024-2379)

Check warning

Code scanning / Checkmarx One

(CVE-2025-14819) Medium

(CVE-2025-14819)
# Build stage #
###############################################
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build

# Docker buildx supplies the value for this arg
ARG TARGETPLATFORM

# Determine proper runtime value for .NET
# We put the value in a file to be read by later layers.
RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
RID=linux-x64 ; \
RUST_TARGET=x86_64-unknown-linux-gnu ; \
elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \
RID=linux-arm64 ; \
RUST_TARGET=aarch64-unknown-linux-gnu ; \
elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \
RID=linux-arm ; \
RUST_TARGET=armv7-unknown-linux-gnueabihf ; \
fi \
&& echo "RID=$RID" > /tmp/rid.txt \
&& echo "$RUST_TARGET" > /tmp/rust_target.txt

# Install Rust
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
curl \
&& curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal \
&& . $HOME/.cargo/env \
&& rustup target add $(cat /tmp/rust_target.txt) \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

ENV PATH="/root/.cargo/bin:${PATH}"

# Copy required project files
WORKDIR /source
COPY . ./

# Restore project dependencies and tools
WORKDIR /source/util/SeederApi
RUN . /tmp/rid.txt && dotnet restore -r $RID

# Build project
RUN . /tmp/rid.txt && dotnet publish \
-c release \
--no-restore \
--self-contained \
/p:PublishSingleFile=true \
-r $RID \
-o out

###############################################
# App stage #
###############################################
FROM mcr.microsoft.com/dotnet/aspnet:8.0

ARG TARGETPLATFORM
LABEL com.bitwarden.product="bitwarden"
ENV ASPNETCORE_ENVIRONMENT=Production
ENV ASPNETCORE_URLS=http://+:5000
ENV SSL_CERT_DIR=/etc/bitwarden/ca-certificates
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
EXPOSE 5000

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
curl \
krb5-user \
gosu \
tzdata \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Copy app from the build stage
WORKDIR /app
COPY --from=build /source/util/SeederApi/out /app
COPY ./util/SeederApi/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
HEALTHCHECK CMD curl -f http://localhost:5000/alive || exit 1

ENTRYPOINT ["/entrypoint.sh"]
49 changes: 49 additions & 0 deletions util/SeederApi/HostedServices/DatabaseMigrationHostedService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Data.Common;
using Bit.Core.Utilities;

namespace Bit.SeederApi.HostedServices;

public sealed class DatabaseMigrationHostedService(
IDbMigrator dbMigrator,
ILogger<DatabaseMigrationHostedService> logger)
: IHostedService, IDisposable
{
public async Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Starting database migration...");

// Wait 5 seconds to allow database file to be ready
await Task.Delay(5000, cancellationToken);

const int maxMigrationAttempts = 10;
for (var i = 1; i <= maxMigrationAttempts; i++)
{
try
{
dbMigrator.MigrateDatabase(true, cancellationToken);
logger.LogInformation("Database migration completed successfully");
break;
}
catch (DbException e)
{
if (i >= maxMigrationAttempts)
{
logger.LogError(e, "Database failed to migrate after {MaxAttempts} attempts", maxMigrationAttempts);
throw;
}

logger.LogWarning(e,
"Database unavailable for migration. Trying again (attempt #{AttemptNumber})...", i + 1);
await Task.Delay(5000, cancellationToken);
}
}
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.FromResult(0);
}

public void Dispose()
{ }
}
1 change: 1 addition & 0 deletions util/SeederApi/SeederApi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\SharedWeb\SharedWeb.csproj" />
<ProjectReference Include="..\Seeder\Seeder.csproj" />
<ProjectReference Include="..\SqliteMigrations\SqliteMigrations.csproj" />
</ItemGroup>

</Project>
13 changes: 12 additions & 1 deletion util/SeederApi/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ο»Ώusing System.Globalization;
using Bit.Core.Settings;
using Bit.SeederApi.Extensions;
using Bit.SeederApi.HostedServices;
using Bit.SharedWeb.Utilities;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand Down Expand Up @@ -28,7 +29,17 @@ public void ConfigureServices(IServiceCollection services)
services.AddCustomDataProtectionServices(Environment, globalSettings);

services.AddTokenizers();
services.AddDatabaseRepositories(globalSettings);
var databaseProvider = services.AddDatabaseRepositories(globalSettings);

// Register database migrator based on provider
switch (databaseProvider)
{
case Core.Enums.SupportedDatabaseProviders.Sqlite:
services.AddSingleton<Core.Utilities.IDbMigrator, SqliteMigrations.SqliteDbMigrator>();
services.AddHostedService<DatabaseMigrationHostedService>();
break;
}

services.AddTestPlayIdTracking(globalSettings);
services.AddManglerService(globalSettings);

Expand Down
54 changes: 54 additions & 0 deletions util/SeederApi/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/bin/sh

# Setup

GROUPNAME="bitwarden"
USERNAME="bitwarden"

LUID=${LOCAL_UID:-0}
LGID=${LOCAL_GID:-0}

# Step down from host root to well-known nobody/nogroup user

if [ $LUID -eq 0 ]
then
LUID=65534
fi
if [ $LGID -eq 0 ]
then
LGID=65534
fi

if [ "$(id -u)" = "0" ]
then
# Create user and group

groupadd -o -g $LGID $GROUPNAME >/dev/null 2>&1 ||
groupmod -o -g $LGID $GROUPNAME >/dev/null 2>&1
useradd -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1 ||
usermod -o -u $LUID -g $GROUPNAME -s /bin/false $USERNAME >/dev/null 2>&1
mkhomedir_helper $USERNAME

# The rest...

chown -R $USERNAME:$GROUPNAME /app
mkdir -p /etc/bitwarden/core
mkdir -p /etc/bitwarden/logs
mkdir -p /etc/bitwarden/ca-certificates
chown -R $USERNAME:$GROUPNAME /etc/bitwarden

if [ -f "/etc/bitwarden/kerberos/bitwarden.keytab" ] && [ -f "/etc/bitwarden/kerberos/krb5.conf" ]; then
chown -R $USERNAME:$GROUPNAME /etc/bitwarden/kerberos
fi

gosu_cmd="gosu $USERNAME:$GROUPNAME"
else
gosu_cmd=""
fi

if [ -f "/etc/bitwarden/kerberos/bitwarden.keytab" ] && [ -f "/etc/bitwarden/kerberos/krb5.conf" ]; then
cp -f /etc/bitwarden/kerberos/krb5.conf /etc/krb5.conf
$gosu_cmd kinit $globalSettings__kerberosUser -k -t /etc/bitwarden/kerberos/bitwarden.keytab
fi

exec $gosu_cmd /app/SeederApi
Loading