diff --git a/code/src/sixsq/nuvla/server/resources/nuvlabox.clj b/code/src/sixsq/nuvla/server/resources/nuvlabox.clj index f8a528c5d..cba01eebb 100644 --- a/code/src/sixsq/nuvla/server/resources/nuvlabox.clj +++ b/code/src/sixsq/nuvla/server/resources/nuvlabox.clj @@ -968,6 +968,53 @@ particular NuvlaBox release. (or (ex-data e) (throw e))))) +;; +;; Setup a websocket connection to the NB +;; + + + +(defn create-websocket + [{:keys [id state acl] :as nuvlabox} websocket-token] + (if (= state state-commissioned) + (if (nil? websocket-token) + (logu/log-and-throw-400 "Cannot create a websocket without a secure token") + (do + (log/warn "Starting an SSH session via a websocket, with the authn token " websocket-token " for NuvlaBox " id) + (try + (let [{{job-id :resource-id + job-status :status} :body} (job/create-job + id "nuvlabox_ssh" + (-> acl + (a/acl-append :edit-data id) + (a/acl-append :manage id)) + :payload (json/write-str {:token websocket-token}) + :priority 50 + :execution-mode (utils/get-execution-mode nuvlabox)) + job-msg (str "starting SSH websocket session with token " websocket-token + " for NuvlaBox " id " with async " job-id)] + (when (not= job-status 201) + (throw (r/ex-response + "unable to create async job to SSH to NuvlaBox" 500 id))) + (event-utils/create-event id job-msg acl) + (r/map-response job-msg 202 id job-id)) + (catch Exception e + (or (ex-data e) (throw e)))))) + (logu/log-and-throw-400 (str "invalid state for NuvlaBox SSH action: " state)))) + + +(defmethod crud/do-action [resource-type "ssh"] + [{{uuid :uuid} :params body :body :as request}] + (try + (let [id (str resource-type "/" uuid) + token (:token body)] + (-> (db/retrieve id request) + (a/throw-cannot-manage request) + (create-websocket token))) + (catch Exception e + (or (ex-data e) (throw e))))) + + ;; ;; Set operation ;; @@ -1001,6 +1048,7 @@ particular NuvlaBox release. disable-host-mgmt-op (u/action-map id :disable-host-level-management) enable-emergency-op (u/action-map id :enable-emergency-playbooks) generate-new-key-op (u/action-map id :generate-new-api-key) + ssh-op (u/action-map id :ssh) ops (cond-> [] (a/can-edit? resource request) (conj edit-op) (and (a/can-delete? resource request) @@ -1041,7 +1089,9 @@ particular NuvlaBox release. (contains? resource :host-level-management-api-key)) (conj disable-host-mgmt-op) (and (a/can-manage? resource request) (not= state state-decommissioned) - (not= state state-decommissioning)) (conj generate-new-key-op))] + (not= state state-decommissioning)) (conj generate-new-key-op) + (and (a/can-manage? resource request) + (#{state-commissioned} state)) (conj ssh-op))] (assoc resource :operations ops))) ;; diff --git a/code/test/sixsq/nuvla/server/resources/nuvlabox_2_lifecycle_test.clj b/code/test/sixsq/nuvla/server/resources/nuvlabox_2_lifecycle_test.clj index dd4992c26..e503dfb0e 100644 --- a/code/test/sixsq/nuvla/server/resources/nuvlabox_2_lifecycle_test.clj +++ b/code/test/sixsq/nuvla/server/resources/nuvlabox_2_lifecycle_test.clj @@ -504,6 +504,7 @@ (ltu/is-operation-present :update-nuvlabox) (ltu/is-operation-present :cluster-nuvlabox) (ltu/is-operation-present :assemble-playbooks) + (ltu/is-operation-present :ssh) (ltu/is-key-value :state "COMMISSIONED") (ltu/get-op-url :cluster-nuvlabox))] @@ -1622,6 +1623,26 @@ (ltu/body->edn) (ltu/is-status 403))) + + (let [ssh (-> session-owner + (request nuvlabox-url) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/get-op-url :ssh)) + job-url (-> session-owner + (request ssh + :request-method :post + :body (json/write-str {:token "xyz"})) + (ltu/body->edn) + (ltu/is-status 202) + (ltu/location-url))] + + (-> session-admin + (request job-url) + (ltu/body->edn) + (ltu/is-status 200) + (ltu/is-key-value :payload "{\"token\":\"xyz\"}"))) + )))))