Skip to content

Commit

Permalink
feat: backup organizations (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Quadrubo authored Jul 9, 2024
1 parent 3db5acc commit 45fd839
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 14 deletions.
1 change: 1 addition & 0 deletions .env.dev.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ BW_SERVER=https://vault.bitwarden.com

BACKUP_FORMAT=encrypted_json
BACKUP_PASSWORD=password
BACKUP_ORGANIZATIONS=

CRON_SCHEDULE="* * * * *"
3 changes: 2 additions & 1 deletion .env.docker.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ BW_CLIENT_ID=
BW_CLIENT_SECRET=
BW_MASTER_PASSWORD=

BACKUP_PASSWORD=
BACKUP_PASSWORD=
BACKUP_ORGANIZATIONS=
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,19 @@ Make sure to use an up to date image tag.

Environment variables:

| Variable | Example | Description |
| ------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| BACKUP_PATH | /backup | The path to store backups in **inside** the container. Shouldn't change, instead change the volume mapping to access your backups. |
| BW_BINARY | /usr/local/bin/bw | The path to the Bitwarden CLI binary. Shouldn't need to change. |
| BW_CLIENT_ID | user.abcdefgh-1234-abcd-1234-abcdefghijkl | Your Bitwarden client id. Retrieve from [https://vault.bitwarden.com](https://vault.bitwarden.com). |
| BW_CLIENT_SECRET | abcdefghijklmnopqrstuvwxyzabcd | Your Bitwarden client secret. Retrieve from [https://vault.bitwarden.com](https://vault.bitwarden.com). |
| BW_SERVER | https://vault.bitwarden.com | The bitwarden server to use. Replace with your selfhosted server or use the EU server [https://vault.bitwarden.eu](https://vault.bitwarden.eu). |
| BW_MASTER_PASSWORD | your-extremely-secure-master-password | Your Bitwarden master password. |
| CRON_SCHEDULE | 0 1 \* \* \* | The cron schedule on which to run the backup. Use [https://crontab.guru/](https://crontab.guru/) for help generating one. |
| TZ | Europe/Berlin | Your timezone. Needed for the cron job to work correctly. Here is a [List of valid timezones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). |
| Variable | Example | Description |
| -------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BACKUP_PATH | /backup | The path to store backups in **inside** the container. Shouldn't change, instead change the volume mapping to access your backups. |
| BW_BINARY | /usr/local/bin/bw | The path to the Bitwarden CLI binary. Shouldn't need to change. |
| BW_CLIENT_ID | user.abcdefgh-1234-abcd-1234-abcdefghijkl | Your Bitwarden client id. Retrieve from [https://vault.bitwarden.com](https://vault.bitwarden.com). |
| BW_CLIENT_SECRET | abcdefghijklmnopqrstuvwxyzabcd | Your Bitwarden client secret. Retrieve from [https://vault.bitwarden.com](https://vault.bitwarden.com). |
| BW_MASTER_PASSWORD | your-extremely-secure-master-password | Your Bitwarden master password. |
| BW_SERVER | https://vault.bitwarden.com | The bitwarden server to use. Replace with your selfhosted server or use the EU server [https://vault.bitwarden.eu](https://vault.bitwarden.eu). |
| BACKUP_FORMAT | encrypted_json | The format of the backup. See the [Export command](https://bitwarden.com/help/cli/#export) for more details. |
| BACKUP_PASSWORD | your-backup-encryption-password | The password to encrypt the backup with. Only works if you use `encrypted_json` as your `BACKUP_FORMAT`. If no password is chosen your account encryption key will be used. |
| BACKUP_ORGANIZATIONS | organization_id_1,organization_id_2 | A comma delimted list of organization ids. These will also be backed up. |
| CRON_SCHEDULE | 0 1 \* \* \* | The cron schedule on which to run the backup. Use [https://crontab.guru/](https://crontab.guru/) for help generating one. |
| TZ | Europe/Berlin | Your timezone. Needed for the cron job to work correctly. Here is a [List of valid timezones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). |

```yml
services:
Expand All @@ -41,6 +44,7 @@ services:
# Backups
- BACKUP_FORMAT=encrypted_json
- BACKUP_PASSWORD=your-backup-encryption-password
- BACKUP_ORGANIZATIONS=abcdefgh-1234-abcd-1234-abcdefghijkl,12345667-abcd-1234-abcd-123456789012
# Cron
- CRON_SCHEDULE=0 1 * * *
# Time
Expand Down Expand Up @@ -80,6 +84,7 @@ BW_CLIENT_SECRET="abcdefghijklmnopqrstuvwxyzabcd"
BW_MASTER_PASSWORD="your-extremely-secure-master-password"

BACKUP_PASSWORD=password
BACKUP_ORGANIZATIONS=abcdefgh-1234-abcd-1234-abcdefghijkl,12345667-abcd-1234-abcd-123456789012
```

Execute the program.
Expand Down Expand Up @@ -107,6 +112,7 @@ BW_CLIENT_SECRET="abcdefghijklmnopqrstuvwxyzabcd"
BW_MASTER_PASSWORD="your-extremely-secure-master-password"

BACKUP_PASSWORD=password
BACKUP_ORGANIZATIONS=abcdefgh-1234-abcd-1234-abcdefghijkl,12345667-abcd-1234-abcd-123456789012
```

Start the container.
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ services:
# Backups
- BACKUP_FORMAT=${BACKUP_FORMAT:-encrypted_json}
- BACKUP_PASSWORD=${BACKUP_PASSWORD}
- BACKUP_ORGANIZATIONS=${BACKUP_ORGANIZATIONS}
# Cron
- CRON_SCHEDULE=${CRON_SCHEDULE:-0 1 * * *}
volumes:
Expand Down
7 changes: 5 additions & 2 deletions src/bitwarden.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,13 @@ def unlock(self, master_password):

self.session_key = session_key

def export(self, output, cfg_format, password, organization_id = None):
def export(self, output, cfg_format, password = None, organization_id = None):
my_env = self.get_session_environment()

export_command = [self.binary_path, 'export', '--output', output, '--format', cfg_format, '--password', password]
export_command = [self.binary_path, 'export', '--output', output, '--format', cfg_format]

if password:
export_command += ['--password', password]

if organization_id:
export_command += ['--organizationid', organization_id]
Expand Down
22 changes: 21 additions & 1 deletion src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,29 @@
bitwarden.login(CLIENT_ID, CLIENT_SECRET)
bitwarden.unlock(MASTER_PASSWORD)

def generate_output_path(path, current_time, organization_id = None):
output_path = BACKUP_PATH + "/bitwarden-encrypted_" + current_time

if organization_id:
output_path += "_" + organization_id

output_path += ".json"

return output_path

current_time = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
output = BACKUP_PATH + "/bitwarden-encrypted-" + current_time + ".json"

bitwarden.export(output, BACKUP_FORMAT, BACKUP_PASSWORD)
bitwarden.export(generate_output_path(BACKUP_PATH, current_time), BACKUP_FORMAT, BACKUP_PASSWORD)

BACKUP_ORGANIZATIONS = os.getenv("BACKUP_ORGANIZATIONS").strip()

if (BACKUP_ORGANIZATIONS):
BACKUP_ORGANIZATIONS = BACKUP_ORGANIZATIONS.split(",")
else:
BACKUP_ORGANIZATIONS = []

for organization_id in BACKUP_ORGANIZATIONS:
bitwarden.export(generate_output_path(BACKUP_PATH, current_time, organization_id), BACKUP_FORMAT, BACKUP_PASSWORD, organization_id)

bitwarden.logout()

0 comments on commit 45fd839

Please sign in to comment.