funcool/buddy

Issue when compiling to uberjar

freckletonj opened this issue · 5 comments

When I run the following

lein ring uberjar java -cp target/fb-backend.jar clojure.main -m fb-backend.handler

I get this

Exception in thread "main" org.bouncycastle.openssl.PEMException: Unable to create OpenSSL PBDKF: PBKDF-OpenSSL SecretKeyFactory not available, compiling:(handler.clj:193:14)

Caused by: org.bouncycastle.openssl.PEMException: Unable to create OpenSSL PBDKF: PBKDF-OpenSSL SecretKeyFactory not available

This occurs on a line that uses:

(def privkey (keys/private-key "keys/privkey.pem" "XXXXXX"))

I would like to deploy a backend to heroku that uses buddy, and compojure-api, and I need to compile it down to an uberjar, or else heroku's lein takes too long grabbing libraries and booting up.

I found this "lead" but I'm not sure what to make of it:
https://clojurians-log.clojureverse.org/clojure/2016-04-27.html
https://github.com/middlesphere/jwt-auth-service/blob/210e797802b4bf53bfd03aa639ede54a73154f4d/src/jwt_auth_service/core.clj

Thoughts?

The uberjar task AOT compies all the think by default and AOT is known by its issues, this is one of its. You have here two options:

  • Only activate AOT for your main namespace and leave the rest without AOT.
  • Make the private key lazy and only evaluate it on compile time using as example delay:
(def privkey (delay (keys/private-key "keys/privkey.pem" "XXXXXX")))
;; and later when you need acces to it, just use @privkey

Defining a function that returns a privkey when it is called is also an option, but delay is more efficient because it caches it result for subsequent invocations.

My general suggestion is not use AOT at all (only for main ns) or avoid toplevel declarations that can execute code that can not be executed at compile time...

the delay suggestion didn't work,

No matching method found: init for class javax.crypto.Cipher

but not using AOT did work.

Thanks, I think I'm good now! And thank you for the insanely fast response!

@freckletonj if you'd still like to run an uberjar, you can exclude the Bouncy Castle jars from the buddy-core dependency and provide them yourself when running the uberjar.

;; project.clj
(...
  :dependencies [...
                 [buddy "1.1.0" :exclusions [buddy/buddy-core]]
                 [buddy/buddy-core "1.0.0"
                  :exclusions [org.clojure/clojure
                               org.bouncycastle/bcpkix-jdk15on
                               org.bouncycastle/bcprov-jdk15on]]
                 ...
 ...)

and then build your uberjar and run it like

java -cp $path_to_bouncy_castle_jars/bcpkix-jdk15on-1.55.jar:$path_to_bouncy_castle_jars/bcprov-jdk15on-1.55.jar:$your_uberjar $your_uberjar_main

I'm running into the same issue. I get my private key from a function like this:

(defn pkey [auth-conf]
  (let [key-file (io/resource (:privkey auth-conf))
        passphrase (:passphrase auth-conf)]
    (keys/private-key key-file passphrase)))

I'm avoiding aot compilation by specifying

:main ^{:skip-aot true} my-project.handler

I can verify that aot compilation is not taking place from the output when I compile to an uberjar:

Warning: The Main-Class specified does not exist within the jar. It may not be executable as expected. A gen-class directive may be missing in the namespace which contains the main method, or the namespace has not been AOT-compiled.
Created /Users/leourbina/code/projects/my-project/target/my-project-0.1.0-SNAPSHOT.jar
Created /Users/leourbina/code/projects/my-project/target/my-project-0.1.0-SNAPSHOT-standalone.jar

I'm running the jar like this:

java -cp target/my-project-0.1.0-SNAPSHOT.jar clojure.main -m my-project.handler

When the pkey function executes I get the following trace:

Caused by: java.security.NoSuchAlgorithmException: PBKDF-OpenSSL SecretKeyFactory not available
    at javax.crypto.SecretKeyFactory.<init>(SecretKeyFactory.java:122)
    at javax.crypto.SecretKeyFactory.getInstance(SecretKeyFactory.java:160)
    at org.bouncycastle.jcajce.util.DefaultJcaJceHelper.createSecretKeyFactory(Unknown Source)
    ... 56 more

I've tried all the resources mentioned above with no luck. Any suggestions?