ring-clojure / ring

Clojure HTTP server abstraction
MIT License
3.75k stars 519 forks source link

Add option to use the KeyStoreScanner bean #416

Closed sirmspencer closed 3 years ago

sirmspencer commented 3 years ago

The module is jetty-ssl-context-reload.xml

<Configure id="Server" class="org.eclipse.jetty.server.Server">
  <Call name="addBean">
    <Arg>
      <New id="keyStoreScanner" class="org.eclipse.jetty.util.ssl.KeyStoreScanner">
        <Arg><Ref refid="sslContextFactory"/></Arg>
        <Set name="scanInterval"><Property name="jetty.sslContext.reload.scanInterval" default="1"/></Set>
      </New>
    </Arg>
  </Call>
</Configure>

All you need (I think) is (import [org.eclipse.jetty.util.ssl KeyStoreScanner])

(defn- ^ServerConnector ssl-connector [server options]
  (let [ssl-port     (options :ssl-port 443)
        http-factory (HttpConnectionFactory.
                      (doto (http-config options)
                        (.setSecureScheme "https")
                        (.setSecurePort ssl-port)
                        (.addCustomizer (SecureRequestCustomizer.))))
        context      (ssl-context-factory options)
        ssl-factory  (SslConnectionFactory.
                      context
                      "http/1.1")]
    (doto (server-connector server ssl-factory http-factory)
      (.setPort ssl-port)
      (.setHost (options :host))
      (.setIdleTimeout (options :max-idle-time 200000)))
    (when-let [scan-interval (options :scan-interval)]
      (.addBean server (doto (KeyStoreScanner. context)
                         (.setScanInterval scan-interval))))))
weavejester commented 3 years ago

What is this used for, why do you want it, and can this be done through the :configurator option instead?

sirmspencer commented 3 years ago

This is used for monitoring key stores and reloading the ssl-context-factory when they change. When using certbot to get web certificates, they only last 3 months. This module is to help so you dont have to take the server down to reset the ssl keystore.

Technically yes, I can do it with :configurator. Its kind of messy because I dont have a reference to the ssl-context-factory. I understand you cant add an option for every module that comes with Jetty, but I think this is a nice extension of the ssl modules you are already using.

sirmspencer commented 3 years ago

I have tested this code chunk on my project.

(.addBean server
          (doto (KeyStoreScanner. ssl-context-factory)
             (.setScanInterval 600)))
weavejester commented 3 years ago

This sounds like a reasonable addition, perhaps under the option :keystore-scan-interval.

sirmspencer commented 3 years ago

This sounds like a reasonable addition, perhaps under the option :keystore-scan-interval.

Sounds good. I'll put together a PR this week.

sirmspencer commented 3 years ago

@weavejester What should I do with the column alignment for the new option? keystore-scan-interval is two characters longer than the current alignment. I see another change where the new new options have their own alignment (although they are much longer).

  :exclude-protocols    - when :ssl? is true, additionally exclude these
                          protocols
  :replace-exclude-ciphers?   - when true, :exclude-ciphers will replace rather
                                than add to the cipher exclusion list (defaults
                                to false)
  :replace-exclude-protocols? - when true, :exclude-protocols will replace
                                rather than add to the protocols exclusion list
                                (defaults to false)
  :keystore             - the keystore to use for SSL connections
  :keystore-type        - the keystore type (default jks)
  :key-password         - the password to the keystore
  :keystore-scan-interval - When provided, the interval in seconds to scan for
                              an updated keystore.
weavejester commented 3 years ago

Ideally update all of the other lines to the right indentation, so:


  :exclude-protocols      - when :ssl? is true, additionally exclude these
                          protocols
  :replace-exclude-ciphers?   - when true, :exclude-ciphers will replace rather
                                than add to the cipher exclusion list (defaults
                                to false)
  :replace-exclude-protocols? - when true, :exclude-protocols will replace
                                rather than add to the protocols exclusion list
                                (defaults to false)
  :keystore               - the keystore to use for SSL connections
  :keystore-type          - the keystore type (default jks)
  :key-password           - the password to the keystore
  :keystore-scan-interval - if not nil, the interval in seconds to scan for an
                            updated keystore