Mladen,

On 12/23/20 09:07, Mladen Adamović wrote:
hmmm.. at least for us, Certbot fetches acme-challenge on HTTP connector.
According to
https://github.com/payara/Payara/blob/master/appserver/packager/appserver-core/src/main/resources/bin/letsencrypt.py
an app most likely should have a HTTP connector for Letsencrypt.

Then it really doesn't matter AFAIK, if Servet is used or a Valve for most
cases.  Whatever dev thinks fits more in the nature of the system.

Romain is right: if you have configured blanket authentication requirements for your web application, they will be applied *before* a Servlet is invoked and Let's Encrypt doesn't generally provide authentication to the application handling its ACME reply.

Stated more simply: if your application requests username+password, then your application cannot be used to respond to ACME requests.

If you use a Valve, you can have the ACME-handling code execute before the authenticator. That's how you get around the authentication "problem".

I know this can be implemented outside of Tomcat (as we have that
implementation through Servlet), I'm discussing what could be done in
Tomcat to simplify Letsencrypt integration.

Use a Valve. ;)

-chris

On Wed, Dec 23, 2020 at 2:01 PM Romain Manni-Bucau <rmannibu...@gmail.com>
wrote:

Le mer. 23 déc. 2020 à 12:50, Mladen Adamović <mladen.adamo...@gmail.com>
a
écrit :

On Wed, Dec 23, 2020 at 12:12 PM Romain Manni-Bucau <
rmannibu...@gmail.com

wrote:

I don't think so, this connector auth is only used in very particular
cases
(= never ;)): HTTP2 - we don't care, AJP - we don't care much. It is
also a
kind of automatic authorization - no password or so - so will pass and
not
fail.


That sounds very strange, as I have seen in the code:
             if (req.getRemoteUserNeedsAuthorization()) {
...
                 } else if (!(authenticator instanceof
AuthenticatorBase)) {
    ...
                 }

