Fork me on GitHub
#pedestal
<
2017-07-07
>
skylar13:07:07

What is the best way to secure Pedestal REST-endpoints?

shaun-mahood15:07:18

@skylar: I haven't gotten to using it yet, but https://github.com/propan/geheimtur has been recommended to me when I asked about it earlier.

shaun-mahood15:07:55

Are there any examples of how to use the resource ring-middleware (https://github.com/pedestal/pedestal/blob/master/service/src/io/pedestal/http/ring_middlewares.clj#L142) or any of the other ring-middleware that takes an argument? It's just different enough from the examples I can find (for both ring and pedestal) that it's giving me a bit of difficulty figuring out. I think I'm almost there but not sure yet if what I'm trying is just a terrible mess compared to what it could be.

ddeaguiar17:07:28

@shaun-mahood, the ring resource middleware is used when :io.pedestal.http/resource-path is set on the service-map. Refer to https://github.com/pedestal/pedestal/blob/master/service/src/io/pedestal/http.clj#L256. All the middleware adapters in the io.pedestal.http.ring-middlewares namespace are just functions which return interceptors. To use them, you would invoke the functions when building your interceptor chain. A lot of them are configured through the default-interceptors fn, though. Take a deeper look there for more details. https://github.com/pedestal/pedestal/blob/master/service/src/io/pedestal/http.clj#L181

ddeaguiar17:07:39

@skylar another authentication option is Buddy (https://github.com/funcool/buddy). There’s a PR which includes an a Buddy auth integration sample project. https://github.com/pedestal/pedestal/pull/503.

shaun-mahood19:07:18

@ddeaguiar: Maybe I'm going down the wrong path then - what I'm trying to do is grab a file from the local filesystem (not in the resource-path) and serve that file. My thought was that I could use one of the existing ring-middlewares and pass in the specific file path. At this point I've got an interceptor that grabs the info from the request and does a query to find the file-path and adds that to the context, and I want to have that file-path sent to the resource middleware (or one of the alternatives) - so for now I'm trying to just wrap it with another interceptor that passes in the file-path. My first thought was to just put the argument (or the path to the context) into the interceptor chain directly, but I couldn't find a way to do that. What you posted above helps since I was making one wrong assumption already, so thanks!

bherrmann21:07:05

Harumph... the war example seems broken.... https://github.com/pedestal/pedestal/issues/527

bherrmann21:07:34

any ideas on how to poke at this one?

mtnygard22:07:51

@bherrmann I'll take a look at this. I've needed to understand how war deployment works for a while. (I never worked on that part before.) What I see at the moment looks like a missing Jar file for the servlet API.

mtnygard22:07:03

@bherrmann OK, I figured out what was going on. In the war example, we don't have Jetty in the dependencies. That's so the war file doesn't contain a complete copy of Jetty, Tomcat, etc.

mtnygard22:07:31

Instead, there's a profile in project.clj that you need to add for REPL based development only.

mtnygard22:07:43

So if you run 'lein with-profile +jetty repl' you get the desired behavior.

mtnygard22:07:03

I've pushed an update to the readme that clarifies this process.

mtnygard22:07:32

As an aside, one thing I'd really love to have is build automation that could start up and test each of the samples during a CI build...

souenzzo22:07:04

((io.pedestal.http.route/form-action-for-routes
   #{["/" :get (fn [_] {:status 200 :body "Hello"}) :route-name :main]}) :main)
ExceptionInfo Route not found clojure.core/ex-info (core.clj:4617) I'm missing something?

mtnygard22:07:55

@souenzzo I think form-action-for-routes needs the fully-expanded routes. Can you try the same thing with the value of (:io.pedestal.http/routes service-map) after starting the service?

souenzzo22:07:53

(let [routes #{["/" :get (fn [_] {:status 200 :body "Hello"}) :route-name :main]}
      service {::bootstrap/routes routes
               ::bootstrap/join?  false
               ::bootstrap/type   :jetty
               ::bootstrap/port   8080}
      server (bootstrap/create-server service)]
  ((io.pedestal.http.route/form-action-for-routes (::bootstrap/routes server)) :main))

ExceptionInfo Route not found  clojure.core/ex-info (core.clj:4617)

souenzzo22:07:21

#error{:cause "Route not found",
       :data {:app-name nil, :route-name :main},
       :via [{:type clojure.lang.ExceptionInfo,
              :message "Route not found",
              :data {:app-name nil, :route-name :main},
              :at [clojure.core$ex_info invokeStatic "core.clj" 4617]}],
       :trace [[clojure.core$ex_info invokeStatic "core.clj" 4617]
               [clojure.core$ex_info invoke "core.clj" 4617]
               [io.pedestal.http.route$find_route invokeStatic "route.clj" 265]
               [io.pedestal.http.route$find_route invoke "route.clj" 259]
               [io.pedestal.http.route$form_action_for_routes$fn__10117 doInvoke "route.clj" 495]
               [clojure.lang.RestFn invoke "RestFn.java" 410]
               [formiguinhas_service.service$eval69611 invokeStatic "form-init7223753487312925116.clj" 8]
               [formiguinhas_service.service$eval69611 invoke "form-init7223753487312925116.clj" 1]
               [clojure.lang.Compiler eval "Compiler.java" 6927]
               [clojure.lang.Compiler eval "Compiler.java" 6890]
               [clojure.core$eval invokeStatic "core.clj" 3105]
               [clojure.core$eval invoke "core.clj" 3101]
               [clojure.main$repl$read_eval_print__7408$fn__7411 invoke "main.clj" 240]
               [clojure.main$repl$read_eval_print__7408 invoke "main.clj" 240]
               [clojure.main$repl$fn__7417 invoke "main.clj" 258]
               [clojure.main$repl invokeStatic "main.clj" 258]
               [clojure.main$repl doInvoke "main.clj" 174]
               [clojure.lang.RestFn invoke "RestFn.java" 1523]
               [clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__68771 invoke "interruptible_eval.clj" 87]
               [clojure.lang.AFn applyToHelper "AFn.java" 152]
               [clojure.lang.AFn applyTo "AFn.java" 144]
               [clojure.core$apply invokeStatic "core.clj" 646]
               [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1881]
               [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1881]
               [clojure.lang.RestFn invoke "RestFn.java" 425]
               [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 85]
               [clojure.tools.nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 55]
               [clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__68816$fn__68819
                invoke
                "interruptible_eval.clj"
                222]
               [clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__68811
                invoke
                "interruptible_eval.clj"
                190]
               [clojure.lang.AFn run "AFn.java" 22]
               [java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1142]
               [java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 617]
               [java.lang.Thread run "Thread.java" 748]]}

souenzzo22:07:42

Even after (-> service bootstrap/default-interceptors bootstrap/create-server bootstrap/start), the routes continue as a set

mtnygard22:07:53

@souenzzo I have to head out for dinner. I'll check back in later. Let me know if that doesn't work and I can dig some more.

souenzzo15:07:42

@mtnygard I still cant use form-action-for-routes 😕

mtnygard22:07:24

OK, I'll try to diagnose further later.

bherrmann22:07:25

@mtnygard Huh. While you looked at that, I was writting up this, https://github.com/pedestal/pedestal/issues/529

bherrmann22:07:01

@mtnygard Your "lein with-profile +jetty repl" does work for the REPL case though.

bherrmann22:07:35

I wonder if using a WAR file is just weird. It doesnt appear to be the path most traveled.