From: Peter Amstutz Date: Mon, 15 Oct 2018 15:02:38 +0000 (-0400) Subject: 14260: Additional validation when container uuid is provided in token X-Git-Tag: 1.3.0~70^2~10 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/9277fdba1f3df9468b4d4e2a8f150bca635e48fb 14260: Additional validation when container uuid is provided in token Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- diff --git a/services/api/app/models/api_client_authorization.rb b/services/api/app/models/api_client_authorization.rb index 12ef8eb3eb..53ae6af464 100644 --- a/services/api/app/models/api_client_authorization.rb +++ b/services/api/app/models/api_client_authorization.rb @@ -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 index 0000000000..bec8b5784a --- /dev/null +++ b/services/api/test/integration/container_auth_test.rb @@ -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