hi everyone, I finally had the time to take a look at the code.
With regards to setting up https for webmin Sadly spark's code forces us to go through a keystore, there is no way to bypass that without changing spark. One option I have not yet investigated is building a keystore from a more classic crt+key or pem file setup on startup and passing that to spark. With regards to authentication: As has been said: the 2 current choices are no authentication or JWT. The JWT setup is exactly the same as a token based setup, using cryptography doesn't bring much since a captured token cannot be invalidated unless I missed something. The documentation on how to setup such a token can be found at https://james.staged.apache.org/james-project/3.9.0/servers/distributed/configure/webadmin.html#_generating_a_jwt_key_pair It boils down to creating an asymmetric key pair (private + public keys) You provide the public key (pem file) of the certificate to james so it can verify the provided tokens You can then use the private key to sign as many JWT tokens as needed. James verifies the received tokens against the public key then parses the claims in the token if the signature is valid. When you want to use the token to authenticate you send it in the standard `Authentication: Bearer $TOKEN` http header just like any other bearer token authentication scheme. It protects against bruteforcing the authentication token as it would require bruteforcing the private key which can be quite difficult depending on the algorithm and keysize you choose. It does not protect you against replay attacks so one must ensure the token is never leaked. Of course the private key must never be leaked either or it could be used to generate a rogue valid token. The documentation suggests RSA 4096, but you should be able to use elliptic curve keys instead if you are worried about qantum cryptography. I would say that following the latest best practices for SSH keys would be a good enough starting point. The idea is that using JWT we can have auditability and we could build different tokens with different grants, allowing us to manage granular permission levels. For now james can only understand 2 things in the JWT token : - a login in the `sub=` attribute - a claim to the admin role in the `c=` attribute If your token doesn't have the admin claim you will not be authorized even if the token is properly signed. The main benefit I can see to the current JWT scheme over a basic token based approach is auditability of admin actions. Another benefit is that it doesn't require any storage on james side. A couple drawbacks : - the inability to revoke a token without rotating the entire key and all the corresponding tokens, this can be ok for smaller deployments but could become problematic for larger deployments. - the usual risk associated with any private key based scheme it is only as strong as the user's ability to protect that secret key. - it makes the initial setup a bit harder. implementing a basic token auth should not be very difficult for anyone with some java knowledge. It would then be as simple as - generating a random string that can be written in a HTTP header - providing that string to the server through the config file - sending the string in the Authorization header x509 client certificate requires a full on private key infrastructure with a certificate authority which is known by both parties. In my experience it is used more to secure machine to machine communication (webservices) than for requests operated by humans as configuring the clients to use the correct certificates is usually quite painful/fragile. I haven't thought too deeply about it but I guess it would suffer from more or less the same issues as the JWT solutions while being even more complex to setup. Any other scheme I can think of requires server side storage of the credentials and thus much more work. Jean On Sun, Feb 16, 2025 at 10:53 PM cryptearth <cryptea...@cryptearth.de.invalid> wrote: > Hey there everyone, > > so I put together some lines and uploaded them onto my github: > https://github.com/n0xena/apache-james-webadmin > The basic gist: There's one certificate generator and two files to show > how to setup the server and client. It's pretty much the same code > already in place for the socketTLS and startTLS but with a trust root > and the clientAuth set. > As James already comes with BouncyCastle I reused it for loading the PEM > encode files - but this could be conde in some other way to keep it > vanilla java without any external lib dependencies. > Its sole security relies on the admin controls the client certificates > and hence the root private key should be kept offline. Also the > certificates lack a lot of usually common extensions like > authority/subject key information, crl/ocsp, policies and others. But > populating these extensions requires to provide additional services like > regular updated CRLs or online OCSP service. > As mentioned the certificate management can be done with openssl, but I > don't know how to do that properly. > Again: This is just a proposal of how to secure a service with standard > x509 certificates. But I see some token-based auth the proper solution. > So a proper example for how to setup/use JWT would be more useful as > it's already implemented. > I'll add some proper explanation/comments over the week. > > Have a good one. > > Matt > > Am 14.02.25 um 11:37 schrieb Ilya Terskov: > > Hi there Matt. Looking forward anything u doin :) i think u need use - So > > long © as ur special word for something pretty hard and need a lot of > time > > to make it work ^_^ > > > > пт, 14 февр. 2025 г., 12:05 cryptearth <cryptea...@cryptearth.de > .invalid>: > > > >> Well, a simple credential based auth like a password as the most common > >> and basic form of a challenge-response would work if the webadmin > >> wouldn't be a rest endpoint. But as it is and the way a rest api is > >> meant to be used this credential has to be give at each request. Fun > >> fact: it doesn'T really matter if this "one has to provide some > >> credential over and over again" is some password, some other kind of > >> token or even the rather expensive mutual tls. The point is rather a > >> rest api endpoint is really meant for such. A different approach could > >> be to convert it from a rest endpoint to something with a continous > >> connection like the keep-alive header in http to re-use one already > >> established connection for multiple requests instead of open a new > >> request for every resource. > >> The JWT is a good idea although it lacks some example how to set it up > >> (at least I wasn't able to figure it out) and maybe it could be > >> simplified to be just an arbitrary token instead of something that > >> requires cryptography. The idea should be, at least as the first step, > >> to put some kind of simple protection in place to close the > >> vulnerability of "it's an open unprotected admin control endpoint". And > >> if it's just some token set fixed in the config which has to be provided > >> along. Yes, someone may see this still as vulnerable - but as I > >> mentioned: when someone already has local access to your server to > >> extract that token from the config then you likely have way more serious > >> issues to deal with than someone abusing the james webadmin endpoint. > >> > >> Anyway - I try to come up with some example over the weekend. Have to go > >> to work now. > >> > >> So long. > >> > >> Matt > >> > >> Am 13.02.25 um 02:10 schrieb Ilya Terskov: > >>> Hi guys, so if using lets encrypt certificate, anyone can get access? > >> What > >>> about certificates with password? Client need to write correct one to > get > >>> access? Also additional user/pass layer i think good thing ofc with > >>> tls/ssl. Thanks for your hard work. I not developer and all i can help > u > >>> with just testing and get logs :( sorry about that, i know i am > >> disturbing > >>> you pretty much Matt and Benoit too. > >>> > >>> чт, 13 февр. 2025 г., 07:57 cryptearth <cryptea...@cryptearth.de > >> .invalid>: > >>>> Hello Benoit, > >>>> > >>>> I'm happy to provide something back to the James project. > Unfortunately > >>>> I read your reply too late to start work on it over the past weekend. > >>>> And currently I work long shifts due to high backlog that has to be > >>>> cleaned up. I try to tinker some lines together over the upcomming > >>>> weekend and provide them over on my github. > >>>> > >>>> Long story short: Setting up your own PKI and some lines of Java to > >>>> setup mutual TLS is quite easy. James already comes with the required > >>>> BouncyCastle libs bcpkix, bcprov and bcutil to do so. > >>>> I have to stress: As by the standard any client certificate signed by > >>>> any of the specified root PKI will pass the verification - so using > >>>> Let's Encrypt is discouraged as ANY LE client cert will be valid. To > use > >>>> mutual TLS properly one pretty much has to setup thier own PKI to be > in > >>>> control of any certificates issued. > >>>> Also both Java SSE and BouncyCastle are able to perform basic validity > >>>> checks like CRL or OCSP but these has to be kept up along. As the RFC > >>>> only recommends these to have setup but not actually require them the > >>>> simplest setup is a root ca certificate and two leaf certificates, one > >>>> for the server and one for the client, without all the fancy stuff > like > >>>> AIA, CRL-dp or any of the other x.509 extensions. > >>>> This can also be done with a few simple openssl commands (and unless > >>>> you're a java dev with a jdk installed that's likely the better > >>>> solution) - but as I'm a hobbyist java dev I always did it this way > and > >>>> don't know the openssl commands. So someone with experience in both my > >>>> provide a "translation". > >>>> > >>>> Anyway - I see how I have time and report back if I have some example > >>>> written down. > >>>> > >>>> Have a good one. > >>>> > >>>> Greetings, > >>>> > >>>> Matt > >>>> > >>>> Am 09.02.25 um 22:55 schrieb Benoit TELLIER: > >>>>> Hi there > >>>>> I had a private discussion couple of week ago with Jean HELOU who > >>>> complained of webadmin being hard top secure and hé proposer settings > >> up an > >>>> optional basic auth scheme, easier to use that the jwt bearer token. > >>>>> Would this be helping? > >>>>> Would this be something you would be willing to contribute, with > >>>> guidance? > >>>>> Idem for repairing the TLS setup, or making it usable with pem > files... > >>>>> > >>>>> -- > >>>>> > >>>>> Best regards, > >>>>> > >>>>> Benoit TELLIER > >>>>> > >>>>> General manager of Linagora VIETNAM. > >>>>> Product owner for Team-Mail product. > >>>>> Chairman of the Apache James project. > >>>>> > >>>>> Mail: btell...@linagora.com > >>>>> Tel: (0033) 6 77 26 04 58 (WhatsApp, Signal) > >>>>> > >>>>> > >>>>> Le févr. 8, 2025 6:06 PM, de Cryptearth <cryptea...@cryptearth.de > >> .INVALID>Hi > >>>> Ilya, > >>>>> for me in my very own personal opinion using RSA keys would be fine > >>>>> already, or any other established public-key auth like SSH. But JWT > >>>>> already is some sorts of this which just has to be implemented > >>>>> correctly. I tried to look into it but honestly not really understood > >>>>> it. So I guess if someone could give me just an example I likely > would > >>>>> be able to figure it out on my own. > >>>>> > >>>>> Another option I already use on other projects: mutual TLS. > >>>>> It's easy to setup your own PKI and using client certificates for > both > >>>>> authentication and identification is part of the TLS standard itself > >> and > >>>>> works with established servers like apache httpd. Implementing it in > >>>>> java is as easy as to set your own root-ca-cert as trustanchor when > >>>>> creating the TLS server socket. The server then requests a client > >>>>> certificate signed by the root-ca-cert (even works with intermediate > >>>>> certs) during the handshake and if none is presented the connection > is > >>>>> terminated. All the verification is done by the java SSE itself - > >> nothin > >>>>> complicated to implement - just setup two certificates. > >>>>> > >>>>> Should this be a (or THE) route to implement security on webadmin? I > >>>>> don'T think so. It's an open admin control port and no matter if it > >>>>> comes with some sort of auth or ident it should always be treated as > >>>>> such - which means: only accessible local and protected by firewall > at > >>>>> the very least. Yes, there still should be some security on top - but > >> it > >>>>> often comes down to: if an attacker already got local access to your > >>>>> server in most cases you lost already. > >>>>> > >>>>> So, TLDR: For me if, for some reason, one need remote access to james > >>>>> webadmin just use ssh tunneling like > >>>>> > >>>>> ssh user@host -L8443:localhost:8443 > >>>>> > >>>>> and use the local 8443 and let ssh handle the auth and ident and > crypto > >>>>> and all that stuff. We already have this tool at hand - and: "Don't > >> roll > >>>>> your own crypto!". > >>>>> > >>>>> > >>>>> Am 07.02.25 um 10:26 schrieb Ilya Terskov: > >>>>>> yeah guys i tried that in the end but one problem - if i have > forwards > >>>> to > >>>>>> other email - it need to delete also, same for aliases, so if doing > >>>> script > >>>>>> it need to do all that and recursively. > >>>>>> we sure need 3.9.0 with actions working :) about security on it i > >> think > >>>> we > >>>>>> need just RSA keys just like used in SSH and ofc encryption on this > >>>>>> chanel no plaintext for sure :) > >>>> --------------------------------------------------------------------- > >>>> To unsubscribe, e-mail: server-user-unsubscr...@james.apache.org > >>>> For additional commands, e-mail: server-user-h...@james.apache.org > >>>> > >>>> > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: server-user-unsubscr...@james.apache.org > >> For additional commands, e-mail: server-user-h...@james.apache.org > >> > >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: server-user-unsubscr...@james.apache.org > For additional commands, e-mail: server-user-h...@james.apache.org > >