Skip to content

Commit

Permalink
Full Unified support including Linux and Windows (#155 / #154)
Browse files Browse the repository at this point in the history
* Initial work

* Fix typo

* Fix typo

* Fix stupid issue

* Add comments and fix minor issues

* Add extra information

* Add Linux script for generating keys

* Add circleci

* Add comments

* Add extra option

* Add missing permissions and empty script for now

* Fix line endings

* Add missing mount point

* Simplify patch

* Fix scripts

* Reduce complexity

* Fix circleci

* Remove useless line

* Move to src folder and improve image creation
  • Loading branch information
GieltjE authored Jan 16, 2023
1 parent b819fe0 commit d4abc9e
Show file tree
Hide file tree
Showing 20 changed files with 732 additions and 680 deletions.
30 changes: 15 additions & 15 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
version: 2
jobs:
build:
machine: true
steps:
- checkout
- run:
name: Print the Current Time
command: date
- run:
name: Generate Keys
command: ./.keys/generate-keys.sh
- run:
name: Build script
command: ./build.sh
version: 2.1
jobs:
build:
machine: true
steps:
- checkout
- run:
name: Print the Current Time
command: date
- run:
name: Generate Keys
command: ./generateKeys.sh
- run:
name: Build script
command: ./build.sh y
3 changes: 3 additions & 0 deletions .servers/serverlist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
docker run -d --name bitwarden -v <full-local-path>\logs:/var/log/bitwarden -v <full-local-path>\bwdata:/etc/bitwarden -p 80:8080 --env-file <full-local-path>\settings.env bitwarden-patch
<OR>
docker-compose -f <full-local-path>/docker-compose.yml up -d
104 changes: 30 additions & 74 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# BitBetter

BitBetter is is a tool to modify Bitwarden's core dll to allow you to generate your own individual and organisation licenses. **You must have an existing installation of Bitwarden for BitBetter to modify.**
BitBetter is is a tool to modify Bitwarden's core dll to allow you to generate your own individual and organisation licenses.

Please see the FAQ below for details on why this software was created.

_Beware! BitBetter does janky stuff to rewrite the bitwarden core dll and allow the installation of a self signed certificate. Use at your own risk!_
_Beware! BitBetter does some semi janky stuff to rewrite the bitwarden core dll and allow the installation of a self signed certificate. Use at your own risk!_

Credit to https://github.com/h44z/BitBetter and https://github.com/jakeswenson/BitBetter

Expand All @@ -25,125 +25,82 @@ Credit to https://github.com/h44z/BitBetter and https://github.com/jakeswenson/B
- [Footnotes](#footnotes)

# Getting Started
The following instructions are for unix-based systems (Linux, BSD, macOS), it is possible to use a Windows systems assuming you are able to enable and install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
The following instructions are for unix-based systems (Linux, BSD, macOS) and Windows, just choose the correct script extension (.sh or .ps1 respectively).

## Dependencies
Aside from docker, which you also need for Bitwarden, BitBetter requires the following:

* Bitwarden (tested with 1.47.1, might work on lower versions)
* openssl (probably already installed on most Linux or WSL systems, any version should work)
* openssl (probably already installed on most Linux or WSL systems, any version should work, on Windows it will be auto installed using winget)

## Setting up BitBetter
With your dependencies installed, begin the installation of BitBetter by downloading it through Github or using the git command:

```bash
```
git clone https://github.com/jakeswenson/BitBetter.git
```

## Building BitBetter

Now that you've set up your build environment, you can **run the main build script** to generate a modified version of the `bitwarden/api` and `bitwarden/identity` docker images.

From the BitBetter directory, simply run:
```bash
./build.sh
```

This will create a new self-signed certificate in the `.keys` directory if one does not already exist and then create a modified version of the official `bitwarden/api` called `bitbetter/api` and a modified version of the `bitwarden/identity` called `bitbetter/identity`.

You may now simply create the file `/path/to/bwdata/docker/docker-compose.override.yml` with the following contents to utilize the modified images.
Now that you've set up your build environment, we need to specify which servers to start after the work is done.
The scripts supports running and patching multi instances.

```yaml
version: '3'
Edit the .servers/serverlist.txt file and fill in the missing values, they can be replaced with existing installation values.
This file may be empty, but there will be no containers will be spun up automatically.

services:
api:
image: bitbetter/api
Now it is time to **run the main build script** to generate a modified version of the `bitwarden/self-host` docker image and the license generator.

identity:
image: bitbetter/identity
From the BitBetter directory, simply run:
```
./build.[sh|ps1]
```

You'll also want to edit the `/path/to/bwdata/scripts/run.sh` file. In the `function restart()` block, comment out the call to `dockerComposePull`.

> Replace `dockerComposePull`<br>with `#dockerComposePull`

You can now start or restart Bitwarden as normal and the modified api will be used. **It is now ready to accept self-issued licenses.**

---
### Note: Manually generating Certificate & Key
This will create a new self-signed certificate in the `.keys` directory if one does not already exist and then create a modified version of the official `bitwarden/self-host` image called `bitwarden-patch`.

If you wish to generate your self-signed cert & key manually, you can run the following commands.
Afterwards it will automatically generate the license generator and start all previously specified containers which are **now ready to accept self-issued licenses.**

```bash
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.cert -days 36500 -outform DER -passout pass:test
openssl x509 -inform DER -in cert.cert -out cert.pem
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passin pass:test -passout pass:test
```

> Note that the password here must be `test`.<sup>[1](#f1)</sup>

---

## Updating Bitwarden and BitBetter

To update Bitwarden, the provided `update-bitwarden.sh` script can be used. It will rebuild the BitBetter images and automatically update Bitwarden afterwards. Docker pull errors can be ignored for api and identity images.

You can either run this script without providing any parameters in interactive mode (`./update-bitwarden.sh`) or by setting the parameters as follows, to run the script in non-interactive mode:
```bash
./update-bitwarden.sh param1 param2 param3
```
`param1`: The path to the directory containing your bwdata directory

`param2`: If you want the docker-compose file to be overwritten (either `y` or `n`)

`param3`: If you want the bitbetter images to be rebuild (either `y` or `n`)

If you are updating from versions <= 1.46.2, you may need to run `update-bitwarden.sh` twice to complete the update process.
To update Bitwarden, the same `build.[sh|ps1]` script can be used. It will rebuild the BitBetter image and automatically update Bitwarden before doing so.

## Generating Signed Licenses

There is a tool included in the directory `src/licenseGen/` that will generate new individual and organization licenses. These licenses will be accepted by the modified Bitwarden because they will be signed by the certificate you generated in earlier steps.


First, from the `BitBetter/src/licenseGen` directory, **build the license generator**.<sup>[2](#f2)</sup>

```bash
./build.sh
```
There is a tool included in the directory `licenseGen/` that will generate new individual and organization licenses. These licenses will be accepted by the modified Bitwarden because they will be signed by the certificate you generated in earlier steps.

In order to run the tool and generate a license you'll need to get a **user's GUID** in order to generate an **invididual license** or the server's **install ID** to generate an **Organization license**. These can be retrieved most easily through the Bitwarden [Admin Portal](https://help.bitwarden.com/article/admin-portal/).

**The user must have a verified email address at the time of license import, otherwise Bitwarden will reject the license key. Nevertheless, the license key can be generated even before the user's email is verified.**

If you generated your keys in the default `BitBetter/.keys` directory, you can **simply run the license gen in interactive mode** from the `Bitbetter` directory and **follow the prompts to generate your license**.
If you ran the build script, you can **simply run the license gen in interactive mode** from the `Bitbetter` directory and **follow the prompts to generate your license**.

```bash
./src/licenseGen/run.sh interactive
```
./licenseGen.[sh|ps1] interactive
```

**The license generator will spit out a JSON-formatted license which can then be used within the Bitwarden web front-end to license your user or org!**


---

### Note: Alternative Ways to Generate License
### Note: Manually generating Certificate & Key

If you wish to run the license gen from a directory aside from the root `BitBetter` one, you'll have to provide the absolute path to your cert.pfx.
If you wish to generate your self-signed cert & key manually, you can run the following commands.
Note that you should never have to do this yourself, but can also be triggered by running the generateKeys.[sh|ps1] script.

```bash
./src/licenseGen/run.sh /Absolute/Path/To/BitBetter/.keys/cert.pfx interactive
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.cert -days 36500 -outform DER -passout pass:test
openssl x509 -inform DER -in cert.cert -out cert.pem
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passin pass:test -passout pass:test
```

Additional, instead of interactive mode, you can also pass the parameters directly to the command as follows.
> Note that the password here must be `test`.<sup>[2](#f1)</sup>
```bash
./src/licenseGen/run.sh /Absolute/Path/To/BitBetter/.keys/cert.pfx user "Name" "E-Mail" "User-GUID" ["Storage Space in GB"] ["Custom LicenseKey"]
./src/licenseGen/run.sh /Absolute/Path/To/BitBetter/.keys/cert.pfx org "Name" "E-Mail" "Install-ID used to install the server" ["Storage Space in GB"] ["Custom LicenseKey"]
```

---


# FAQ: Questions you might have.

## Why build a license generator for open source software?
Expand All @@ -161,7 +118,6 @@ UPDATE: Bitwarden now offers a cheap license called [Families Organization](http

# Footnotes

<a name="#f1"><sup>1</sup></a> If you wish to change this you'll need to change the value that `src/licenseGen/Program.cs` uses for its `GenerateUserLicense` and `GenerateOrgLicense` calls. Remember, this is really unnecessary as this certificate does not represent any type of security-related certificate.

<a name="#f2"><sup>2</sup></a>This tool builds on top of the `bitbetter/api` container image so make sure you've built that above using the root `./build.sh` script.
<a name="#f1"><sup>1</sup></a>This tool builds on top of the `bitbetter/api` container image so make sure you've built that above using the root `./build.sh` script.

<a name="#f2"><sup>2</sup></a> If you wish to change this you'll need to change the value that `licenseGen/Program.cs` uses for its `GenerateUserLicense` and `GenerateOrgLicense` calls. Remember, this is really unnecessary as this certificate does not represent any type of security-related certificate.
104 changes: 104 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# define temporary directory
$tempdirectory = "$pwd\temp"
# define services to patch
$components = "Api","Identity"

# delete old directories / files if applicable
if (Test-Path "$tempdirectory") {
Remove-Item "$tempdirectory" -Recurse -Force
}

if (Test-Path -Path "$pwd\src\licenseGen\Core.dll" -PathType Leaf) {
Remove-Item "$pwd\src\licenseGen\Core.dll" -Force
}

if (Test-Path -Path "$pwd\src\licenseGen\cert.pfx" -PathType Leaf) {
Remove-Item "$pwd\src\licenseGen\cert.pfx" -Force
}

if (Test-Path -Path "$pwd\src\bitBetter\cert.cert" -PathType Leaf) {
Remove-Item "$pwd\src\bitBetter\cert.cert" -Force
}

# generate keys if none are available
if (!(Test-Path "$pwd\.keys")) {
.\generateKeys.ps1
}

# copy the key to bitBetter and licenseGen
Copy-Item "$pwd\.keys\cert.cert" -Destination "$pwd\src\bitBetter"
Copy-Item "$pwd\.keys\cert.pfx" -Destination "$pwd\src\licenseGen"

# build bitBetter and clean the source directory after
docker build -t bitbetter/bitbetter "$pwd\src\bitBetter"
Remove-Item "$pwd\src\bitBetter\cert.cert" -Force

# gather all running instances
$oldinstances = docker container ps --all -f Name=bitwarden --format '{{.ID}}'

# stop all running instances
foreach ($instance in $oldinstances) {
docker stop $instance
docker rm $instance
}

# update bitwarden itself
if ($args[0] -eq 'y')
{
docker pull bitwarden/self-host:beta
}
else
{
$confirmation = Read-Host "Update (or get) bitwarden source container"
if ($confirmation -eq 'y') {
docker pull bitwarden/self-host:beta
}
}

# stop and remove previous existing patch(ed) container
docker stop bitwarden-patch
docker rm bitwarden-patch
docker image rm bitwarden-patch

# start a new bitwarden instance so we can patch it
$patchinstance = docker run -d --name bitwarden-patch bitwarden/self-host:beta

# create our temporary directory
New-item -ItemType Directory -Path $tempdirectory

# extract the files that need to be patched from the services that need to be patched into our temporary directory
foreach ($component in $components) {
New-item -itemtype Directory -path "$tempdirectory\$component"
docker cp $patchinstance`:/app/$component/Core.dll "$tempdirectory\$component\Core.dll"
}

# run bitBetter, this applies our patches to the required files
docker run -v "$tempdirectory`:/app/mount" --rm bitbetter/bitbetter

# create a new image with the patched files
docker build . --tag bitwarden-patch --file "$pwd\src\bitBetter\Dockerfile-bitwarden-patch"

# stop and remove our temporary container
docker stop bitwarden-patch
docker rm bitwarden-patch

# copy our patched library to the licenseGen source directory
Copy-Item "$tempdirectory\Identity\Core.dll" -Destination "$pwd\src\licenseGen"

# remove our temporary directory
Remove-Item "$tempdirectory" -Recurse -Force

# start all user requested instances
foreach($line in Get-Content "$pwd\.servers\serverlist.txt") {
Invoke-Expression "& $line"
}

# remove our bitBetter image
docker image rm bitbetter/bitbetter

# build the licenseGen
docker build -t bitbetter/licensegen "$pwd\src\licenseGen"

# clean the licenseGen source directory
Remove-Item "$pwd\src\licenseGen\Core.dll" -Force
Remove-Item "$pwd\src\licenseGen\cert.pfx" -Force
Loading

0 comments on commit d4abc9e

Please sign in to comment.