Where I work, we really needed a team password manager that's kept up to date with any password that's been added by a team member. In addition to that, we needed it to be protected by an LDAP authentication and self-hosted (I personally can't trust any cloud-based password manager).
Sadly, most of the open source web-based password managers that offer self-hosting and LDAP authentication were paid.
Recipe
Lucky for me (and for you), we can build what we want using the following free and open source applications:
- Apache Httpd 2.4
- Apache LDAP & WebDAV modules
- KeeWeb https://keeweb.info/ by the amazing @antelle
We all know what Apache httpd and its mods are, but let's talk a little about KeeWeb (Github repo):
It's basically written in HTML/CSS and JavaScript, and it's based on KeePass, so you get almost all the features of the KeePass desktop app.
It decrypts your .kdbx database locally on the browser, so security++ ;)
It uses browser cache whenever it can, so keep an eye on that when redeploying your application.
Time to get your hands dirty!
We'll deploy KeeWeb on an Apache httpd web server, we'll configure KeeWeb to look for our .kdbx database hosted on the same server using WebDAV protocol, and finally, we'll protect the access to the website by configuring the Apache LDAP module.
I'll be working on CentOS 7 so some commands may vary depending on your operating system.
So let's get started by installing Apache httpd.
sudo yum install -y httpd
Apache on CentOS loads automatically the necessary mods that we'll use in our configuration so don't worry about that.
Next, we have to get the resources of the KeeWeb application:
Download the
gh-pages
branch content:
wget https://github.com/keeweb/keeweb/archive/gh-pages.zip
Unzip it at the root of your HTTP server.
sudo unzip gh-pages.zip -d /var/www/html/
You should have a folder
/var/www/html/keeweb-gh-pages
, let's move its content to the parent folder:
sudo mv /var/www/html/keeweb-gh-pages/* /var/www/html/ && sudo rmdir /var/www/html/keeweb-gh-pages/
thenchown -R apache.apache /var/www/html/
Next, we are going to write a Virtual Host for KeeWeb:
sudo vim /etc/httpd/conf.d/01-default.conf
This is my full virtual host configuration file, we assume that the .kdbx database file will be stored in the webdav
folder of our website.
DavLockDB "/var/www/html/webdav/DavLock"
<VirtualHost *:80>
DocumentRoot "/var/www/html"
# According to the dev of KeeWeb, OPTIONS request must work without authorization. So we'll keep it outside the following location tags
RewriteEngine on
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ blank.html [R=200,L,E=HTTP_ORIGIN:%{HTTP:ORIGIN}]
# If your Apache is behind a load-balancer, and the SSL certificate is handled by the Load-balancer, leave this.
RequestHeader edit Destination ^https: http: early
# Don't require LDAP authentication for a healthcheck
SetEnvIf Request_URI "^/healhcheck" accessgranted=1
<Location />
Order deny,allow
Satisfy any
Deny from all
Allow from env=accessgranted
AuthName "LDAP Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthLDAPURL "ldap://your-ldap-url:389/dc=example,dc=com?uid"
AuthLDAPBindDN ${Your-ldap-bind-dn}
AuthLDAPBindPassword ${Your-ldap-bind-password}
AuthLDAPGroupAttribute ${Your-ldap-membership-attribute}
AuthLDAPGroupAttributeIsDN off
Require ldap-group ${The-ldap-group-dn-you-require-your-users-to-belong-to}
</Location>
<Location "/webdav">
DAV On
AuthType "Basic"
AuthName "webdav"
Options Indexes
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Headers "origin, content-type, cache-control, accept, authorization, if-match, destination, overwrite"
Header always set Access-Control-Expose-Headers "ETag"
Header always set Access-Control-Allow-Methods "GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK"
Header always set Access-Control-Allow-Credentials "true"
</Location>
# Logs
ErrorLog /dev/stderr
CustomLog "|/usr/sbin/rotatelogs -l /var/log/httpd/apache_access.log.%Y-%m-%d 86400" combined
</VirtualHost>
Quick explanation
DavLockDB "/var/www/html/webdav/DavLock"
is a lockfile used by Apache for when our server will receive LOCK or UNLOCK requests to handle write-concurrency for example.
RequestHeader edit Destination ^https: http: early
If your Apache is behind a load-balancer, and the SSL certificate is handled by the Load-balancer, leave this.
SetEnvIf Request_URI "^/healhcheck" accessgranted=1
If you need a healthcheck URI that should not be protected by LDAP, set a variable accessgranted=1
and make sure to add Allow from env=accessgranted
inside the tag that checks the LDAP authentication.
Then comes a classic location tag that checks LDAP authentication and authorization, here we make sure the user belongs to the specified LDAP group. If you don't need the user to belong to a specific group, you can find plenty of examples on how to do it on the interwebs ;) :
<Location />
Order deny,allow
Satisfy any
Deny from all
Allow from env=accessgranted
AuthName "LDAP Authentication"
AuthType Basic
AuthBasicProvider ldap
AuthLDAPURL "ldap://your-ldap-url:389/dc=example,dc=com?uid"
AuthLDAPBindDN ${Your-ldap-bind-dn}
AuthLDAPBindPassword ${Your-ldap-bind-password}
AuthLDAPGroupAttribute ${Your-ldap-membership-attribute}
AuthLDAPGroupAttributeIsDN off
Require ldap-group ${The-ldap-group-dn-you-require-your-users-to-belong-to}
</Location>
Then a classic location tag to configure WebDav:
<Location "/webdav">
DAV On
AuthType "Basic"
AuthName "webdav"
Options Indexes
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Headers "origin, content-type, cache-control, accept, authorization, if-match, destination, overwrite"
Header always set Access-Control-Expose-Headers "ETag"
Header always set Access-Control-Allow-Methods "GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK"
Header always set Access-Control-Allow-Credentials "true"
</Location>
If you don't have a .kdbx file yet, I recommend to create one using the Keepass 2 desktop app, and copy it inside the /webdav folder.
Head off to your browser, and authenticate with your LDAP credentials you should see now the KeeWeb app! You can choose the webdav method by clicking More, then fill in the path to your .kdbx file, in our case it's https://www.example.com/webdav/database.kdbx
. We didn't set any webdav user or password so hit OK then enter the master password and Voilà!
App configuration
Not too fast, we don't want our users to go through all this jazz each time they want to access the app...
In the index.html
, find the meta tag kw-config
and make sure the attribute content
has a value of config.json
, we'll create this file later.
The whole html meta tag looks like this:
<meta name="kw-config" content="config.json">
Next, create a file called config.json
at the root of your website and fill it with the configuration you need from here. My config file looked like this:
{
"settings": {
"theme": "fb",
"autoSave": true,
"autoSaveInterval": 1,
"canOpenDemo": false,
"dropbox": false,
"gdrive": false,
"onedrive": false,
"canExportXml": false
},
"files": [{
"storage": "webdav",
"name": "Database",
"path": "/webdav/database.kdbx"
}]
}
Make sure to delete your browser cache, and you're done!
Last words
The downside of this web application is that we can not apply ACL to each entry in the password manager, so it probably can not be shared by many teams at work. If you have any questions I'll be glad to help.
Note: This article has been first published on my personal blog: https://www.zaine.me/
Top comments (0)