wip(lldap): Consultant
This commit is contained in:
123
scripts/ldap-nginx-plumber/src/ldap_nginx_plumber/main.clj
Normal file
123
scripts/ldap-nginx-plumber/src/ldap_nginx_plumber/main.clj
Normal file
@@ -0,0 +1,123 @@
|
||||
(ns ldap-nginx-plumber.main
|
||||
(:require [clojure.spec.alpha :as spec]
|
||||
[clojure.string :as str]
|
||||
[org.httpkit.server :as http]
|
||||
[clj-ldap.client :as ldap]
|
||||
[babashka.cli :as cli]
|
||||
[clojure.pprint :refer [pprint]])
|
||||
(:import [java.util Base64]
|
||||
[java.nio.charset StandardCharsets])
|
||||
(:gen-class))
|
||||
|
||||
(defn- port? [x]
|
||||
(and (nat-int? x)
|
||||
(<= 0 x 65535)))
|
||||
|
||||
(def cli-spec
|
||||
{:spec
|
||||
{:port {:coerce :int
|
||||
:desc "Port to listen on"
|
||||
:alias :p
|
||||
:validate port?
|
||||
:require true}
|
||||
:base-dn {:coerce :string
|
||||
:desc "Base DN for LDAP searches"
|
||||
:require true}
|
||||
:ldap-host {:coerce :string
|
||||
:require true}
|
||||
:ldap-port {:coerce :int
|
||||
:validate port?
|
||||
:default 389}
|
||||
:bind-dn {:coerce :string
|
||||
:require true}
|
||||
:bind-password {:coerce :string
|
||||
:require true}}})
|
||||
|
||||
(def ^:dynamic *opts*)
|
||||
|
||||
(defonce ldap-connection-pool
|
||||
(atom nil))
|
||||
|
||||
(defn- base64->utf8 [base64]
|
||||
(try (-> (.decode (Base64/getDecoder) base64)
|
||||
(String. StandardCharsets/UTF_8))
|
||||
(catch java.lang.IllegalArgumentException _))
|
||||
nil)
|
||||
|
||||
(defn- response [status & {:as more}]
|
||||
(apply merge
|
||||
{:status status
|
||||
:headers {"Content-Type" "text/plain"}}
|
||||
more))
|
||||
|
||||
(defn- consultant-app [req]
|
||||
(printf "\n%s received request:\n" (.toString (java.util.Date.)))
|
||||
(pprint req)
|
||||
(try
|
||||
(if-let [[_ user pass] (some->> (get-in [req :headers] "Authorization")
|
||||
str/lower-case
|
||||
(re-matches #"basic ([a-zA-Z0-9+/=]+)")
|
||||
second
|
||||
base64->utf8
|
||||
(re-matches #"([^:]+):(.*)"))]
|
||||
(response 200 :body "yay!")
|
||||
(response
|
||||
401
|
||||
:headers {"WWW-Authenticate" "Basic realm=\"Restricted\""
|
||||
"Cache-Control" "no-cache"}))
|
||||
(catch Exception e
|
||||
(println "`consultant-app` threw an error:")
|
||||
(prn e)
|
||||
(response 500))))
|
||||
|
||||
(defonce consultant-server (atom nil))
|
||||
|
||||
(defn- stop-consultant! []
|
||||
(when @consultant-server
|
||||
;; Graceful shutdown: wait 100ms for existing requests to be finished.
|
||||
;; :timeout is optional, when no timeout, stop immediately.
|
||||
(http/server-stop! @consultant-server {:timeout 100})
|
||||
(reset! consultant-server nil)))
|
||||
|
||||
(defn- start-consultant [& {:keys [port] :as opts}]
|
||||
(binding [*opts* opts]
|
||||
(if @consultant-server
|
||||
(throw (ex-info "Refusing to start the server whilst a previous lingers" {}))
|
||||
(reset! consultant-server
|
||||
(http/run-server #'consultant-app
|
||||
{:port port
|
||||
:legacy-return-value? false})))))
|
||||
|
||||
(defn- connect-to-ldap
|
||||
[& {:keys [ldap-host ldap-port bind-dn bind-password]}]
|
||||
(reset! ldap-connection-pool
|
||||
(or @ldap-connection-pool
|
||||
(ldap/connect {:host {:address ldap-host
|
||||
:port ldap-port}
|
||||
:max-connections 8
|
||||
:bind-dn bind-dn
|
||||
:password bind-password}))))
|
||||
|
||||
(defn- main* [& opts]
|
||||
(and (apply connect-to-ldap opts)
|
||||
(apply start-consultant opts)))
|
||||
|
||||
(comment
|
||||
(let [ask (let [base-dn "dc=identify,dc=deertopia,dc=net"]
|
||||
(consultant-app {:port 8080 :ldap-host "192.168.68.79" :ldap-port 3890
|
||||
:base-dn base-dn
|
||||
:bind-dn (str "uid=nginx-bind-user,ou=people," base-dn)
|
||||
:bind-password "secret123"}))]
|
||||
(ask {})))
|
||||
|
||||
(comment ; Start on :8080
|
||||
(let [base-dn "dc=identify,dc=deertopia,dc=net"]
|
||||
(main* :port 8080 :ldap-host "192.168.68.79" :ldap-port 3890 :base-dn base-dn
|
||||
:bind-dn (str "uid=nginx-bind-user,ou=people," base-dn)
|
||||
:bind-password "secret123")))
|
||||
|
||||
(comment ; Shutdown
|
||||
(stop-consultant!))
|
||||
|
||||
(defn -main [& args]
|
||||
(main* (cli/parse-opts args cli-spec)))
|
||||
Reference in New Issue
Block a user