Move signature verification stoplight to the requests themselves (#10813)
* Move signature verification stoplight to the requests themselves This avoids blocking messages from known keys for 5 minutes when only one fails… * Put the stoplight on the actual client IP, not a potential reverse proxy
This commit is contained in:
		
							parent
							
								
									369eb63321
								
							
						
					
					
						commit
						89d600bedb
					
				@ -43,13 +43,7 @@ module SignatureVerification
 | 
				
			|||||||
      return
 | 
					      return
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    account_stoplight = Stoplight("source:#{request.ip}") { account_from_key_id(signature_params['keyId']) }
 | 
					    account = account_from_key_id(signature_params['keyId'])
 | 
				
			||||||
      .with_fallback { nil }
 | 
					 | 
				
			||||||
      .with_threshold(1)
 | 
					 | 
				
			||||||
      .with_cool_off_time(5.minutes.seconds)
 | 
					 | 
				
			||||||
      .with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    account = account_stoplight.run
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if account.nil?
 | 
					    if account.nil?
 | 
				
			||||||
      @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
 | 
					      @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
 | 
				
			||||||
@ -62,13 +56,7 @@ module SignatureVerification
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return account unless verify_signature(account, signature, compare_signed_string).nil?
 | 
					    return account unless verify_signature(account, signature, compare_signed_string).nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    account_stoplight = Stoplight("source:#{request.ip}") { account.possibly_stale? ? account.refresh! : account_refresh_key(account) }
 | 
					    account = stoplight_wrap_request { account.possibly_stale? ? account.refresh! : account_refresh_key(account) }
 | 
				
			||||||
      .with_fallback { nil }
 | 
					 | 
				
			||||||
      .with_threshold(1)
 | 
					 | 
				
			||||||
      .with_cool_off_time(5.minutes.seconds)
 | 
					 | 
				
			||||||
      .with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    account = account_stoplight.run
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if account.nil?
 | 
					    if account.nil?
 | 
				
			||||||
      @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
 | 
					      @signature_verification_failure_reason = "Public key not found for key #{signature_params['keyId']}"
 | 
				
			||||||
@ -136,14 +124,23 @@ module SignatureVerification
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def account_from_key_id(key_id)
 | 
					  def account_from_key_id(key_id)
 | 
				
			||||||
    if key_id.start_with?('acct:')
 | 
					    if key_id.start_with?('acct:')
 | 
				
			||||||
      ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, ''))
 | 
					      stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, '')) }
 | 
				
			||||||
    elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
 | 
					    elsif !ActivityPub::TagManager.instance.local_uri?(key_id)
 | 
				
			||||||
      account   = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account)
 | 
					      account   = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account)
 | 
				
			||||||
      account ||= ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false)
 | 
					      account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false) }
 | 
				
			||||||
      account
 | 
					      account
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def stoplight_wrap_request(&block)
 | 
				
			||||||
 | 
					    Stoplight("source:#{request.remote_ip}", &block)
 | 
				
			||||||
 | 
					      .with_fallback { nil }
 | 
				
			||||||
 | 
					      .with_threshold(1)
 | 
				
			||||||
 | 
					      .with_cool_off_time(5.minutes.seconds)
 | 
				
			||||||
 | 
					      .with_error_handler { |error, handle| error.is_a?(HTTP::Error) ? handle.call(error) : raise(error) }
 | 
				
			||||||
 | 
					      .run
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def account_refresh_key(account)
 | 
					  def account_refresh_key(account)
 | 
				
			||||||
    return if account.local? || !account.activitypub?
 | 
					    return if account.local? || !account.activitypub?
 | 
				
			||||||
    ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true)
 | 
					    ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user