18887: Fix salted_secret check. Add test.
[arvados.git] / services / api / app / models / api_client_authorization.rb
index a6beaa07ab38b6a177e9a466f7cd50f737b0edaa..52922d32b1868fdb53d8bcd3f1197d149a93bb63 100644 (file)
@@ -35,7 +35,12 @@ class ApiClientAuthorization < ArvadosModel
   UNLOGGED_CHANGES = ['last_used_at', 'last_used_by_ip_address', 'updated_at']
 
   def assign_random_api_token
-    self.api_token ||= rand(2**256).to_s(36)
+    begin
+      self.api_token ||= rand(2**256).to_s(36)
+    rescue ActiveModel::MissingAttributeError
+      # Ignore the case where self.api_token doesn't exist, which happens when
+      # the select=[...] is used.
+    end
   end
 
   def owner_uuid
@@ -111,12 +116,13 @@ class ApiClientAuthorization < ArvadosModel
     clnt
   end
 
-  def self.check_anonymous_user_token token
+  def self.check_anonymous_user_token(token:, remote:)
     case token[0..2]
     when 'v2/'
       _, token_uuid, secret, optional = token.split('/')
-      unless token_uuid.andand.length == 27 && secret.andand.length.andand > 0
-        # invalid token
+      unless token_uuid.andand.length == 27 && secret.andand.length.andand > 0 &&
+             token_uuid == Rails.configuration.ClusterID+"-gj3su-anonymouspublic"
+        # invalid v2 token, or v2 token for another user
         return nil
       end
     else
@@ -124,12 +130,18 @@ class ApiClientAuthorization < ArvadosModel
       secret = token
     end
 
+    # Usually, the secret is salted
+    salted_secret = OpenSSL::HMAC.hexdigest('sha1', Rails.configuration.Users.AnonymousUserToken, remote)
+
+    # The anonymous token could be specified as a full v2 token in the config,
+    # but the config loader strips it down to the secret part.
     # The anonymous token content and minimum length is verified in lib/config
-    if secret.length >= 0 && secret == Rails.configuration.Users.AnonymousUserToken
+    if secret.length >= 0 && (secret == Rails.configuration.Users.AnonymousUserToken || secret == salted_secret)
       return ApiClientAuthorization.new(user: User.find_by_uuid(anonymous_user_uuid),
                                         uuid: Rails.configuration.ClusterID+"-gj3su-anonymouspublic",
-                                        api_token: token,
-                                        api_client: anonymous_user_token_api_client)
+                                        api_token: secret,
+                                        api_client: anonymous_user_token_api_client,
+                                        scopes: ['GET /'])
     else
       return nil
     end
@@ -150,7 +162,7 @@ class ApiClientAuthorization < ArvadosModel
     return nil if token.nil? or token.empty?
     remote ||= Rails.configuration.ClusterID
 
-    auth = self.check_anonymous_user_token(token)
+    auth = self.check_anonymous_user_token(token: token, remote: remote)
     if !auth.nil?
       return auth
     end