(ns metabase-enterprise.airgap (:require [buddy.core.keys :as keys] [buddy.sign.jwt :as jwt] [clojure.java.io :as io] [clojure.string :as str] [java-time.api :as t] [metabase.public-settings.premium-features :as premium-features :refer [defenterprise]] [metabase.util.i18n :refer [tru]] [metabase.util.malli :as mu] [metabase.util.malli.schema :as ms]) (:import [java.io Reader])) | |
(set! *warn-on-reflection* true) | |
(mu/defn- valid-now? :- :boolean [token :- premium-features/TokenStatus] (t/before? (t/instant) (t/instant (:valid-thru token)))) | |
(defn- token? [token] (and token (str/starts-with? token "airgap_"))) | |
(mu/defn- pubkey-reader :- [:maybe (ms/InstanceOfClass Reader)] ^Reader [] (when-let [pubkey-resource (io/resource "airgap/pubkey.pem")] (io/reader pubkey-resource))) | |
(mu/defn- decode-token :- :map "Given an encrypted airgap token, decrypts it and returns a TokenStatus" [token] (when-not (token? token) (throw (ex-info "Malformed airgap token" {:token token}))) (let [token (str/replace token #"^airgap_" ) pubkey-reader (pubkey-reader)] (when-not pubkey-reader (throw (ex-info "No public key available for airgap token" {}))) (let [pub-key (with-open [rdr pubkey-reader] (keys/public-key rdr)) decrypted (jwt/decrypt token pub-key {:alg :rsa-oaep :enc :a128cbc-hs256})] (if (valid-now? decrypted) decrypted {:valid false :status (tru "Unable to validate token") :error-details (tru "Token validation failed.")})))) | |
Decodes the airgap token and returns the decoded token. | (defenterprise decode-airgap-token :feature :none [token] (decode-token token)) |
Check that the decoded token is still valid and returns the decoded token. | (defenterprise token-valid-now? :feature :none [token-status] (valid-now? token-status)) |