-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexport_bw_vault.ps1
210 lines (168 loc) · 7 KB
/
export_bw_vault.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# Constants
$timestamp = Get-Date -Format "yyyyMMddHHmmss"
$TaskName = "BackupBWVaultTask"
$ScriptPath = "$PSCommandPath"
# Define the Desktop path and ExportPath
$DesktopPath = [System.Environment]::GetFolderPath("Desktop")
$ExportFolder = Join-Path -Path $DesktopPath -ChildPath "bitwarden-exports"
$ExportPath = Join-Path -Path $ExportFolder -ChildPath "bitwarden_encrypted_export_$($timestamp).json"
# Ensure the export folder exists
if (-not (Test-Path -Path $ExportFolder)) {
try {
New-Item -ItemType Directory -Path $ExportFolder -Force | Out-Null
Write-Output "Folder '$ExportFolder' created successfully."
} catch {
Write-Error "Failed to create folder '$ExportFolder'. Error: $_"
exit 1
}
}
# Function to check and install a module if not present
function EnsureModule {
param (
[string]$ModuleName # Name of the module to check/install
)
if (-not (Get-Module -ListAvailable -Name $ModuleName)) {
Write-Output "Module '$ModuleName' not found. Installing it now"
try {
Install-Module -Name $ModuleName -Force
Write-Output "Module '$ModuleName' installed successfully"
} catch {
Write-Error "Failed to install module '$ModuleName'. Error: $_"
exit 1
}
}
# Import the module
try {
Import-Module -Name $ModuleName -ErrorAction Stop
} catch {
Write-Error "Failed to import module '$ModuleName'. Error: $_"
exit 1
}
}
# Ensure CredentialManager module is installed and imported
EnsureModule -ModuleName "CredentialManager"
# Check if Bitwarden CLI is installed
if (-not (Get-Command "bw" -ErrorAction SilentlyContinue)) {
throw "Bitwarden CLI is not installed. Please install it"
}
# Function to create a scheduled task for daily execution at midnight
function EnsureTaskScheduler {
param (
[string]$TaskName,
[string]$ScriptPath
)
# Check if the task already exists
$taskExists = Get-ScheduledTask | Where-Object { $_.TaskName -eq $TaskName }
if ($null -eq $taskExists) {
Write-Output "Creating scheduled task '$TaskName'."
try {
# Create a new task trigger for daily execution at midnight
$Trigger = New-ScheduledTaskTrigger -Daily -At 2:00PM
# Create the action to run the script with PowerShell
$Action = New-ScheduledTaskAction `
-Execute "pwsh.exe" `
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$ScriptPath`""
# Create a Settings object for storing Task specific settings
$Settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-StartWhenAvailable `
-DontStopIfGoingOnBatteries `
-WakeToRun `
-MultipleInstances IgnoreNew
# Register the scheduled task
Register-ScheduledTask `
-TaskName $TaskName `
-Settings $Settings `
-Trigger $Trigger `
-Action $Action `
-Description "Backup Bitwarden Vault"
Write-Output "Scheduled task '$TaskName' created successfully"
} catch {
Write-Error "Failed to create scheduled task '$TaskName'. Error: $_"
exit 1
}
} else {
Write-Output "Scheduled task '$TaskName' already exists"
}
}
# Ensure the task scheduler is set up
EnsureTaskScheduler -TaskName $TaskName -ScriptPath $ScriptPath
# Convert a SecureString to Plain Text
function Convert-SecureStringToPlainText {
param (
[System.Security.SecureString]$SecureString
)
try {
# Convert the SecureString to plain text
return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto(
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
)
} catch {
# Handle any exceptions during the conversion
Write-Error "An error occurred while converting the SecureString to plain text: $_"
exit 1
}
}
# Set the converted plain text secret as an environment variable
function Set-CredentialAsEnvVariable {
param (
[PSCredential]$Credential, # Credential object containing the target name
[string]$EnvVariableName # Name of the environment variable to set
)
# Convert the secure string password to plain text
$PlainTextPassword = Convert-SecureStringToPlainText -SecureString $Credential.Password
# Set the plain text password as an environment variable
[Environment]::SetEnvironmentVariable($EnvVariableName, $PlainTextPassword, "Process")
}
# Function to retrieve and validate a credential from Credential Manager
function Get-AndValidateCredential {
param (
[string]$ExpectedSecretName # The expected name of the credential
)
# Retrieve the credential from Credential Manager
$Credential = Get-StoredCredential -Target $ExpectedSecretName
# Validate the credential
if ($null -eq $Credential) {
Write-Error "Generic secret '$ExpectedSecretName' is null or was not found in the Credential Manager"
exit 1
}
# Return the credential if validation passes
return $Credential
}
# Login to BW server, Authenticate to BW vault and finally export the
# encrypted JSON file
function BackupBWVault {
# Ensure session logout before starting it up
bw logout
# Get the current vault server
Write-Output "`n"
$ServerOutput = bw config server
bw config server $ServerOutput
# Login
Write-Output "`n"
bw login --apikey
# Get the session token, needed for vault unlock
$SessionToken = bw unlock --passwordenv BW_MASTER_PASSWORD --raw
# Export vault with the --password parameter specified
# This allows to import the file into a different Bitwarden account
# File will be encrypted using that password instead of master password
Write-Output "`n"
bw export `
--format encrypted_json `
--session $SessionToken `
--password "$Env:BW_ENC_PASSWORD" `
--output $ExportPath
# Logout
Write-Output "`n"
bw logout
Write-Output "`n"
}
# Retrieve credential from Credentials Manager, then convert it to plain text
# and finally set it as environment variable for the process
Set-CredentialAsEnvVariable -Credential (Get-AndValidateCredential -ExpectedSecretName "BW_CLIENTID") -EnvVariableName "BW_CLIENTID"
Set-CredentialAsEnvVariable -Credential (Get-AndValidateCredential -ExpectedSecretName "BW_CLIENTSECRET") -EnvVariableName "BW_CLIENTSECRET"
Set-CredentialAsEnvVariable -Credential (Get-AndValidateCredential -ExpectedSecretName "BW_ENC_PASSWORD") -EnvVariableName "BW_ENC_PASSWORD"
Set-CredentialAsEnvVariable -Credential (Get-AndValidateCredential -ExpectedSecretName "BW_MASTER_PASSWORD") -EnvVariableName "BW_MASTER_PASSWORD"
Write-Output "Environment variables set successfully"
# Start backup of Bitwarden vault by exporting the encrypted JSON file
BackupBWVault