Salsa
A simple web interface which interacts with HAProxy to grant and revoke access to backends via HAproxy's built in ACL feature.
ACLs can be managed with a Salsa admin user. Groups can then be created with a list of ACLs to unlock to users. Users can be added and removed to multiple groups. Once a user successfully logs in, that user's IP address with be added to the ACL (whitelisted).
Building
- Build the backend with go
go build
- Install the frontend dependencies
cd frontend; npm i
- Build the frontend with webpack
npm run prod
Installation
- Install dependencies
apt install haproxy sqlite3
- Setup haproxy - view the sample haproxy configration
- Create a config file like the following:
AutomaticTLS = true
HTTPAddr = "auth.example.com"
DBFile = "salsa.db"
HAProxyNet = "unix"
HAProxyAddr = "/run/haproxy-stats.sock"
LDAPURL = "ldap://ldap.example.com:389"
LDAPStartTLS = true
LDAPSkipVerifyTLS = false
By setting the AutomaticTLS
to true in the config Salsa will automatically fetch a TLS certificate from lets encrypt and listen on 443. If this is set to true, be sure your HTTPAddr
option is a proper domain name pointing to this server, so the ACME challenge will succeed. Setting this false will cause Salsa to listen on port 80 and will extract the original IP address from the standard X-Forwarded-For
instead of the RemoteAddr on the request. In haproxy this can be set automatically with the option forwardfor
option. This will also cause the server to listen on port 80, and disable automatic LetsEncrypt.
Setting LDAPSkipVerifyTLS
currently only works for StartTLS, this can be added for regular TLS on 636 but required a bunch of extra work.
Dependencies
Server
- github.com/BurntSushi/toml - TOML parser for a good configuration format
- github.com/go-chi/chi - Lightweight improvement on the default go router
- github.com/go-ldap/ldap - For LDAP user authentication
- github.com/jmoiron/sqlx - Lightweight improvement on the std sql go library
- github.com/mattn/go-sqlite3 - SQLite3 golang driver
- golang.org/x/crypto - For bcrypt password hashing
Frontend
- webpack - Bundler to build a bundle.js blob
- babel - Transforms JSX into JS
- dayjs - Super lightweight helper library built on top of javascript Dates
- node-fetch - Fetch on the node side (so we can test salsa.js)
- preact - Lightweight view library (4KB version of React)
- preact-router - Lightweight frontend router
Development
The application can be tested by running npm test
from the frontend directory. This requires the server to be running and the API will be tested via the salsa.js library, which is the library the frontend uses to interface with the backend. Some additional tests will be added to test the servers resilience against some specially crafted HTTP requests.
Roadmap?
We can do the same thing haproxy is doing, it would be trivial to remove HAProxy entirely and manage whitelisting IPs and reverse proxying ourself, this would mean all state is in salsa and would reduce multi-state related bugs. This would also significantly simplify the installation step and reduce the barrier to entry. We could manage ACLs from the existing ACL UI.
- Improve user session tracking
- Add a way to export user session history
- Extend test suite
- Fuzz the API
- Blacklist IP's that are brute forcing tokens or logins