14260: Additional validation when container uuid is provided in token
authorPeter Amstutz <pamstutz@veritasgenetics.com>
Mon, 15 Oct 2018 15:02:38 +0000 (11:02 -0400)
committerPeter Amstutz <pamstutz@veritasgenetics.com>
Mon, 15 Oct 2018 15:02:38 +0000 (11:02 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz@veritasgenetics.com>

services/api/app/models/api_client_authorization.rb
services/api/test/integration/container_auth_test.rb [new file with mode: 0644]

index 12ef8eb3eb5a2abede54c35919a8b72c815a357c..53ae6af46426cadd55bf7ec4ae1cc94659ef1c0f 100644 (file)
@@ -98,11 +98,31 @@ class ApiClientAuthorization < ArvadosModel
 
     case token[0..2]
     when 'v2/'
-      _, uuid, secret = token.split('/')
+      _, uuid, secret, optional = token.split('/')
       unless uuid.andand.length == 27 && secret.andand.length.andand > 0
         return nil
       end
 
+      if !optional.nil?
+        # if "optional" is a container uuid, check that it
+        # matches expections.
+        c = Container.where(uuid: optional).first
+        if !c.nil?
+          if !c.auth_uuid.nil? and c.auth_uuid != uuid
+            # token doesn't match the container's token
+            return nil
+          end
+          if !c.runtime_token.nil? and "v2/#{uuid}/#{secret}" != c.runtime_token
+            # token doesn't match the container's token
+            return nil
+          end
+          if ![Container::Locked, Container::Running].include?(c.state)
+            # container isn't locked or running, token shouldn't be used
+            return nil
+          end
+        end
+      end
+
       auth = ApiClientAuthorization.
              includes(:user, :api_client).
              where('uuid=? and (expires_at is null or expires_at > CURRENT_TIMESTAMP)', uuid).
diff --git a/services/api/test/integration/container_auth_test.rb b/services/api/test/integration/container_auth_test.rb
new file mode 100644 (file)
index 0000000..bec8b57
--- /dev/null
@@ -0,0 +1,69 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+require 'test_helper'
+
+class ContainerAuthTest < ActionDispatch::IntegrationTest
+  fixtures :all
+
+  test "container token validate, Queued" do
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:container_runtime_token).token}/#{containers(:runtime_token).uuid}"}
+    # Container is Queued, token cannot be used
+    assert_response 401
+  end
+
+  test "container token validate, Running, regular auth" do
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:running_container_auth).token}/#{containers(:running).uuid}"}
+    # Container is Running, token can be used
+    assert_response :success
+    assert_equal containers(:running).uuid, json_response['uuid']
+  end
+
+  test "container token validate, Locked, runtime_token" do
+    post "/arvados/v1/containers/#{containers(:runtime_token).uuid}/lock", {
+      :format => :json
+    }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:dispatch1).token}"}
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:container_runtime_token).token}/#{containers(:runtime_token).uuid}"}
+    # Container is Running, token can be used
+    assert_response :success
+    assert_equal containers(:runtime_token).uuid, json_response['uuid']
+  end
+
+  test "container token validate, Running, without optional portion" do
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:running_container_auth).token}"}
+    # Container is Running, token can be used
+    assert_response :success
+    assert_equal containers(:running).uuid, json_response['uuid']
+  end
+
+  test "container token validate, Locked, runtime_token, without optional portion" do
+    post "/arvados/v1/containers/#{containers(:runtime_token).uuid}/lock", {
+      :format => :json
+    }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:dispatch1).token}"}
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:container_runtime_token).token}"}
+    # runtime_token without container uuid won't return 'current'
+    assert_response 404
+  end
+
+  test "container token validate, wrong container uuid" do
+    post "/arvados/v1/containers/#{containers(:runtime_token).uuid}/lock", {
+      :format => :json
+    }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:dispatch1).token}"}
+    get "/arvados/v1/containers/current", {
+      :format => :json
+        }, {'HTTP_AUTHORIZATION' => "Bearer #{api_client_authorizations(:container_runtime_token).token}/#{containers(:running).uuid}"}
+    # Container uuid mismatch, token can't be used
+    assert_response 401
+  end
+end