public class SSLAuthenticator extends AuthenticatorBase {


Sure but check what makes remoteUserNeedsAuthorization true (http2 and ajp)
and what does the block when true (authenticate(username), no password or
so).
So not an issue IMHO.



My point was if you have some security contraint (JWT, basic, etc...) on
/*, then your servlet will not be called for letsencrypt call whereas
if
you have a valve you can still handle it properly since you didn't
enter
the secured chain - a valve is before filter chain and can be before
authenticators in valve chain since authenticators - AuthenticatorBase
-
are valves.


Authenticator Valve's seems to me to have a different treatment than
other
Valves which are accessed through Pipeline.


This is true since it can be obtained from the context and its call can be
forced, but here again the question is when.
If you check callers then it shouldn't be the case until you add another
valve doing it and if so you can still set the LetsEncryptValve before and
bypass it - can even be set on the host and not the context.





In other words: no code change required in tomcat internals.


I don't understand this yet. If the implementation would use serverl.xml
to
change StandardContextValve to something else?


No, change nothing, just add a valve on the host for example through <Valve
className.... /> tag.



I've tried to figure out what are you doing in meecrowave and my IDE
(Netbeans) shows me Usage of LetsEncryptValve [no occurrences]


Maybe use another IDE ;) (joking ;)):

https://github.com/apache/openwebbeans-meecrowave/blob/433a691b246f9eeda2273e794ddbb7970691cc5f/meecrowave-letsencrypt/src/main/java/org/apache/meecrowave/letencrypt/LetsEncryptSetup.java#L44
The MeecrowaveAwareInstanceCustomizer instance enables to "code" the
server.xml but it is equivalent to previous proposal (<Valve/>).



How this LetsEncryptValve is actually "injected" into meecrowave
Pipeline ?
Or how it is used internally?
I didn't see any Reflection code on Valves or Valve base by searching
source code.





Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <
https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<


https://www.packtpub.com/application-development/java-ee-8-high-performance



Le mer. 23 déc. 2020 à 11:23, Mladen Adamović <
mladen.adamo...@gmail.com

a
écrit :

Thank you Romain, do you then think the place to check for ACME Valve
(if
that would the be appropriate naming) would be in
CoyoteAdapter.postParseRequest line 814
before doConnectorAuthenticationAuthorization(...) ?


On Wed, Dec 23, 2020 at 9:22 AM Romain Manni-Bucau <
rmannibu...@gmail.com>
wrote:

Side note: using a servlet generally does not work if you have any
security
on the webapp + requires a webapp whereas using a valve solves
these
two
issues.

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <
https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<




https://www.packtpub.com/application-development/java-ee-8-high-performance



Le mer. 23 déc. 2020 à 09:15, Mladen Adamović <
mladen.adamo...@gmail.com

a
écrit :

As I haven't received more replies on this topic, I'm guessing
project
maintainers are not interested in reviewing and including the
code
for
simpler Letsencrypt integration and discussing the mentioned SSL
documentation improvements?

Enabling AMCE response servlet (good idea by default) would be a
good
step
in my opinion?

My procedure is explained here:






https://mladenadamovic.wordpress.com/2016/09/06/configure-tomcat-with-ssl-on-ubuntu-minimal/
and the step "Configure HTTP redirect application with support to
ACME
challenge" could be integrated into Tomcat easily.

In the case that is integrated, I can write a new improved
tutorial/process.




On Sat, Dec 19, 2020 at 11:09 PM Mladen Adamović <
mladen.adamo...@gmail.com>
wrote:

On Sat, Dec 19, 2020 at 6:30 PM Romain Manni-Bucau <
rmannibu...@gmail.com>
wrote:

It moves the problem elsewhere, how would the CLI communicate
with
tomcat?
JMX, HTTP uses a port, a file based communication would be
probably
worse
because of perms and other admin issues (and just not working
in
k8s).


I don't see other sane ways actually. So it seems a web-based
manager
with
curl is there to stay (for the time being at least).

To Chris: It's somewhat weird that the user needs a web manager
just
for
curl-ing certification renewal.

To everyone:
I have a suggestion on improving Documentation regarding SSL.
https://tomcat.apache.org/tomcat-10.0-doc/ssl-howto.html
Currently, it states
Configuration
Prepare the Certificate Keystore
Tomcat currently operates only on JKS, PKCS11 or PKCS12 format
keystores.

...


I think it should start with
Configuration
Option 1) Use Tomcat Native
which would showcase a path to something like:

<!-- Define an SSL Coyote HTTP/1.1 Connector on port 8443 -->
<Connector
     protocol="org.apache.coyote.http11.Http11NioProtocol"
     port="8443"
     maxThreads="150"
     SSLEnabled="true" >
   <SSLHostConfig>
     <Certificate
         certificateKeyFile="conf/localhost-rsa-key.pem"
         certificateFile="conf/localhost-rsa-cert.pem"
         certificateChainFile="conf/localhost-rsa-chain.pem"
         type="RSA"
         />
   </SSLHostConfig>
</Connector>

Option 2) Without Tomcat Native


...



I don't know what is the formal process for improving the
documentation
here?









Le sam. 19 déc. 2020 à 15:24, Mladen Adamović <
mladen.adamo...@gmail.com

a
écrit :

On Sat, Dec 19, 2020 at 2:29 PM Christopher Schultz
<
ch...@christopherschultz.net> wrote:

Why not use cron? You can do this with a single
"curl"
command
and
the
Manager+JMXProxyServlet.


We are not using Tomcat manager app.

Why someone should be forced to use Manager, to
read/setup
the
documentation regarding JMXProxyServlet, create an
additional
servlet (where does it have dependency on?) only to
reload
automatically
certificates?

I'm proposing a solution with the simple
SSLHostConfig
parameter.
It's
a
user friendly. Simple, intuitive.
No need for using manager, no need to create a
specific
servlet
somewhere
in your code. Just a single server.xml argument.

Also, *another idea*, I'm contributing this code
(see
below)
we
are
using
for Letsencrypt ACME challenge.
Tomcat could also have an option, i.e. in web.xml to
automatically
support
Letsencrypt ACME challenge.
Idea for web.xml
   <servlet>

  <servlet-name>Letsencrypt-acme</servlet-name>













<servlet-class>org.apache.catalina.servlets.LetsencryptAcmeChallenge</servlet-class>
         <init-param>
etc.
</servlet>


We are using
@WebServlet(name = "LetsencryptAcmeChallenge",
urlPatterns =
{"/.well-known/acme-challenge/*"})
public class LetsencryptAcmeChallenge extends
HttpServlet
{

   /**
    * Processes requests for both HTTP
<code>GET</code>
and
<code>POST</code> methods.
    *
    * @param request servlet request
    * @param response servlet response
    * @throws ServletException if a servlet-specific
error
occurs
    * @throws IOException if an I/O error occurs
    */
   protected void processRequest(HttpServletRequest
request,
HttpServletResponse response)
       throws ServletException, IOException {
     String requestUrl =
request.getRequestURL().toString();
     if
(requestUrl.contains(".well-known/acme-challenge/"))
{
       int indexFilename =
requestUrl.lastIndexOf("/")
+
1;
       boolean wasError = true;
       if (indexFilename > 0 && indexFilename <
requestUrl.length()) {
         String filename =
requestUrl.substring(indexFilename);
         File existingFile = new

File("/tmp/letsencrypt/public_html/.well-known/acme-challenge/"
+
  filename);
         if (existingFile.exists()) {
           response.setContentType("text/plain");
           OutputStream out =
response.getOutputStream();
           FileInputStream in = new
FileInputStream(existingFile);

  FilesOperations.inputStreamToOutputStream(in,
out);
           wasError = false;
         }
       }
       if (wasError) {
         throw new ServletException("invalid
requestUrl
" +
requestUrl);
       }
   }

from FilesOperations:
      public static void
inputStreamToOutputStream(InputStream
in,
OutputStream out) throws IOException {
         try {
             byte[  ] buf = new byte[32 * 1024];  //
32K
buffer
             int bytesRead;
             while ((bytesRead = in.read(buf)) !=
-1) {
                 out.write(buf, 0, bytesRead);
             }
         } finally {
             if (in != null) {
               in.close();
               out.close();
             }
         }
     }








*Long*:
SSL certificates have a period of expiration and
in
the
case of
Letsencrypt, it's set to 3 months as they think
everyone
should
have
the
renewal mechanism automatically.

As the Letsencrypt is the most popular SSL
issuing
authority
(source:
https://trends.builtwith.com/ssl/LetsEncrypt
), I
think
Tomcat
should
have
an integration with Letsencrypt working
flawlessly.

We are currently using the script to renew the
certificate
(I
can
share
our
integration details with whoever is interested,
please
email me
if
you
are
interested), but it's restarting Tomcat.

As Tomcat shall not be restarted ever
(ideally), I
think
Tomcat
should
have
an option to reload certificate, without a
dependency
to
Tomcat
source
code
and "hacks" like some available on
StackOverflow:













https://stackoverflow.com/questions/5816239/how-do-i-force-tomcat-to-reload-trusted-certificates
).
Those hacks are no good as:
1) code to reload certificate should not run
inside
Java
code,
as
letsencrypt is invoked through Linux
2) each application uses that Stackoverflow hack
have
additional
compile
and run dependency set to Tomcat (which is very
bad).

I have a proposal on how this should be fixed:
Tomcat
should
have a
server.xml options something like
certificateReloadAfterDays or
reloadAfterDays

I see this is moved to SSLHostConfig, we are
still
using
old
params.

Do you agree on this feature?

If so... I'm not lazy to try to do it myself,
but
as I
haven't
ever
written
Tomcat code neither know procedures (I have been
coding
professionally
since 2006, but I never committed to Maven or
Git
project
before,
lol),
is
there someone else who is keen on doing this
feature?

Have a look at this:


http://tomcat.apache.org/presentations.html#latest-lets-encrypt

-chris




---------------------------------------------------------------------
To unsubscribe, e-mail:
dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail:
dev-h...@tomcat.apache.org

















---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to