Skip to content

Commit

Permalink
feat: read GA4GH Visa signing keys from configurable files
Browse files Browse the repository at this point in the history
  • Loading branch information
opqdonut committed Oct 2, 2020
1 parent ce8109c commit a27468d
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 41 deletions.
3 changes: 3 additions & 0 deletions dev-config.edn
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@
:application-deadline-days 4
:enable-pdf-api true
:enable-permissions-api true
;; example keys from https://tools.ietf.org/html/rfc7517#appendix-A
:ga4gh-visa-private-key "test-data/example-private-key.jwk"
:ga4gh-visa-public-key "test-data/example-public-key.jwk"
:catalogue-is-public false}
4 changes: 4 additions & 0 deletions resources/config-defaults.edn
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@

;; enable /api/permissions/:user
:enable-permissions-api false
;; Keys for signing GA4GH Visas produced by permissions api.
;; Format: path to file containing key in JWK (Json Web Key) format
:ga4gh-visa-private-key nil
:ga4gh-visa-public-key nil

;; Should the catalogue be public and visible to everyone, i.e. also to not logged-in users.
:catalogue-is-public false
Expand Down
5 changes: 3 additions & 2 deletions src/clj/rems/api/permissions.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
[rems.api.util :as api-util] ; required for route :roles
[rems.db.entitlements :as entitlements]
[rems.config :as config]
[rems.ga4gh]
[ring.util.http-response :refer :all]
[schema.core :as s]))

Expand All @@ -20,7 +19,9 @@
:return s/Any
(if (not (:enable-permissions-api config/env))
(not-implemented "permissions api not implemented")
(ok {:keys [rems.ga4gh/+public-key+]}))))
(let [key (:ga4gh-visa-public-key config/env)]
(assert key ":ga4gh-visa-public-key not defined in config!")
(ok {:keys [key]})))))
(context "/permissions" []
:tags ["permissions"]
(GET "/:user" []
Expand Down
4 changes: 3 additions & 1 deletion src/clj/rems/api/public.clj
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@
:authentication "HIDDEN"
:database-url "HIDDEN"
:test-database-url "HIDDEN"
:oidc-client-secret "HIDDEN")))))
:oidc-client-secret "HIDDEN"
:ga4gh-visa-private-key "HIDDEN"
:ga4gh-visa-public-key "HIDDEN")))))

(def keepalive-api
(context "/keepalive" []
Expand Down
8 changes: 8 additions & 0 deletions src/clj/rems/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
:theme-static-resources (file-sibling file "public")})
config))

(defn load-keys [config]
(merge config
(when-let [key-file (get-file config :ga4gh-visa-private-key)]
{:ga4gh-visa-private-key (json/parse-string (slurp key-file))})
(when-let [key-file (get-file config :ga4gh-visa-public-key)]
{:ga4gh-visa-public-key (json/parse-string (slurp key-file))})))

(defn- parse-config [config]
(-> config
(update :email-retry-period #(Period/parse %))
Expand Down Expand Up @@ -75,6 +82,7 @@
;; If neither system property is defined, the :file parameter is silently ignored.
:file (System/getProperty "rems.config"))
(load-external-theme)
(load-keys)
(parse-config)
(validate-config)))

Expand Down
39 changes: 6 additions & 33 deletions src/clj/rems/ga4gh.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,6 @@
[schema.core :as s])
(:import org.joda.time.DateTime))

;; TODO real keys
;; example keys from https://tools.ietf.org/html/rfc7517#appendix-A
(def +public-key+
(json/parse-string
"{\"kty\":\"RSA\",
\"n\": \"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw\",
\"e\":\"AQAB\",
\"alg\":\"RS256\",
\"kid\":\"2011-04-29\"}"))

