fudo-service/test/fudo/server_test.clj

316 lines
12 KiB
Clojure

(ns fudo.server-test
(:require [fudo.api.request.generator :as gen]
[fudo.api.request :as req]
[fudo.server.config :as config]
[fudo.server.services.dyndns :as dyndns]
[fudo.server.services.auth :as auth]
[fudo.server.service :as service]
[fudo.server.services :as services]
[fudo.crypto.utils :as crypt]
[fudo.crypto.keys :as key]
[fudo.db.dyndns-db :as dyndns-db]
[fudo.db.transient-dyndns-db :as test-dyndns-db]
[fudo.db.auth-db :as auth-db]
[fudo.db.transient-auth-db :as test-auth-db]
[fudo.net.ip :as ip]
[fudo.net.dns :as dns]
[fudo.api.request.authenticator.auth-db :as authenticator]
[clojure.data.json :as json]
[clojure.test :refer [deftest is]]
[orchestra.spec.test :as spectest]))
(defn pp [obj]
(println (format "TEST_DBG: %s" obj))
obj)
(spectest/instrument)
(let [test-domain "test.com"
test-host "my-host"
config (config/init-mock-config {})
test-v4ip "4.3.2.1"
test-v6ip "6::2"
test-sshfp ["0 0 b9c019543f72777aee2d9b4ba883856f2f1f83e4e62ee8717"
"1 1 00a8f69cddae085451dec5d7b54e36e0bedb42241728751b81355f7abe8f99ffb"]
test-hosts {
"my-v4ip-host" {::dns/v4ip (ip/address test-v4ip)}
"my-v6ip-host" {::dns/v6ip (ip/address test-v6ip)}
"my-sshfp-host" {::dns/sshfp test-sshfp}
}
dyndns-db (test-dyndns-db/create true config test-domain test-hosts)
dyndns-service (service/initialize (dyndns/create true config dyndns-db))
dyndns-handler (service/generate-handler dyndns-service)]
(deftest dyndns-domain
(is (= test-domain
(-> (gen/make-get "/dyndns/domain")
(gen/add-host-header test-host)
dyndns-handler
:body
clojure.string/trim))))
(deftest dyndns-domain-success
(is (= 200
(-> (gen/make-get "/dyndns/domain")
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest insert-v4ip
(is (= 200
(-> (gen/make-put (format "/dyndns/%s/v4ip" test-host) "4.3.2.1")
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-v4ip
(is (= (ip/address test-v4ip)
(-> (gen/make-get (format "/dyndns/my-v4ip-host/v4ip"))
(gen/add-host-header test-host)
dyndns-handler
:body
clojure.string/trim
ip/address))))
(deftest read-v4ip-success
(is (= 200
(-> (gen/make-get (format "/dyndns/my-v4ip-host/v4ip"))
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest insert-v6ip
(is (= 200
(-> (gen/make-put (format "/dyndns/%s/v6ip" test-host) "4::1")
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-v6ip
(is (= (ip/address test-v6ip)
(-> (gen/make-get (format "/dyndns/my-v6ip-host/v6ip"))
(gen/add-host-header test-host)
dyndns-handler
:body
clojure.string/trim
ip/address))))
(deftest read-v6ip-success
(is (= 200
(-> (gen/make-get (format "/dyndns/my-v6ip-host/v6ip"))
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest insert-sshfp
(is (= 200
(-> (gen/make-put (format "/dyndns/%s/sshfp" test-host)
(clojure.string/join "\n" test-sshfp))
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-sshfp
(is (= test-sshfp
(-> (gen/make-get (format "/dyndns/my-sshfp-host/sshfp"))
(gen/add-host-header test-host)
dyndns-handler
:body
clojure.string/trim
(clojure.string/split #"\n")))))
(deftest read-sshfp-success
(is (= 200
(-> (gen/make-get (format "/dyndns/my-sshfp-host/sshfp"))
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-missing-v4ip
(is (= 404
(-> (gen/make-get "/dyndns/nonexistent-host/v4ip")
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-missing-v6ip
(is (= 404
(-> (gen/make-get "/dyndns/nonexistent-host/v6ip")
(gen/add-host-header test-host)
dyndns-handler
:status))))
(deftest read-missing-sshfp
(is (= 404
(-> (gen/make-get "/dyndns/nonexistent-host/sshfp")
(gen/add-host-header test-host)
dyndns-handler
:status)))))
(let [config (config/init-mock-config {})
keypair (key/generate-public-private-pair)
pubkey (-> keypair ::key/public-key)
key-id (-> pubkey key/pubkey->string crypt/sha1-hash)
test-host "test-host"
auth-hosts {test-host (auth-db/make-entity test-host pubkey)}
auth-db (test-auth-db/create true config auth-hosts)
auth-service (auth/create true config auth-db)
auth-handler (service/generate-handler auth-service)]
(deftest get-key
(is (= (key/pubkey->string pubkey)
(-> (gen/make-get (format "/auth/entity/%s/key" test-host))
(gen/add-host-header test-host)
auth-handler
:body
clojure.string/trim))))
(deftest get-key-success
(is (= 200
(-> (gen/make-get (format "/auth/entity/%s/key" test-host))
(gen/add-host-header test-host)
auth-handler
:status))))
(deftest get-missing-key
(is (= 404
(-> (gen/make-get "/auth/entity/nonexistent-host/key")
(gen/add-host-header test-host)
auth-handler
:status))))
(deftest get-key-id
(is (= key-id
(-> (gen/make-get (format "/auth/entity/%s/key-id" test-host))
(gen/add-host-header test-host)
auth-handler
:body
clojure.string/trim))))
(deftest get-key-id-success
(is (= 200
(-> (gen/make-get (format "/auth/entity/%s/key-id" test-host))
(gen/add-host-header test-host)
auth-handler
:status))))
(deftest get-missing-key-id
(is (= 404
(-> (gen/make-get "/auth/entity/nonexistent-host/key-id")
(gen/add-host-header test-host)
auth-handler
:status)))))
(let [debug false
test-domain "test.com"
test-host "my-host"
config (config/init-mock-config {"FUDO_SECRET" "test-secret"})
keypair (key/generate-public-private-pair)
privkey (-> keypair ::key/private-key)
pubkey (-> keypair ::key/public-key)
key-id (-> pubkey key/pubkey->string crypt/sha1-hash)
auth-hosts {test-host (auth-db/make-entity test-host pubkey)}
auth-db (test-auth-db/create debug config auth-hosts)
auth-service (auth/create debug config auth-db)
test-v4ip "4.3.2.1"
test-v6ip "6::2"
test-sshfp ["0 0 b9c019543f72777aee2d9b4ba883856f2f1f83e4e62ee8717"
"1 1 00a8f69cddae085451dec5d7b54e36e0bedb42241728751b81355f7abe8f99ffb"]
test-hosts {
"my-v4ip-host" {::dns/v4ip (ip/address test-v4ip)}
"my-v6ip-host" {::dns/v6ip (ip/address test-v6ip)}
"my-sshfp-host" {::dns/sshfp test-sshfp}
}
dyndns-db (test-dyndns-db/create debug config test-domain test-hosts)
dyndns-service (service/initialize (dyndns/create debug config dyndns-db))
authenticator (authenticator/init-mock debug config auth-db)
local-services {:services [auth-service dyndns-service]}
services (services/init-mock debug config local-services authenticator)
handler (service/generate-handler services)
get-result (fn [url]
(-> (gen/make-get url)
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
handler))
get-status (fn [url] (:status (get-result url)))
get-body (fn [url] (json/read-str (:body (get-result url))))
put-result (fn [url data]
(-> (gen/make-put url (json/write-str data))
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
handler))
put-status (fn [url data] (:status (pp (put-result url data))))]
(deftest authenticated-get-v4ip-success
(is (= 200 (get-status "/api/private/dyndns/my-v4ip-host/v4ip"))))
(deftest authenticated-get-v4ip
(is (= (ip/address test-v4ip)
(ip/address (get-body (format "/api/private/dyndns/my-v4ip-host/v4ip"))))))
(deftest authenticated-get-missing-v4ip
(is (= 404 (get-status "/api/private/dyndns/nonexistent-host/v4ip"))))
(deftest authenticated-put-new-v4ip-unauthorized
(is (= 401 (put-status "/api/private/dyndns/new-host/v4ip" "4.5.3.6"))))
(deftest authenticated-put-new-v4ip-authorized
(is (= 200 (put-status (format "/api/private/dyndns/%s/v4ip" test-host)
"4.5.3.6"))))
(deftest authenticated-put-new-v6ip-unauthorized
(is (= 401 (put-status "/api/private/dyndns/other-host/v6ip" "5::3"))))
(deftest authenticated-put-new-v6ip-authorized
(is (= 200 (put-status (format "/api/private/dyndns/%s/v6ip" test-host) "5::3"))))
(deftest authenticated-get-v6ip-success
(is (= 200 (get-status "/api/private/dyndns/my-v6ip-host/v6ip"))))
(deftest authenticated-get-v6ip
(is (= (ip/address test-v6ip)
(ip/address (get-body "/api/private/dyndns/my-v6ip-host/v6ip")))))
(deftest authenticated-get-missing-v6ip
(is (= 404 (get-status "/api/private/dyndns/nonexistent-host/v6ip"))))
(deftest missing-fudo-secret
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/authenticate-request test-host privkey key-id)
handler
:status))))
(deftest missing-fudo-entity-header
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
(gen/remove-header "fudo-entity")
handler
:status))))
(deftest missing-fudo-key-id-header
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
(gen/remove-header "fudo-key-id")
handler
:status))))
(deftest missing-fudo-timestamp-header
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
(gen/remove-header "fudo-timestamp")
handler
:status))))
(deftest missing-fudo-signature-header
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
(gen/remove-header "fudo-signature")
handler
:status))))
(deftest bad-fudo-signature-header
(is (= 400
(-> (gen/make-get "/api/private/dyndns/my-v4ip-host/v4ip")
(gen/add-fudo-secret "test-secret")
(gen/authenticate-request test-host privkey key-id)
(req/set-header "fudo-signature" "gobbledigook")
handler
:status)))))