├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── KeepassPluginVersion.txt ├── LICENSE ├── README.md ├── VaultSyncPlugin.IntegrationTests ├── Properties │ └── AssemblyInfo.cs ├── SynchronousVaultClientTests.cs ├── TestSettings.cs ├── VaultSyncPlugin.IntegrationTests.csproj ├── VaultSyncPlugin.IntegrationTests.licenseheader ├── app.config └── packages.config ├── VaultSyncPlugin.sln ├── VaultSyncPlugin ├── PlgxConfig.xml ├── Properties │ └── AssemblyInfo.cs ├── Secret.cs ├── SecretFolder.cs ├── SecretKeys.cs ├── SyncStatus.cs ├── SyncStatusForm.Designer.cs ├── SyncStatusForm.cs ├── SyncStatusForm.resx ├── SynchronousVaultClient.cs ├── VaultSyncPlugin.csproj ├── VaultSyncPlugin.licenseheader ├── VaultSyncPluginExt.cs ├── app.config └── packages.config ├── build_plgx.bat └── external └── Readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | 263 | # Specific ignore 264 | /external/keepass 265 | /VaultSyncPlugin.IntegrationTests/secrets.* 266 | /exclude/** -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /KeepassPluginVersion.txt: -------------------------------------------------------------------------------- 1 | : 2 | VaultSyncPlugin:1.1.1 3 | : -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Developped at Orange Business Services under LGPL-2.1. See [LICENSE](LICENSE). 4 | 5 | # How to use 6 | 7 | ## Pre-requisites 8 | 9 | This plugin requires .NET Framework 4.6 minimum, you can download the latest version from [Microsoft website](https://dotnet.microsoft.com/download). 10 | 11 | For Linux users, you need to install the latest `mono-complete` package. 12 | 13 | ## Usage 14 | 15 | 1. Download the [latest PLGX file](https://github.com/Orange-OpenSource/keepass-vault-sync-plugin/releases) and copy it in the KeePass installation folder, in plugins directory 16 | * For Windows it's in `C:\Program Files (x86)\KeePass Password Safe 2\Plugins` 17 | * For Linux it's in `/usr/lib/keepass2/Plugins` 18 | 2. Open your database 19 | 3. Create an entry with name starting with `vault`. For example: `vault-personal-folder` 20 | * Username is the username used to authenticate on Vault 21 | * Password is the password used to authenticate on Vault 22 | * URL is the Vault Backend URL (port included). For example: `https://local-vault:8200` 23 | * In Advanced tab add the following String fields: 24 | * `auth` field contains the auth path. For basic Vault authentication, it should be `username`. For LDAP authentication, it should be the LDAP name. 25 | * `path` field contains the path to synchronize. Any secret in this path will be synchronized, recursively. 26 | 4. Click on *Tools -> Synchronize Vault entries*. Synchronization may take a while, since Vault API is really not designed for this kind of use case. 27 | 5. A folder named with your entry name followed by the date and time timestamp will be created. If the entry was previously synchronized, the previous folder won't be deleted. 28 | 6. You can save your database. The plugin won't do it for you. 29 | 7. For now, there is no error message in case of issue. Only the lack of synchronization will be a symptom of issue. It may be improved in future versions. If needed. 30 | 31 | # Why these release names? 32 | 33 | * Because release themes are cheap but are a small pleasure in release process 34 | * Because it helps structuring releases 35 | * Because why not? 36 | * Because [Vault](https://en.wikipedia.org/wiki/Vault_\(comics\)), so [Release Theme](https://fr.wikipedia.org/wiki/Cat%C3%A9gorie:Super-vilain_Marvel) 37 | 38 | # How to build 39 | 40 | 1. Get the dependencies listed [here](external/Readme.md) 41 | 1. Modify the version in both AssemblyInfo and KeepassPluginVersion.txt 42 | 1. Build the solution, targetting `Release PLGX` 43 | 1. The file is generated in VaultSyncPlugin/bin/ReleasePlgx/VaultSyncPlugin.plgx 44 | 45 | For some reason, the execution of plgxtool can fail. The quick workaround consists in running the command directly in bash from the VaultSyncPlugin project folder. 46 | 47 | # How to test 48 | 49 | This part could be improved. For now, there are is one integration test, with minimal assertion. 50 | On first run, a `secrets.json` file will be generated, containing the needed values to be modified for the test to run. 51 | Since it contains sensitive data, this file is gitignored. But you should check regularly that it's not committed. 52 | 53 | # Library used 54 | 55 | * [KeePass](https://keepass.info) for plugin API (GPL-2.0) 56 | * [Vault.NET](https://github.com/Chatham/Vault.NET) for Vault API C# wrapping (MIT) 57 | * [PlgxTool](https://github.com/dlech/KeePassPluginDevTools) for PLGX generation (GPL-2.0) 58 | * [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) as dependency of Vault.NET (MIT) 59 | * A bunch of .NET extension libraries, as dependencies of dependencies, from .NET framework 4.6 or Microsoft libraries on nuget (Apache 2 and MIT, depends on the lib/framework) 60 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VaultSyncPlugin.IntegrationTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("FT")] 12 | [assembly: AssemblyProduct("VaultSyncPlugin.IntegrationTests")] 13 | [assembly: AssemblyCopyright("Copyright © FT 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("713fbbee-a3d6-4866-ab1d-5c64d2cb048c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/SynchronousVaultClientTests.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using Newtonsoft.Json; 22 | using NFluent; 23 | using NUnit.Framework; 24 | using System; 25 | using System.Collections.Generic; 26 | using System.IO; 27 | using System.Linq; 28 | using System.Net; 29 | 30 | namespace VaultSyncPlugin.IntegrationTests 31 | { 32 | [TestFixture] 33 | public class SynchronousVaultClientTests 34 | { 35 | private TestSettings settings; 36 | private SyncStatus syncStatus; 37 | 38 | [SetUp] 39 | public void Setup() 40 | { 41 | var file = Path.Combine(TestContext.CurrentContext.TestDirectory, @"..\..\secrets.json"); 42 | 43 | if (File.Exists(file)) 44 | { 45 | var configuration = File.ReadAllText(file); 46 | this.settings = JsonConvert.DeserializeObject(configuration); 47 | this.syncStatus = new SyncStatus(); 48 | } 49 | else 50 | { 51 | var defaultSettings = new TestSettings 52 | { 53 | VaultUrl = "http://localhost:8200", 54 | AuthPath = "userpass", 55 | Path = "my-secrets/", 56 | User = "user", 57 | Password = "password", 58 | }; 59 | 60 | var content = JsonConvert.SerializeObject(defaultSettings); 61 | File.WriteAllText(file, content); 62 | 63 | Assert.Fail(@"You need to update your Vault data in secrets.json. It WON'T be commited to git (but you should check anyway)."); 64 | } 65 | } 66 | 67 | [Test] 68 | public void Top_level_access_should_be_OK_by_credentials() 69 | { 70 | var client = new SynchronousVaultClient(new Uri(this.settings.VaultUrl), this.settings.AuthPath, this.settings.User, this.settings.Password, this.syncStatus); 71 | SecretFolder structure; 72 | try 73 | { 74 | structure = client.GetSecrets(this.settings.Path).Result; 75 | Check.That(structure.Folders.Count()).IsStrictlyGreaterThan(0); 76 | Check.That(structure.Secrets.Count()).IsStrictlyGreaterThan(0); 77 | } 78 | catch (Exception) 79 | { 80 | Assert.Fail(@"Access failed. You should check that your credentials are valid."); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/TestSettings.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | namespace VaultSyncPlugin.IntegrationTests 22 | { 23 | /// 24 | /// Test settings 25 | /// 26 | internal class TestSettings 27 | { 28 | /// 29 | /// Vault URL. Base URL of the backend, without any path 30 | /// 31 | public string VaultUrl { get; set; } 32 | 33 | /// 34 | /// Username for auth 35 | /// 36 | public string User { get; set; } 37 | 38 | /// 39 | /// Password for auth 40 | /// 41 | public string Password { get; set; } 42 | 43 | /// 44 | /// Path for auth. May be 'username' for Vault auth, or the LDAP name for LDAP auth 45 | /// 46 | public string AuthPath { get; set; } 47 | 48 | /// 49 | /// The path to get secrets structure from. 50 | /// 51 | public string Path { get; set; } 52 | } 53 | } -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/VaultSyncPlugin.IntegrationTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Debug 8 | AnyCPU 9 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C} 10 | Library 11 | Properties 12 | VaultSyncPlugin.IntegrationTests 13 | VaultSyncPlugin.IntegrationTests 14 | v4.6 15 | 512 16 | 17 | 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | bin\Release PLGX\ 39 | TRACE 40 | true 41 | pdbonly 42 | AnyCPU 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | 46 | 47 | 48 | ..\packages\Microsoft.Extensions.DependencyInjection.1.1.1\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll 49 | 50 | 51 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll 52 | 53 | 54 | ..\packages\Microsoft.Extensions.Options.1.1.1\lib\netstandard1.0\Microsoft.Extensions.Options.dll 55 | 56 | 57 | ..\packages\Microsoft.Extensions.Primitives.1.1.1\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll 58 | 59 | 60 | ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll 61 | 62 | 63 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 64 | 65 | 66 | ..\packages\NFluent.2.4.0\lib\net45\NFluent.dll 67 | 68 | 69 | ..\packages\NUnit.3.11.0\lib\net45\nunit.framework.dll 70 | 71 | 72 | 73 | ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll 74 | 75 | 76 | 77 | ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll 78 | 79 | 80 | 81 | ..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll 82 | 83 | 84 | ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll 85 | 86 | 87 | ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll 88 | 89 | 90 | 91 | ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll 92 | 93 | 94 | ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll 95 | 96 | 97 | ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll 98 | 99 | 100 | ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll 101 | 102 | 103 | ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll 104 | 105 | 106 | 107 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll 108 | 109 | 110 | ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll 111 | 112 | 113 | ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net46\System.Security.Cryptography.Algorithms.dll 114 | 115 | 116 | ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll 117 | 118 | 119 | ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll 120 | 121 | 122 | ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net46\System.Security.Cryptography.X509Certificates.dll 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll 132 | 133 | 134 | ..\packages\Vault.0.9.1.3\lib\net451\Vault.dll 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | {4cb007ff-21f1-499c-bf47-0a5ad1f8de64} 153 | VaultSyncPlugin 154 | 155 | 156 | 157 | 158 | 159 | Ce projet fait référence à des packages NuGet qui sont manquants sur cet ordinateur. Utilisez l'option de restauration des packages NuGet pour les télécharger. Pour plus d'informations, consultez http://go.microsoft.com/fwlink/?LinkID=322105. Le fichier manquant est : {0}. 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/VaultSyncPlugin.IntegrationTests.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: designer.cs generated.cs 2 | extensions: .cs .cpp .h 3 | // Keepass Vault Sync Plugin 4 | // Copyright (C) 2018 Orange Business Services 5 | // 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Lesser General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2.1 of the License, or (at your option) any later version. 10 | // 11 | // This library is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | // Lesser General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU Lesser General Public 17 | // License along with this library; if not, write to the Free Software 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 | // USA 20 | // 21 | 22 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/app.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /VaultSyncPlugin.IntegrationTests/packages.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /VaultSyncPlugin.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31019.35 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VaultSyncPlugin", "VaultSyncPlugin\VaultSyncPlugin.csproj", "{4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VaultSyncPlugin.IntegrationTests", "VaultSyncPlugin.IntegrationTests\VaultSyncPlugin.IntegrationTests.csproj", "{713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{0ED5E318-B407-4D80-8030-E0EEF3D67CC4}" 11 | ProjectSection(SolutionItems) = preProject 12 | .gitattributes = .gitattributes 13 | .gitignore = .gitignore 14 | build_plgx.bat = build_plgx.bat 15 | KeepassPluginVersion.txt = KeepassPluginVersion.txt 16 | LICENSE = LICENSE 17 | README.md = README.md 18 | EndProjectSection 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release PLGX|Any CPU = Release PLGX|Any CPU 24 | Release|Any CPU = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Release PLGX|Any CPU.ActiveCfg = Release PLGX|Any CPU 30 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Release PLGX|Any CPU.Build.0 = Release PLGX|Any CPU 31 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}.Release PLGX|Any CPU.ActiveCfg = Release PLGX|Any CPU 36 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {713FBBEE-A3D6-4866-AB1D-5C64D2CB048C}.Release|Any CPU.Build.0 = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | GlobalSection(ExtensibilityGlobals) = postSolution 43 | SolutionGuid = {1C9A9223-4CC3-463F-803C-7C9180C70ECD} 44 | EndGlobalSection 45 | EndGlobal 46 | -------------------------------------------------------------------------------- /VaultSyncPlugin/PlgxConfig.xml: -------------------------------------------------------------------------------- 1 | 2.194.0 -------------------------------------------------------------------------------- /VaultSyncPlugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("VaultSyncPlugin")] 9 | [assembly: AssemblyDescription("Synchronizes Vault secrets in the local database. Licensed under LGPL-2.1")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Orange Application for Business")] 12 | [assembly: AssemblyProduct("KeePass Plugin")] 13 | [assembly: AssemblyCopyright("Copyright © Orange Business Services 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4cb007ff-21f1-499c-bf47-0a5ad1f8de64")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.1.1.0")] 36 | [assembly: AssemblyFileVersion("1.1.1.0")] 37 | -------------------------------------------------------------------------------- /VaultSyncPlugin/Secret.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using System.Collections.Generic; 22 | 23 | namespace VaultSyncPlugin 24 | { 25 | /// 26 | /// Does it really need comments? Self explained POCO. 27 | /// 28 | public class Secret 29 | { 30 | public Secret(string name, string user, string password, Dictionary content) 31 | { 32 | this.Name = name; 33 | this.User = user; 34 | this.Password = password; 35 | this.Content = content; 36 | } 37 | 38 | public string Name { get; private set; } 39 | public string User { get; private set; } 40 | public string Password { get; private set; } 41 | public Dictionary Content { get; private set; } 42 | 43 | public string Url { get; set; } 44 | } 45 | } -------------------------------------------------------------------------------- /VaultSyncPlugin/SecretFolder.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using System.Collections; 22 | using System.Collections.Generic; 23 | 24 | namespace VaultSyncPlugin 25 | { 26 | /// 27 | /// Does it really need comments? Self explained POCO. 28 | /// 29 | public class SecretFolder 30 | { 31 | private List folders = new List(); 32 | private List secrets = new List(); 33 | 34 | public SecretFolder(string name) 35 | { 36 | this.Name = name; 37 | } 38 | 39 | public string Name { get; private set; } 40 | 41 | public IEnumerable Folders 42 | { 43 | get { return this.folders; } 44 | } 45 | 46 | public IEnumerable Secrets 47 | { 48 | get { return this.secrets; } 49 | } 50 | 51 | /// 52 | /// Adds a sub folder in the folder 53 | /// 54 | /// The folder 55 | public void AddFolder(SecretFolder folder) 56 | { 57 | this.folders.Add(folder); 58 | } 59 | 60 | /// 61 | /// Adds a secret in the folder 62 | /// 63 | /// The secret 64 | public void AddSecret(Secret secret) 65 | { 66 | this.secrets.Add(secret); 67 | } 68 | 69 | /// 70 | /// Returns true if the path is a folder and not a secret. 71 | /// Vault API seems to return "/" at the end of the path 72 | /// in case of folder. 73 | /// 74 | /// The path 75 | /// True if is a folder 76 | public static bool IsFolder(string path) 77 | { 78 | return path.EndsWith("/"); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /VaultSyncPlugin/SecretKeys.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using System.Collections; 22 | using System.Collections.Generic; 23 | 24 | namespace VaultSyncPlugin 25 | { 26 | /// 27 | /// Does it really need comments? Self explained POCO. 28 | /// 29 | public class SecretKeys 30 | { 31 | private IEnumerable keys = new List(); 32 | 33 | public SecretKeys(IEnumerable keys) 34 | { 35 | this.keys = keys; 36 | } 37 | 38 | public IEnumerable Keys 39 | { 40 | get { return this.keys; } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /VaultSyncPlugin/SyncStatus.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | using System; 21 | using System.Collections.Generic; 22 | using System.ComponentModel; 23 | using System.Linq; 24 | using System.Text; 25 | using System.Threading.Tasks; 26 | 27 | namespace VaultSyncPlugin 28 | { 29 | public class SyncStatus 30 | { 31 | public event EventHandler NewLog; 32 | 33 | public event EventHandler Started; 34 | 35 | public event EventHandler Ended; 36 | 37 | public void StartSync() 38 | { 39 | if (this.Started != null) 40 | { 41 | this.Started(this, new EventArgs()); 42 | } 43 | } 44 | 45 | public void StopSync() 46 | { 47 | if (this.Ended != null) 48 | { 49 | this.Ended(this, new EventArgs()); 50 | } 51 | } 52 | 53 | public void AddLog(string log) 54 | { 55 | if (this.NewLog != null) 56 | { 57 | this.NewLog(this, log); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /VaultSyncPlugin/SyncStatusForm.Designer.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Windows.Forms; 3 | 4 | namespace VaultSyncPlugin 5 | { 6 | partial class SyncStatusForm 7 | { 8 | /// 9 | /// Required designer variable. 10 | /// 11 | private System.ComponentModel.IContainer components = null; 12 | 13 | /// 14 | /// Clean up any resources being used. 15 | /// 16 | /// true if managed resources should be disposed; otherwise, false. 17 | protected override void Dispose(bool disposing) 18 | { 19 | if (disposing && (components != null)) 20 | { 21 | components.Dispose(); 22 | } 23 | base.Dispose(disposing); 24 | } 25 | 26 | #region Windows Form Designer generated code 27 | 28 | /// 29 | /// Required method for Designer support - do not modify 30 | /// the contents of this method with the code editor. 31 | /// 32 | private void InitializeComponent() 33 | { 34 | this.panel1 = new System.Windows.Forms.Panel(); 35 | this.progressBar = new System.Windows.Forms.ProgressBar(); 36 | this.logBox = new System.Windows.Forms.TextBox(); 37 | this.okButton = new System.Windows.Forms.Button(); 38 | this.panel1.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // panel1 42 | // 43 | this.panel1.Controls.Add(this.progressBar); 44 | this.panel1.Controls.Add(this.logBox); 45 | this.panel1.Controls.Add(this.okButton); 46 | this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; 47 | this.panel1.Location = new System.Drawing.Point(0, 0); 48 | this.panel1.Name = "panel1"; 49 | this.panel1.Size = new System.Drawing.Size(800, 450); 50 | this.panel1.TabIndex = 0; 51 | // 52 | // progressBar 53 | // 54 | this.progressBar.Location = new System.Drawing.Point(12, 12); 55 | this.progressBar.Name = "progressBar"; 56 | this.progressBar.Size = new System.Drawing.Size(776, 23); 57 | this.progressBar.TabIndex = 2; 58 | // 59 | // logBox 60 | // 61 | this.logBox.Location = new System.Drawing.Point(12, 41); 62 | this.logBox.Multiline = true; 63 | this.logBox.Name = "logBox"; 64 | this.logBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; 65 | this.logBox.Size = new System.Drawing.Size(776, 368); 66 | this.logBox.TabIndex = 1; 67 | // 68 | // okButton 69 | // 70 | this.okButton.Location = new System.Drawing.Point(713, 415); 71 | this.okButton.Name = "okButton"; 72 | this.okButton.Size = new System.Drawing.Size(75, 23); 73 | this.okButton.TabIndex = 0; 74 | this.okButton.Text = "OK"; 75 | this.okButton.UseVisualStyleBackColor = true; 76 | this.okButton.Click += new System.EventHandler(this.okButton_Click); 77 | // 78 | // SyncStatusForm 79 | // 80 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); 81 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 82 | this.ClientSize = new System.Drawing.Size(800, 450); 83 | this.Controls.Add(this.panel1); 84 | this.Name = "SyncStatusForm"; 85 | this.Text = "Vault Sync Status"; 86 | this.panel1.ResumeLayout(false); 87 | this.panel1.PerformLayout(); 88 | this.ResumeLayout(false); 89 | 90 | } 91 | 92 | #endregion 93 | 94 | private System.Windows.Forms.Panel panel1; 95 | private System.Windows.Forms.ProgressBar progressBar; 96 | private System.Windows.Forms.TextBox logBox; 97 | private System.Windows.Forms.Button okButton; 98 | } 99 | } -------------------------------------------------------------------------------- /VaultSyncPlugin/SyncStatusForm.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | using System; 21 | using System.Collections.Generic; 22 | using System.ComponentModel; 23 | using System.Data; 24 | using System.Drawing; 25 | using System.Linq; 26 | using System.Text; 27 | using System.Threading.Tasks; 28 | using System.Windows.Forms; 29 | 30 | namespace VaultSyncPlugin 31 | { 32 | public partial class SyncStatusForm : Form 33 | { 34 | private SyncStatus syncStatus; 35 | 36 | public SyncStatusForm(SyncStatus syncStatus) 37 | { 38 | this.syncStatus = syncStatus; 39 | InitializeComponent(); 40 | 41 | this.syncStatus.NewLog += SyncStatus_NewLog; 42 | this.syncStatus.Started += SyncStatus_Started; 43 | this.syncStatus.Ended += SyncStatus_Ended; 44 | 45 | this.progressBar.MarqueeAnimationSpeed = 30; 46 | } 47 | 48 | private void SyncStatus_NewLog(object sender, string log) 49 | { 50 | this.logBox.AppendText(log); 51 | this.logBox.AppendText(Environment.NewLine); 52 | } 53 | 54 | private void SyncStatus_Ended(object sender, EventArgs e) 55 | { 56 | this.progressBar.Invoke((MethodInvoker)delegate 57 | { 58 | this.progressBar.Style = ProgressBarStyle.Continuous; 59 | }); 60 | } 61 | 62 | private void SyncStatus_Started(object sender, EventArgs e) 63 | { 64 | this.progressBar.Invoke((MethodInvoker)delegate 65 | { 66 | this.progressBar.Style = ProgressBarStyle.Marquee; 67 | }); 68 | } 69 | 70 | private void okButton_Click(object sender, EventArgs e) 71 | { 72 | this.Hide(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /VaultSyncPlugin/SyncStatusForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 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 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /VaultSyncPlugin/SynchronousVaultClient.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using System; 22 | using System.Collections.Generic; 23 | using System.Linq; 24 | using System.Net; 25 | using System.Text; 26 | using System.Threading.Tasks; 27 | using Vault; 28 | using Vault.Models; 29 | using Vault.Models.Auth.UserPass; 30 | 31 | namespace VaultSyncPlugin 32 | { 33 | /// 34 | /// Synchronous wrapper vault client. 35 | /// 36 | public class SynchronousVaultClient 37 | { 38 | VaultClient client; 39 | private SyncStatus syncStatus; 40 | private Uri vaultUrl; 41 | private string authPath; 42 | private string vaultLogin; 43 | private string vaultPassword; 44 | private string token; 45 | 46 | /// 47 | /// Creates a client from credentials 48 | /// 49 | /// The Vault URL 50 | /// The Vault auth path. Can be userpass for standard auth method, or the LDAP path in case of LDAP auth. 51 | /// The login 52 | /// The password 53 | public SynchronousVaultClient(Uri vaultUrl, string authPath, string vaultLogin, string vaultPassword, SyncStatus syncStatus) 54 | { 55 | // Disable SSL checks, for self-signed certificates. 56 | // TODO could be a plugin setting 57 | System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo("en-US"); 58 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; 59 | ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; 60 | 61 | this.vaultUrl = vaultUrl; 62 | this.authPath = authPath; 63 | this.vaultLogin = vaultLogin; 64 | this.vaultPassword = vaultPassword; 65 | this.client = new VaultClient(vaultUrl); 66 | this.syncStatus = syncStatus; 67 | } 68 | 69 | /// 70 | /// Download the secrets from a path (following the '.../v1/secret/') 71 | /// 72 | /// The path. 73 | /// The secret tree structure. 74 | public async Task GetSecrets(string path) 75 | { 76 | var folder = new SecretFolder(this.GetLastFolder(path)); 77 | 78 | // Gets the list of secrets for this path 79 | SecretKeys keyList; 80 | try 81 | { 82 | keyList = await this.GetSecretList(path); 83 | } 84 | catch (VaultRequestException ex) 85 | { 86 | // May be connection issue, or forbidden. We just continue, but we store the error for future display 87 | this.syncStatus.AddLog(string.Format("Exception for {0}: {1}{2}{3}", path, ex.Message, Environment.NewLine, ex.StackTrace)); 88 | return folder; 89 | } 90 | 91 | if (keyList.Keys.Count() > 0) 92 | { 93 | this.syncStatus.AddLog(string.Format("{0} keys fetched in {1}", keyList.Keys.Count(), path)); 94 | } 95 | 96 | foreach (var key in keyList.Keys) 97 | { 98 | if (SecretFolder.IsFolder(key)) 99 | { 100 | // Resursive call 101 | folder.AddFolder(await this.GetSecrets(path + "/" + key)); 102 | } 103 | else 104 | { 105 | // Adds secret 106 | folder.AddSecret(this.GetSecret(path + "/" + key)); 107 | } 108 | } 109 | 110 | if (folder.Secrets.Count() > 0) 111 | { 112 | this.syncStatus.AddLog(string.Format("{0} secrets fetched in {1}", folder.Secrets.Count(), path)); 113 | } 114 | 115 | return folder; 116 | } 117 | 118 | /// 119 | /// Gets the secret list in a path. Contains folders and items. Only difference is folder is ending with a trailing '/'. 120 | /// 121 | /// The path (after .../v1/secret/') 122 | /// The secret list. 123 | private async Task GetSecretList(string path) 124 | { 125 | try 126 | { 127 | this.CheckToken(); 128 | return await Task.FromResult(new SecretKeys(client.Secret.List(path).Result.Data.Keys)); 129 | } 130 | catch (Exception ex) 131 | { 132 | // May be unauthorized access 133 | if (ex.InnerException.Message.Contains("status code Forbidden")) 134 | { 135 | this.syncStatus.AddLog(string.Format("Access to {0} forbidden", path)); 136 | } 137 | else 138 | { 139 | this.syncStatus.AddLog(string.Format("Exception for {0}: {1}{2}{3}", path, ex.InnerException.Message, Environment.NewLine, ex.InnerException.StackTrace)); 140 | } 141 | return new SecretKeys(new List()); 142 | } 143 | } 144 | 145 | /// 146 | /// Checks if the token is downloaded, or else download it. 147 | /// 148 | private void CheckToken() 149 | { 150 | if (string.IsNullOrEmpty(this.token)) 151 | { 152 | this.token = this.GetToken(this.authPath, this.vaultLogin, this.vaultPassword).Result; 153 | this.syncStatus.AddLog(string.Format("Authenticated with token {0}", this.token)); 154 | this.client.Token = this.token; 155 | } 156 | 157 | } 158 | 159 | /// 160 | /// Downloads the token 161 | /// 162 | /// The auth path 163 | /// The username 164 | /// The password 165 | /// 166 | private async Task GetToken(string authPath, string user, string password) 167 | { 168 | 169 | var loginRequest = new LoginRequest 170 | { 171 | Password = password 172 | }; 173 | 174 | this.syncStatus.AddLog(string.Format("Trying to authenticate to {0}{1} with user {2}", this.vaultUrl, authPath + "/login/", user)); 175 | 176 | try 177 | { 178 | return await Task.FromResult(client.Auth.Write(authPath + "/login/" + user, loginRequest).Result.Auth.ClientToken); 179 | } 180 | catch (Exception ex) 181 | { 182 | this.syncStatus.AddLog(string.Format("Error on authentication: {0}{1}{2}", ex.InnerException.Message, Environment.NewLine, ex.InnerException.StackTrace)); 183 | throw ex; 184 | } 185 | } 186 | 187 | /// 188 | /// Download a secret from a path 189 | /// 190 | /// 191 | /// 192 | private Secret GetSecret(string path) 193 | { 194 | Secret secret; 195 | 196 | try 197 | { 198 | var data = Task.FromResult(client.Secret.Read>(path).Result.Data).Result; 199 | secret = this.SecretFromDictionary(this.GetLastFolder(path), data); 200 | } 201 | catch (Exception ex) 202 | { 203 | // Creates the entry with the exception message. Could help analyzing when failing. 204 | this.syncStatus.AddLog(string.Format("Exception for {0}: {1}{2}{3}", path, ex.InnerException.Message, Environment.NewLine, ex.InnerException.StackTrace)); 205 | secret = new Secret(this.GetLastFolder(path), string.Empty, string.Empty, new Dictionary()); 206 | } 207 | 208 | return secret; 209 | } 210 | 211 | /// 212 | /// Creates a secret from a dictionary. Since Vault secrets are not structured, it can fail. In this case there's a message in the field. 213 | /// 214 | /// The secret name 215 | /// The data to create the secret from. 216 | /// 217 | private Secret SecretFromDictionary(string name, Dictionary data) 218 | { 219 | var user = this.UserFromDictionary(data); 220 | var password = this.PasswordFromDictionary(data); 221 | var url = this.UrlFromDictionary(data); 222 | var secret = new Secret(name, user, password, data); 223 | secret.Url = url; 224 | return secret; 225 | } 226 | 227 | /// 228 | /// Yes. That's the only thing we can do about that. 229 | /// 230 | /// The data to look up. 231 | /// The value, or error message if not found 232 | private string PasswordFromDictionary(Dictionary data) 233 | { 234 | string[] keyList = { "password", "pass", "passwd" }; 235 | string value; 236 | 237 | if (this.TryGetValue(keyList, data, out value)) 238 | { 239 | return value; 240 | } 241 | 242 | return "Password field not found"; 243 | } 244 | 245 | /// 246 | /// Yes. That's the only thing we can do about that. 247 | /// 248 | /// The data to look up. 249 | /// The value, or error message if not found 250 | private string UserFromDictionary(Dictionary data) 251 | { 252 | string[] keyList = { "login", "user", "username" }; 253 | string value; 254 | 255 | if (this.TryGetValue(keyList, data, out value)) 256 | { 257 | return value; 258 | } 259 | 260 | return "User field not found"; 261 | } 262 | 263 | /// 264 | /// Yes. That's the only thing we can do about that. 265 | /// 266 | /// The data to look up. 267 | /// The value, or error message if not found 268 | private string UrlFromDictionary(Dictionary data) 269 | { 270 | string[] keyList = { "url" }; 271 | string value; 272 | 273 | if (this.TryGetValue(keyList, data, out value)) 274 | { 275 | return value; 276 | } 277 | 278 | return string.Empty; 279 | } 280 | 281 | /// 282 | /// Helper method. Try to find a value from a list of potential keys. Case insensitive. 283 | /// 284 | /// The list of keys to use 285 | /// The dictionary to look up 286 | /// The value, if found. 287 | /// true if the value is found. 288 | private bool TryGetValue(string[] keyList, Dictionary data, out string value) 289 | { 290 | foreach (var key in keyList) 291 | { 292 | var item = data.FirstOrDefault(i => i.Key.ToLower().Equals(key)); 293 | if (!string.IsNullOrEmpty(item.Key)) 294 | { 295 | value = item.Value; 296 | return true; 297 | } 298 | } 299 | 300 | value = string.Empty; 301 | return false; 302 | } 303 | 304 | /// 305 | /// Get the last folder of a path 306 | /// 307 | /// The path 308 | /// The last folder 309 | private string GetLastFolder(string fullpath) 310 | { 311 | var name = fullpath; 312 | if (SecretFolder.IsFolder(name)) 313 | { 314 | // Remove the trailing / 315 | name = name.Substring(0, name.Length - 1); 316 | } 317 | 318 | return name.Substring(name.LastIndexOf("/") + 1); 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /VaultSyncPlugin/VaultSyncPlugin.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4CB007FF-21F1-499C-BF47-0A5AD1F8DE64} 8 | Library 9 | Properties 10 | VaultSyncPlugin 11 | VaultSyncPlugin 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | false 27 | 28 | 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | false 36 | 37 | 38 | bin\Release PLGX\ 39 | TRACE 40 | true 41 | AnyCPU 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | false 45 | 46 | 47 | 48 | ..\external\keepass\KeePass.exe 49 | 50 | 51 | ..\packages\Microsoft.Extensions.DependencyInjection.1.1.1\lib\netstandard1.1\Microsoft.Extensions.DependencyInjection.dll 52 | 53 | 54 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.1\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll 55 | 56 | 57 | ..\packages\Microsoft.Extensions.Options.1.1.1\lib\netstandard1.0\Microsoft.Extensions.Options.dll 58 | 59 | 60 | ..\packages\Microsoft.Extensions.Primitives.1.1.1\lib\netstandard1.0\Microsoft.Extensions.Primitives.dll 61 | 62 | 63 | ..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll 64 | 65 | 66 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 67 | 68 | 69 | 70 | ..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll 71 | 72 | 73 | 74 | ..\packages\System.Console.4.3.1\lib\net46\System.Console.dll 75 | 76 | 77 | 78 | ..\packages\System.Diagnostics.DiagnosticSource.4.5.1\lib\net46\System.Diagnostics.DiagnosticSource.dll 79 | 80 | 81 | 82 | ..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll 83 | 84 | 85 | ..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll 86 | 87 | 88 | 89 | ..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll 90 | 91 | 92 | ..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll 93 | 94 | 95 | ..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll 96 | 97 | 98 | ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll 99 | 100 | 101 | ..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll 102 | 103 | 104 | 105 | ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll 106 | 107 | 108 | ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll 109 | 110 | 111 | ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net46\System.Security.Cryptography.Algorithms.dll 112 | 113 | 114 | ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll 115 | 116 | 117 | ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll 118 | 119 | 120 | ..\packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net46\System.Security.Cryptography.X509Certificates.dll 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | ..\packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll 131 | 132 | 133 | ..\packages\Vault.0.9.1.3\lib\net45\Vault.dll 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | Form 145 | 146 | 147 | SyncStatusForm.cs 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | PreserveNewest 159 | 160 | 161 | 162 | 163 | SyncStatusForm.cs 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 175 | 176 | 177 | 178 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /VaultSyncPlugin/VaultSyncPlugin.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: designer.cs generated.cs 2 | extensions: .cs .cpp .h 3 | // Keepass Vault Sync Plugin 4 | // Copyright (C) 2018 Orange Business Services 5 | // 6 | // This library is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU Lesser General Public 8 | // License as published by the Free Software Foundation; either 9 | // version 2.1 of the License, or (at your option) any later version. 10 | // 11 | // This library is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | // Lesser General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU Lesser General Public 17 | // License along with this library; if not, write to the Free Software 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 19 | // USA 20 | // 21 | 22 | -------------------------------------------------------------------------------- /VaultSyncPlugin/VaultSyncPluginExt.cs: -------------------------------------------------------------------------------- 1 | // Keepass Vault Sync Plugin 2 | // Copyright (C) 2018 Orange Business Services 3 | // 4 | // This library is free software; you can redistribute it and/or 5 | // modify it under the terms of the GNU Lesser General Public 6 | // License as published by the Free Software Foundation; either 7 | // version 2.1 of the License, or (at your option) any later version. 8 | // 9 | // This library is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | // Lesser General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU Lesser General Public 15 | // License along with this library; if not, write to the Free Software 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 17 | // USA 18 | // 19 | 20 | 21 | using System; 22 | using System.Collections.Generic; 23 | using System.Linq; 24 | using System.Threading.Tasks; 25 | using System.Windows.Forms; 26 | using KeePass.Forms; 27 | using KeePass.Plugins; 28 | using KeePass.Resources; 29 | using KeePass.UI; 30 | using KeePass.Util.Spr; 31 | using KeePassLib; 32 | using KeePassLib.Security; 33 | using Vault; 34 | using Vault.Models; 35 | 36 | namespace VaultSyncPlugin 37 | { 38 | public sealed class VaultSyncPluginExt : Plugin 39 | { 40 | private IPluginHost host = null; 41 | private ToolStripSeparator separator; 42 | private ToolStripMenuItem menuItem; 43 | private SyncStatus syncStatus; 44 | private SyncStatusForm syncStatusForm; 45 | 46 | /// 47 | /// Override UpdateUrl for update checking 48 | /// 49 | public override string UpdateUrl 50 | { 51 | get 52 | { 53 | return "https://raw.githubusercontent.com/Orange-OpenSource/keepass-vault-sync-plugin/master/KeepassPluginVersion.txt"; 54 | } 55 | } 56 | 57 | /// 58 | /// Input method for the keepass plugin. 59 | /// 60 | /// The keepass instance. 61 | /// True is correctly initialized. 62 | public override bool Initialize(IPluginHost host) 63 | { 64 | if (host == null) return false; 65 | this.host = host; 66 | 67 | // Hook on file opened to check entries in it. 68 | // Disabled because it takes too much time. 69 | // But could be re-enabled since the work is done asynchronously now. 70 | // Could be a setting 71 | // this.host.MainWindow.FileOpened += this.OnFileOpened; 72 | 73 | var menuItemCollection = this.host.MainWindow.ToolsMenu.DropDownItems; 74 | this.separator = new ToolStripSeparator(); 75 | menuItemCollection.Add(this.separator); 76 | 77 | // Add menu item 78 | this.menuItem = new ToolStripMenuItem(); 79 | this.menuItem.Text = "Synchronize Vault entries"; 80 | this.menuItem.Click += this.OnMenuItemClick; 81 | menuItemCollection.Add(this.menuItem); 82 | 83 | this.syncStatus = new SyncStatus(); 84 | 85 | return true; 86 | } 87 | 88 | /// 89 | /// Free resources at closing time. 90 | /// 91 | public override void Terminate() 92 | { 93 | // Remove menu items 94 | ToolStripItemCollection menuItemCollection = this.host.MainWindow.ToolsMenu.DropDownItems; 95 | this.menuItem.Click -= this.OnMenuItemClick; 96 | menuItemCollection.Remove(this.menuItem); 97 | menuItemCollection.Remove(this.separator); 98 | 99 | // Unsubscribe from file opened event 100 | this.host.MainWindow.FileOpened -= this.OnFileOpened; 101 | 102 | base.Terminate(); 103 | } 104 | 105 | /// 106 | /// Called when menu item is clicked. 107 | /// 108 | /// The sender. 109 | /// The event args 110 | private void OnMenuItemClick(object sender, EventArgs e) 111 | { 112 | this.DoTheStuffAsync(); 113 | } 114 | 115 | /// 116 | /// Called when file is opened so we can check vault entries in it. 117 | /// 118 | /// The sender. 119 | /// The event args 120 | private void OnFileOpened(object sender, FileOpenedEventArgs e) 121 | { 122 | this.DoTheStuffAsync(); 123 | } 124 | 125 | /// 126 | /// Do the stuff needed. Single entry point for the plugin to do its work. 127 | /// 128 | private void DoTheStuffAsync() 129 | { 130 | if (this.syncStatusForm == null) 131 | { 132 | this.syncStatusForm = new SyncStatusForm(this.syncStatus); 133 | } 134 | 135 | this.syncStatusForm.Show(); 136 | 137 | Task.Run(() => 138 | { 139 | this.syncStatus.StartSync(); 140 | 141 | // We synchronize vault entries 142 | this.SynchronizeVaultEntries(this.host.Database.RootGroup); 143 | 144 | // Then we merge modified data, and refresh the UI. Standard way to do it, but barely documented. 145 | this.host.Database.MergeIn(this.host.Database, PwMergeMethod.Synchronize); 146 | 147 | this.ExecuteInGuiThread(new Action(() => { this.host.MainWindow.UpdateUI(false, null, true, this.host.Database.RootGroup, true, null, true); })); 148 | 149 | // NOTE: We don't automatically save the database 150 | 151 | this.syncStatus.StopSync(); 152 | }); 153 | } 154 | 155 | /// 156 | /// Look for vault entries, recursively, and synchronize them. 157 | /// 158 | /// The group to synchronize (root group for the first call). 159 | private void SynchronizeVaultEntries(PwGroup group) 160 | { 161 | foreach (var entry in group.Entries) 162 | { 163 | // If entry starts with "vault" it is considered vault entry to synchronize 164 | var name = this.GetKeepassEntryProperty(entry, PwDefs.TitleField); 165 | if (this.IsVaultEntry(name)) 166 | { 167 | this.syncStatus.AddLog(string.Format("Found vault entry {0}", name)); 168 | this.SynchronizeVaultEntry(entry); 169 | } 170 | } 171 | 172 | // Recursive call, avoiding scanning vault synchronized groups 173 | foreach (var subGroup in group.Groups) 174 | { 175 | if (!this.IsVaultEntry(subGroup.Name)) 176 | { 177 | this.SynchronizeVaultEntries(subGroup); 178 | } 179 | } 180 | } 181 | 182 | /// 183 | /// Synchronize this vault entry. 184 | /// 1. Does NOT delete previous folder 185 | /// 2. Creates new folder 186 | /// 3. Populates this folder with Vault data 187 | /// 188 | /// The entry to synchronize. 189 | private void SynchronizeVaultEntry(PwEntry entry) 190 | { 191 | var group = entry.ParentGroup; 192 | var entryName = this.GetKeepassEntryProperty(entry, PwDefs.TitleField); 193 | 194 | var vaultLogin = this.GetKeepassEntryPropertyDereferenced(entry, PwDefs.UserNameField); 195 | var vaultPassword = this.GetKeepassEntryPropertyDereferenced(entry, PwDefs.PasswordField); 196 | var vaultUrl = this.GetKeepassEntryPropertyDereferenced(entry, PwDefs.UrlField); 197 | var vaultAuthPath = this.GetKeepassEntryProperty(entry, "auth"); 198 | var vaultPath = this.GetKeepassEntryProperty(entry, "path"); 199 | 200 | if (!string.IsNullOrEmpty(vaultUrl) && 201 | !string.IsNullOrEmpty(vaultLogin) && 202 | !string.IsNullOrEmpty(vaultPassword) && 203 | !string.IsNullOrEmpty(vaultPath) && 204 | !string.IsNullOrEmpty(vaultAuthPath)) 205 | { 206 | // Download secrets 207 | var secrets = this.DownloadSecrets(this.GetSyncGroupName(entryName), vaultUrl, vaultAuthPath, vaultLogin, vaultPassword, vaultPath); 208 | 209 | this.syncStatus.AddLog("Secrets fetched, will now inject them in the database"); 210 | 211 | // Create new sync group to synchronize data. 212 | var newGroup = this.CreateGroup(this.GetSyncGroupName(entryName), secrets, group.IconId); 213 | 214 | group.AddGroup(newGroup, true); 215 | 216 | this.syncStatus.AddLog("Done."); 217 | } 218 | } 219 | 220 | /// 221 | /// Creates (recursively) a group from a downloaded folder 222 | /// 223 | /// The group name of the created group. 224 | /// The downloaded secret folder. 225 | /// The icon 226 | /// The created keepass group 227 | private PwGroup CreateGroup(string groupName, SecretFolder secrets, PwIcon icon) 228 | { 229 | var group = new PwGroup(true, true, groupName, icon); 230 | group.CreationTime = DateTime.Now; 231 | 232 | // Create subfolder to recreate tree structure 233 | foreach (var subFolder in secrets.Folders) 234 | { 235 | // Create a subfolder only if there's something in it 236 | // Avoids having a lot of empty folders we don't have access to in Vault 237 | if (subFolder.Folders.Count() > 0 || subFolder.Secrets.Count() > 0) 238 | { 239 | this.syncStatus.AddLog(string.Format("Create group {0} in {1}", subFolder.Name, groupName)); 240 | var subGroup = this.CreateGroup(subFolder.Name, subFolder, icon); 241 | group.AddGroup(subGroup, true); 242 | } 243 | } 244 | 245 | // Create entries at this level 246 | foreach (var secret in secrets.Secrets) 247 | { 248 | this.syncStatus.AddLog(string.Format("Create entry {0} in {1}", secret.Name, groupName)); 249 | var entry = this.CreateEntry(secret); 250 | group.AddEntry(entry, true); 251 | } 252 | 253 | return group; 254 | } 255 | 256 | /// 257 | /// Creates an entry from a downloaded secret 258 | /// 259 | /// The downloaded secret 260 | /// The keepass entry 261 | private PwEntry CreateEntry(Secret secret) 262 | { 263 | var entry = new PwEntry(true, true); 264 | entry.Strings.Set(PwDefs.TitleField, new ProtectedString(false, secret.Name)); 265 | if (!string.IsNullOrEmpty(secret.User)) 266 | { 267 | entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, secret.User)); 268 | } 269 | if (!string.IsNullOrEmpty(secret.Password)) 270 | { 271 | entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(false, secret.Password)); 272 | } 273 | if (!string.IsNullOrEmpty(secret.Url)) 274 | { 275 | entry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, secret.Url)); 276 | } 277 | foreach (var item in secret.Content) 278 | { 279 | if (!string.IsNullOrEmpty(item.Value)) 280 | { 281 | entry.Strings.Set(item.Key, new ProtectedString(false, item.Value)); 282 | } 283 | } 284 | return entry; 285 | } 286 | 287 | /// 288 | /// Download the secrets available in a specific Vault, with credentials, and a specific path 289 | /// 290 | /// The group name to give to the created group 291 | /// The Vault URL 292 | /// The Vault auth path. Can be a LDAP path, or "userpass" for Vault standard authentication 293 | /// The Vault username 294 | /// The Vault password 295 | /// The Vault path 296 | /// 297 | private SecretFolder DownloadSecrets( 298 | string groupName, 299 | string vaultUrl, 300 | string vaultAuthPath, 301 | string vaultUsername, 302 | string vaultPassword, 303 | string vaultPath) 304 | { 305 | var client = new SynchronousVaultClient(new Uri(vaultUrl), vaultAuthPath, vaultUsername, vaultPassword, this.syncStatus); 306 | var secretFolder = client.GetSecrets(vaultPath).Result; 307 | return secretFolder; 308 | } 309 | 310 | /// 311 | /// Helper method to get keepass entry property as string, following references 312 | /// 313 | /// The keepass entry 314 | /// The field 315 | /// The dereferenced value for this field. 316 | private string GetKeepassEntryPropertyDereferenced(PwEntry entry, string field) 317 | { 318 | var value = this.GetKeepassEntryProperty(entry, field); 319 | this.ExecuteInGuiThread(new Action(() => { value = SprEngine.Compile(value, new SprContext(entry, this.host.Database, SprCompileFlags.All)); })); 320 | return value; 321 | } 322 | 323 | /// 324 | /// Helper method to get keepass entry property as string 325 | /// 326 | /// The keepass entry 327 | /// The field 328 | /// The value for this field. 329 | private string GetKeepassEntryProperty(PwEntry entry, string field) 330 | { 331 | return entry.Strings.GetSafe(field).ReadString(); 332 | } 333 | 334 | /// 335 | /// Gets a standardized group name from an entry name, to create a group for synchronizing data for the entry 336 | /// 337 | /// The entry containing Vault data to synchronize. 338 | /// The group name. 339 | private string GetSyncGroupName(string entryName) 340 | { 341 | return string.Format("{0}-{1}", entryName, DateTime.Now.ToString("yyyyMMdd-HHmm")); 342 | } 343 | 344 | /// 345 | /// Execute a delegate in the GUI thread when manipulating GUI objects 346 | /// 347 | /// The delegate to execute 348 | private void ExecuteInGuiThread(Delegate @delegate) 349 | { 350 | if (this.host.MainWindow.InvokeRequired) 351 | { 352 | this.host.MainWindow.Invoke(@delegate); 353 | } 354 | else 355 | { 356 | @delegate.DynamicInvoke(); 357 | } 358 | } 359 | 360 | /// 361 | /// Returns true if the entry is a vault entry to synchronize. 362 | /// 363 | /// entry name 364 | /// true if this is a vault entry 365 | private bool IsVaultEntry(string entryName) 366 | { 367 | return entryName.StartsWith("vault"); 368 | } 369 | } 370 | } -------------------------------------------------------------------------------- /VaultSyncPlugin/app.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /VaultSyncPlugin/packages.config: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /build_plgx.bat: -------------------------------------------------------------------------------- 1 | ".\packages\PlgxTool.1.0.0\tools\PlgxTool.exe" --build --verbose --input=".\VaultSyncPlugin" --output=".\VaultSyncPlugin\bin\Release PLGX" --config=".\VaultSyncPlugin\\PlgxConfig.xml" -------------------------------------------------------------------------------- /external/Readme.md: -------------------------------------------------------------------------------- 1 | Unzip the portable [Version of KeePass](https://keepass.info/download.html) in external/keepass folder to resolve dependencies. 2 | The keepass.exe must be in the `external/keepass/` folder 3 | --------------------------------------------------------------------------------