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).
--- /dev/null
+# 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