(def +private-key+
(json/parse-string
"{\"kty\":\"RSA\",
\"n\":\"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw\",
\"e\":\"AQAB\",
\"d\":\"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q\",
\"p\":\"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs\",
\"q\":\"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk\",
\"dp\":\"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0\",
\"dq\":\"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk\",
\"qi\":\"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU\",
\"alg\":\"RS256\",
\"kid\":\"2011-04-29\"}"))

(def +private-key-parsed+
(keys/jwk->private-key +private-key+))

(def +public-key-parsed+
(keys/jwk->public-key +public-key+))

(s/defschema VisaType
;; Official types from:
;; https://github.com/ga4gh-duri/ga4gh-duri.github.io/blob/master/researcher_ids/ga4gh_passport_v1.md#ga4gh-standard-passport-visa-type-definitions
Expand Down Expand Up @@ -69,11 +39,14 @@
(defn- visa-header []
{:jku (str (:public-url env) "api/jwk")
:typ "JWT"
:kid (:kid +private-key+)})
:kid (get-in env [:ga4gh-visa-private-key :kid])})

(defn- sign-visa [visa]
;; TODO look up algorithm from key?
(jwt/sign (s/validate VisaClaim visa) +private-key-parsed+ {:alg :rs256 :header (visa-header)}))
(let [key (:ga4gh-visa-private-key env)
parsed-key (keys/jwk->private-key key)]
(assert key ":ga4gh-visa-private-key config variable not set!")
;; TODO look up algorithm from key?
(jwt/sign (s/validate VisaClaim visa) parsed-key {:alg :rs256 :header (visa-header)})))

(def +default-length+ (time/years 1))

Expand Down
3 changes: 3 additions & 0 deletions test-config.edn
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
:languages [:en :fi :sv]
:enable-pdf-api true
:enable-permissions-api true
;; example keys from https://tools.ietf.org/html/rfc7517#appendix-A
:ga4gh-visa-private-key "test-data/example-private-key.jwk"
:ga4gh-visa-public-key "test-data/example-public-key.jwk"
:catalogue-is-public false}
11 changes: 11 additions & 0 deletions test-data/example-private-key.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{"kty":"RSA",
"n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
"e":"AQAB",
"d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqijwp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d_cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBznbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
"p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPVnwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqVWlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
"q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyumqjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgxkIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
"dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oimYwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_NmtuYZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
"dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUUvMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
"qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzgUIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rxyR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
"alg":"RS256",
"kid":"2011-04-29"}
5 changes: 5 additions & 0 deletions test-data/example-public-key.jwk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{"kty":"RSA",
"n": "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
"e":"AQAB",
"alg":"RS256",
"kid":"2011-04-29"}
9 changes: 4 additions & 5 deletions test/clj/rems/api/test_permissions.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns ^:integration rems.api.test-permissions
(:require [buddy.sign.jws :as buddy-jws]
[buddy.sign.jwt :as buddy-jwt]
[buddy.core.keys :as buddy-keys]
[clojure.test :refer :all]
[rems.api.testing :refer :all]
[rems.config]
Expand All @@ -11,10 +12,7 @@

(use-fixtures
:once
api-fixture
(fn [f]
(with-redefs [rems.config/env (assoc rems.config/env :enable-permissions-api true)]
(f))))
api-fixture)

(deftest jwk-api
(let [data (api-call :get "/api/jwk" nil nil nil)]
Expand All @@ -31,7 +29,8 @@
(defn- validate-alice-result [data]
(doseq [visa (:ga4gh_passport_v1 data)]
(let [header (buddy-jws/decode-header visa)
data (buddy-jwt/unsign visa ga4gh/+public-key-parsed+ {:alg :rs256})]
key (buddy-keys/jwk->public-key (rems.config/env :ga4gh-visa-public-key))
data (buddy-jwt/unsign visa key {:alg :rs256})]
(is (= (str (:public-url rems.config/env) "api/jwk") (:jku header)))
(is (= "JWT" (:typ header)))
(is (= "2011-04-29" (:kid header)))
Expand Down

0 comments on commit a27468d

Please sign in to comment.