Compare commits

...

19 Commits

Author SHA1 Message Date
Michiel Hazelhof
08a6b94d47
Migrate cert.cert if exists 2025-08-12 19:27:37 +02:00
Michiel Hazelhof
70517634a5
Add missing file 2025-08-12 17:07:00 +02:00
Michiel Hazelhof
99148f6faf
Use proper file extension 2025-08-12 17:06:19 +02:00
Michiel Hazelhof
6fbcf13b7f
Cleanup org license 2025-08-12 16:40:24 +02:00
Michiel Hazelhof
ca2815411f
Fix tabs 2025-08-12 16:22:48 +02:00
Michiel Hazelhof
4341ad3beb
Add comment 2025-08-12 16:22:15 +02:00
Michiel Hazelhof
1d3bbbcd92
Fix typo 2025-08-12 16:21:20 +02:00
Michiel Hazelhof
5cff265a2a
Fix line endings 2025-08-12 16:16:47 +02:00
Michiel Hazelhof
a527d425fd
Improve naming 2025-08-12 16:15:51 +02:00
Michiel Hazelhof
f9055c711a
Better detect running patched containers 2025-08-12 16:13:11 +02:00
Michiel Hazelhof
1871df136b
Merge branch 'unified' into unified 2025-08-12 15:51:22 +02:00
Michiel Hazelhof
fe7ac2131e
Add missing parameter 2025-08-12 15:47:20 +02:00
Michiel Hazelhof
874ff182c6
Properly detect previous version 2025-08-12 15:45:54 +02:00
juliokele
29add24126
licenseGen: fix OrganizationLicense namespace (#253)
Co-authored-by: juliokele <>
2025-08-03 18:11:30 +02:00
Joseph Gigantino
3689cc5ba1
Test generating user and organization licenses during build check (#251)
Add commands to build check to test if the created licensegen image can actually generate user and organization licenses. licenseGen.sh will print the generated license to stdout and return zero if successful. If an error occurs, a non zero error code is returned which should cause a build error.
2025-07-30 19:51:51 +02:00
Joseph Gigantino
34da077778
Update Program.cs (#241)
Remove duplicate instances of:
Set("UseRiskInsights", true);
Set("UseOrganizationDomains", true);     Set("UseAdminSponsoredFamilies", true);

Signed-off-by: Joseph Gigantino <128943406+Jgigantino31@users.noreply.github.com>
Co-authored-by: h44z <christoph.h@sprinternet.at>
2025-07-29 19:54:54 +02:00
juliokele
a3803cb3bc
[unified] Fix licenseGen according to upstream changes (#247)
* Dockerfile: remove not existing executable argument

* licenseGen: fix classes according to upstream changes

---------

Co-authored-by: juliokele <>
2025-07-29 19:49:52 +02:00
juliokele
01cdfa2842
[unified] Fix patch according to upstream changes and fix build errors (#243)
* Fix bitbetter patch according to upstream changes

* Fix the builds by removing redundant already removed and stopped old instance

---------

Co-authored-by: juliokele <>
2025-07-29 19:48:55 +02:00
Michiel Hazelhof
076b0a624b
Upstream patches (#240) 2025-07-15 10:00:09 +01:00
11 changed files with 96 additions and 63 deletions

2
.gitignore vendored
View File

@ -7,5 +7,5 @@ src/bitBetter/.vs/*
*.pem *.pem
.vscode/ .vscode/
*.pfx *.pfx
*.cert *.cer
*.vsidx *.vsidx

View File

@ -1,4 +1,4 @@
# Uncomment a line below and fill in the missing values or add your own. Every line in this file will be called by build.[sh|ps1] once the patched image is built. # Uncomment a line below and fill in the missing values or add your own. Every line in this file will be called by build.[sh|ps1] once the patched image is built.
# 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 # 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-patched
# <OR> # <OR>
# docker-compose -f <full-local-path>/docker-compose.yml up -d # docker-compose -f <full-local-path>/docker-compose.yml up -d

View File

@ -46,8 +46,8 @@ If you wish to generate your self-signed cert & key manually, you can run the fo
```bash ```bash
cd .keys cd .keys
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.cert -days 36500 -outform DER -passout pass:test openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.cer -days 36500 -outform DER -passout pass:test
openssl x509 -inform DER -in cert.cert -out cert.pem openssl x509 -inform DER -in cert.cer -out cert.pem
openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passin pass:test -passout pass:test openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem -passin pass:test -passout pass:test
``` ```
@ -70,7 +70,7 @@ From the BitBetter directory, simply run:
./build.[sh|ps1] ./build.[sh|ps1]
``` ```
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 `ghcr.io/bitwarden/self-host` image called `bitwarden-patch`. 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 `ghcr.io/bitwarden/self-host` image called `bitwarden-patched`.
Afterwards it will automatically generate the license generator and start all previously specified containers which are **now ready to accept self-issued licenses.** Afterwards it will automatically generate the license generator and start all previously specified containers which are **now ready to accept self-issued licenses.**

View File

@ -7,7 +7,7 @@ $tempdirectory = "$pwd\temp"
$components = "Api","Identity" $components = "Api","Identity"
# delete old directories / files if applicable # delete old directories / files if applicable
if (Test-Path "$tempdirectory") { if (Test-Path "$tempdirectory" -PathType Container) {
Remove-Item "$tempdirectory" -Recurse -Force Remove-Item "$tempdirectory" -Recurse -Force
} }
@ -19,33 +19,38 @@ if (Test-Path -Path "$pwd\src\licenseGen\cert.pfx" -PathType Leaf) {
Remove-Item "$pwd\src\licenseGen\cert.pfx" -Force Remove-Item "$pwd\src\licenseGen\cert.pfx" -Force
} }
if (Test-Path -Path "$pwd\src\bitBetter\cert.cert" -PathType Leaf) { if (Test-Path -Path "$pwd\src\bitBetter\cert.cer" -PathType Leaf) {
Remove-Item "$pwd\src\bitBetter\cert.cert" -Force Remove-Item "$pwd\src\bitBetter\cert.cer" -Force
} }
if (Test-Path "$pwd\.keys\cert.cert" -PathType Leaf) {
Rename-Item -Path "$pwd\.keys\cert.cert" -NewName "$pwd\.keys\cert.cer"
}
# generate keys if none are available # generate keys if none are available
if (!(Test-Path "$pwd\.keys")) { if (!(Test-Path "$pwd\.keys" -PathType Container)) {
.\generateKeys.ps1 .\generateKeys.ps1
} }
# copy the key to bitBetter # copy the key to bitBetter
Copy-Item "$pwd\.keys\cert.cert" -Destination "$pwd\src\bitBetter" Copy-Item "$pwd\.keys\cert.cer" -Destination "$pwd\src\bitBetter"
# build bitBetter and clean the source directory after # build bitBetter and clean the source directory after
docker build --no-cache -t bitbetter/bitbetter "$pwd\src\bitBetter" docker build --no-cache -t bitbetter/bitbetter "$pwd\src\bitBetter"
Remove-Item "$pwd\src\bitBetter\cert.cert" -Force Remove-Item "$pwd\src\bitBetter\cert.cer" -Force
# gather all running instances # gather all running instances, cannot run a wildcard filter on Ancestor= :(
$oldinstances = docker container ps --all -f Name=bitwarden --format '{{.ID}}' $oldinstances = docker container ps --all -f Name=bitwarden --format '{{.ID}}'
# stop all running instances # stop and remove all running instances
foreach ($instance in $oldinstances) { foreach ($instance in $oldinstances) {
docker stop $instance docker stop $instance
docker rm $instance docker rm $instance
} }
# update bitwarden itself # update bitwarden itself
if ($args[0] -eq 'y') { if ($args[0] -eq 'update') {
docker pull ghcr.io/bitwarden/self-host:beta docker pull ghcr.io/bitwarden/self-host:beta
} else { } else {
$confirmation = Read-Host "Update (or get) bitwarden source container (y/n)" $confirmation = Read-Host "Update (or get) bitwarden source container (y/n)"
@ -55,12 +60,25 @@ if ($args[0] -eq 'y') {
} }
# stop and remove previous existing patch(ed) container # stop and remove previous existing patch(ed) container
docker stop bitwarden-patch $oldinstances = docker container ps --all -f Ancestor=bitwarden-patched --format '{{.ID}}'
docker rm bitwarden-patch foreach ($instance in $oldinstances) {
docker image rm bitwarden-patch docker stop $instance
docker rm $instance
}
$oldinstances = docker image ls bitwarden-patched --format '{{.ID}}'
foreach ($instance in $oldinstances) {
docker image rm $instance
}
# remove old extract containers
$oldinstances = docker container ps --all -f Name=bitwarden-extract --format '{{.ID}}'
foreach ($instance in $oldinstances) {
docker stop $instance
docker rm $instance
}
# start a new bitwarden instance so we can patch it # start a new bitwarden instance so we can patch it
$patchinstance = docker run -d --name bitwarden-patch ghcr.io/bitwarden/self-host:beta $patchinstance = docker run -d --name bitwarden-extract ghcr.io/bitwarden/self-host:beta
# create our temporary directory # create our temporary directory
New-item -ItemType Directory -Path $tempdirectory New-item -ItemType Directory -Path $tempdirectory
@ -71,15 +89,15 @@ foreach ($component in $components) {
docker cp $patchinstance`:/app/$component/Core.dll "$tempdirectory\$component\Core.dll" docker cp $patchinstance`:/app/$component/Core.dll "$tempdirectory\$component\Core.dll"
} }
# stop and remove our temporary container
docker stop bitwarden-extract
docker rm bitwarden-extract
# run bitBetter, this applies our patches to the required files # run bitBetter, this applies our patches to the required files
docker run -v "$tempdirectory`:/app/mount" --rm bitbetter/bitbetter docker run -v "$tempdirectory`:/app/mount" --rm bitbetter/bitbetter
# create a new image with the patched files # create a new image with the patched files
docker build . --tag bitwarden-patch --file "$pwd\src\bitBetter\Dockerfile-bitwarden-patch" docker build . --tag bitwarden-patched --file "$pwd\src\bitBetter\Dockerfile-bitwarden-patch"
# stop and remove our temporary container
docker stop bitwarden-patch
docker rm bitwarden-patch
# start all user requested instances # start all user requested instances
if (Test-Path -Path "$pwd\.servers\serverlist.txt" -PathType Leaf) { if (Test-Path -Path "$pwd\.servers\serverlist.txt" -PathType Leaf) {

View File

@ -20,8 +20,12 @@ if [ -f "$PWD/src/licenseGen/cert.pfx" ]; then
rm -f "$PWD/src/licenseGen/cert.pfx" rm -f "$PWD/src/licenseGen/cert.pfx"
fi fi
if [ -f "$PWD/src/bitBetter/cert.cert" ]; then if [ -f "$PWD/src/bitBetter/cert.cer" ]; then
rm -f "$PWD/src/bitBetter/cert.cert" rm -f "$PWD/src/bitBetter/cert.cer"
fi
if [ -f "$PWD/.keys/cert.cert" ]; then
mv "$PWD/.keys/cert.cert" "$PWD/.keys/cert.cer"
fi fi
# generate keys if none are available # generate keys if none are available
@ -30,16 +34,16 @@ if [ ! -d "$PWD/.keys" ]; then
fi fi
# copy the key to bitBetter # copy the key to bitBetter
cp -f "$PWD/.keys/cert.cert" "$PWD/src/bitBetter" cp -f "$PWD/.keys/cert.cer" "$PWD/src/bitBetter"
# build bitBetter and clean the source directory after # build bitBetter and clean the source directory after
docker build --no-cache -t bitbetter/bitbetter "$PWD/src/bitBetter" docker build --no-cache -t bitbetter/bitbetter "$PWD/src/bitBetter"
rm -f "$PWD/src/bitBetter/cert.cert" rm -f "$PWD/src/bitBetter/cert.cer"
# gather all running instances # gather all running instances, cannot run a wildcard filter on Ancestor= :(
OLDINSTANCES=$(docker container ps --all -f Name=bitwarden --format '{{.ID}}') OLDINSTANCES=$(docker container ps --all -f Name=bitwarden --format '{{.ID}}')
# stop all running instances # stop and remove all running instances
for INSTANCE in ${OLDINSTANCES[@]}; do for INSTANCE in ${OLDINSTANCES[@]}; do
docker stop $INSTANCE docker stop $INSTANCE
docker rm $INSTANCE docker rm $INSTANCE
@ -58,12 +62,25 @@ else
fi fi
# stop and remove previous existing patch(ed) container # stop and remove previous existing patch(ed) container
docker stop bitwarden-patch OLDINSTANCES=$(docker container ps --all -f Ancestor=bitwarden-patched --format '{{.ID}}')
docker rm bitwarden-patch for INSTANCE in ${OLDINSTANCES[@]}; do
docker image rm bitwarden-patch docker stop $INSTANCE
docker rm $INSTANCE
done
OLDINSTANCES=$(docker image ls bitwarden-patched --format '{{.ID}}')
for INSTANCE in ${OLDINSTANCES[@]}; do
docker image rm $INSTANCE
done
# remove old extract containers
OLDINSTANCES=$(docker container ps --all -f Name=bitwarden-extract --format '{{.ID}}')
for INSTANCE in ${OLDINSTANCES[@]}; do
docker stop $INSTANCE
docker rm $INSTANCE
done
# start a new bitwarden instance so we can patch it # start a new bitwarden instance so we can patch it
PATCHINSTANCE=$(docker run -d --name bitwarden-patch ghcr.io/bitwarden/self-host:beta) PATCHINSTANCE=$(docker run -d --name bitwarden-extract ghcr.io/bitwarden/self-host:beta)
# create our temporary directory # create our temporary directory
mkdir $TEMPDIRECTORY mkdir $TEMPDIRECTORY
@ -74,21 +91,21 @@ for COMPONENT in ${COMPONENTS[@]}; do
docker cp $PATCHINSTANCE:/app/$COMPONENT/Core.dll "$TEMPDIRECTORY/$COMPONENT/Core.dll" docker cp $PATCHINSTANCE:/app/$COMPONENT/Core.dll "$TEMPDIRECTORY/$COMPONENT/Core.dll"
done done
# stop and remove our temporary container
docker stop bitwarden-extract
docker rm bitwarden-extract
# run bitBetter, this applies our patches to the required files # run bitBetter, this applies our patches to the required files
docker run -v "$TEMPDIRECTORY:/app/mount" --rm bitbetter/bitbetter docker run -v "$TEMPDIRECTORY:/app/mount" --rm bitbetter/bitbetter
# create a new image with the patched files # create a new image with the patched files
docker build . --tag bitwarden-patch --file "$PWD/src/bitBetter/Dockerfile-bitwarden-patch" docker build . --tag bitwarden-patched --file "$PWD/src/bitBetter/Dockerfile-bitwarden-patch"
# stop and remove our temporary container
docker stop bitwarden-patch
docker rm bitwarden-patch
# start all user requested instances # start all user requested instances
if [ -f "$PWD/src/bitBetter/cert.cert" ]; then if [ -f "$PWD/src/bitBetter/cert.cer" ]; then
sed -i 's/\r$//' "$PWD/.servers/serverlist.txt" sed -i 's/\r$//' "$PWD/.servers/serverlist.txt"
cat "$PWD/.servers/serverlist.txt" | while read -r LINE; do cat "$PWD/.servers/serverlist.txt" | while read -r LINE; do
if [[ $LINE == "#*" ]] ; if [[ $LINE == "#*" ]]; then
bash -c "$LINE" bash -c "$LINE"
fi fi
done done

View File

@ -20,6 +20,6 @@ if (Test-Path "$pwd\.keys")
New-item -ItemType Directory -Path "$pwd\.keys" New-item -ItemType Directory -Path "$pwd\.keys"
# generate actual keys # generate actual keys
Invoke-Expression "& '$opensslbinary' req -x509 -newkey rsa:4096 -keyout `"$pwd\.keys\key.pem`" -out `"$pwd\.keys\cert.cert`" -days 36500 -subj '/CN=www.mydom.com/O=My Company Name LTD./C=US' -outform DER -passout pass:test" Invoke-Expression "& '$opensslbinary' req -x509 -newkey rsa:4096 -keyout `"$pwd\.keys\key.pem`" -out `"$pwd\.keys\cert.cer`" -days 36500 -subj '/CN=www.mydom.com/O=My Company Name LTD./C=US' -outform DER -passout pass:test"
Invoke-Expression "& '$opensslbinary' x509 -inform DER -in `"$pwd\.keys\cert.cert`" -out `"$pwd\.keys\cert.pem`"" Invoke-Expression "& '$opensslbinary' x509 -inform DER -in `"$pwd\.keys\cert.cer`" -out `"$pwd\.keys\cert.pem`""
Invoke-Expression "& '$opensslbinary' pkcs12 -export -out `"$pwd\.keys\cert.pfx`" -inkey `"$pwd\.keys\key.pem`" -in `"$pwd\.keys\cert.pem`" -passin pass:test -passout pass:test" Invoke-Expression "& '$opensslbinary' pkcs12 -export -out `"$pwd\.keys\cert.pfx`" -inkey `"$pwd\.keys\key.pem`" -in `"$pwd\.keys\cert.pem`" -passin pass:test -passout pass:test"

View File

@ -15,6 +15,6 @@ fi
mkdir "$DIR" mkdir "$DIR"
# Generate new keys # Generate new keys
openssl req -x509 -newkey rsa:4096 -keyout "$DIR/key.pem" -out "$DIR/cert.cert" -days 36500 -subj '/CN=www.mydom.com/O=My Company Name LTD./C=US' -outform DER -passout pass:test openssl req -x509 -newkey rsa:4096 -keyout "$DIR/key.pem" -out "$DIR/cert.cer" -days 36500 -subj '/CN=www.mydom.com/O=My Company Name LTD./C=US' -outform DER -passout pass:test
openssl x509 -inform DER -in "$DIR/cert.cert" -out "$DIR/cert.pem" openssl x509 -inform DER -in "$DIR/cert.cer" -out "$DIR/cert.pem"
openssl pkcs12 -export -out "$DIR/cert.pfx" -inkey "$DIR/key.pem" -in "$DIR/cert.pem" -passin pass:test -passout pass:test openssl pkcs12 -export -out "$DIR/cert.pfx" -inkey "$DIR/key.pem" -in "$DIR/cert.pem" -passin pass:test -passout pass:test

View File

@ -2,7 +2,7 @@ FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /bitBetter WORKDIR /bitBetter
COPY . /bitBetter COPY . /bitBetter
COPY cert.cert /app/ COPY cert.cer /app/
RUN dotnet restore RUN dotnet restore
RUN dotnet publish -c Release -o /app --no-restore RUN dotnet publish -c Release -o /app --no-restore

View File

@ -14,7 +14,7 @@ internal class Program
{ {
private static Int32 Main() private static Int32 Main()
{ {
const String certFile = "/app/cert.cert"; const String certFile = "/app/cert.cer";
String[] files = Directory.GetFiles("/app/mount", "Core.dll", SearchOption.AllDirectories); String[] files = Directory.GetFiles("/app/mount", "Core.dll", SearchOption.AllDirectories);
foreach (String file in files) foreach (String file in files)

View File

@ -12,4 +12,4 @@ FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app WORKDIR /app
COPY --from=build /app . COPY --from=build /app .
ENTRYPOINT ["dotnet", "/app/licenseGen.dll", "--cert=/app/cert.pfx", "--core=/app/Core.dll"] ENTRYPOINT ["dotnet", "/app/licenseGen.dll", "--cert=/app/cert.pfx", "--core=/app/Core.dll"]

View File

@ -27,7 +27,7 @@ internal class Program
{ {
Check(); Check();
Console.WriteLine("Interactive license mode..."); Console.WriteLine("Interactive license mode...");
while (licenseType == "") while (licenseType == "")
{ {
Console.WriteLine("What would you like to generate, a [u]ser license or an [o]rg license: "); Console.WriteLine("What would you like to generate, a [u]ser license or an [o]rg license: ");
@ -210,7 +210,7 @@ internal class Program
CommandArgument storage = config.Argument("Storage", "extra storage space in GB. Maximum is " + Int16.MaxValue + " (optional, default = max)"); CommandArgument storage = config.Argument("Storage", "extra storage space in GB. Maximum is " + Int16.MaxValue + " (optional, default = max)");
CommandArgument businessName = config.Argument("BusinessName", "name for the organization (optional)"); CommandArgument businessName = config.Argument("BusinessName", "name for the organization (optional)");
CommandArgument key = config.Argument("Key", "your key id (optional)"); CommandArgument key = config.Argument("Key", "your key id (optional)");
config.OnExecute(() => config.OnExecute(() =>
{ {
Check(); Check();
@ -431,8 +431,8 @@ internal class Program
Set(type, license, "BillingEmail", email); Set(type, license, "BillingEmail", email);
Set(type, license, "BusinessName", String.IsNullOrWhiteSpace(businessName) ? "BitBetter" : businessName); Set(type, license, "BusinessName", String.IsNullOrWhiteSpace(businessName) ? "BitBetter" : businessName);
Set(type, license, "Enabled", true); Set(type, license, "Enabled", true);
Set(type, license, "Plan", "Enterprise (Annually)"); Set(type, license, "Plan", "Enterprise (Annually)");
Set(type, license, "PlanType", Enum.Parse(planTypeEnum, "EnterpriseAnnually")); Set(type, license, "PlanType", Enum.Parse(planTypeEnum, "EnterpriseAnnually"));
Set(type, license, "Seats", Int32.MaxValue); Set(type, license, "Seats", Int32.MaxValue);
Set(type, license, "MaxCollections", Int16.MaxValue); Set(type, license, "MaxCollections", Int16.MaxValue);
Set(type, license, "UsePolicies", true); Set(type, license, "UsePolicies", true);
@ -446,26 +446,24 @@ internal class Program
Set(type, license, "Use2fa", true); Set(type, license, "Use2fa", true);
Set(type, license, "UseApi", true); Set(type, license, "UseApi", true);
Set(type, license, "UseResetPassword", true); Set(type, license, "UseResetPassword", true);
Set(type, license, "UseCustomPermissions", true);
Set(type, license, "MaxStorageGb", storage == 0 ? Int16.MaxValue : storage); Set(type, license, "MaxStorageGb", storage == 0 ? Int16.MaxValue : storage);
Set(type, license, "SelfHost", true); Set(type, license, "SelfHost", true);
Set(type, license, "UsersGetPremium", true); Set(type, license, "UsersGetPremium", true);
Set(type, license, "UseCustomPermissions", true);
Set(type, license, "Version", 16);
Set(type, license, "Issued", DateTime.UtcNow);
Set(type, license, "Refresh", DateTime.UtcNow.AddYears(100).AddMonths(-1));
Set(type, license, "Expires", DateTime.UtcNow.AddYears(100));
Set(type, license, "ExpirationWithoutGracePeriod", DateTime.UtcNow.AddYears(100));
Set(type, license, "UsePasswordManager", true); Set(type, license, "UsePasswordManager", true);
Set(type, license, "UseSecretsManager", true); Set(type, license, "UseSecretsManager", true);
Set(type, license, "SmSeats", Int32.MaxValue); Set(type, license, "SmSeats", Int32.MaxValue);
Set(type, license, "SmServiceAccounts", Int32.MaxValue); Set(type, license, "SmServiceAccounts", Int32.MaxValue);
Set(type, license, "Version", 15); //This is set to 15 to use AllowAdminAccessToAllCollectionItems can be changed to 13 to just use Secrets Manager Set(type, license, "UseRiskInsights", true);
Set(type, license, "Issued", DateTime.UtcNow); Set(type, license, "LimitCollectionCreationDeletion", true);
Set(type, license, "Refresh", DateTime.UtcNow.AddYears(100).AddMonths(-1)); Set(type, license, "AllowAdminAccessToAllCollectionItems", true);
Set(type, license, "Expires", DateTime.UtcNow.AddYears(100));
Set(type, license, "Trial", false); Set(type, license, "Trial", false);
Set(type, license, "LicenseType", Enum.Parse(licenseTypeEnum, "Organization")); Set(type, license, "LicenseType", Enum.Parse(licenseTypeEnum, "Organization"));
Set(type, license, "LimitCollectionCreationDeletion", true); //This will be used in the new version of BitWarden but can be applied now
Set(type, license, "AllowAdminAccessToAllCollectionItems", true);
Set(type, license, "UseRiskInsights", true);
Set(type, license, "UseOrganizationDomains", true);
Set(type, license, "UseAdminSponsoredFamilies", true);
Set(type, license, "UseRiskInsights", true);
Set(type, license, "UseOrganizationDomains", true); Set(type, license, "UseOrganizationDomains", true);
Set(type, license, "UseAdminSponsoredFamilies", true); Set(type, license, "UseAdminSponsoredFamilies", true);
Set(type, license, "Hash", Convert.ToBase64String((Byte[])computeHash.Invoke(license, [])!)); Set(type, license, "Hash", Convert.ToBase64String((Byte[])computeHash.Invoke(license, [])!));