관리자로 승급할 때 `run_second_factor!` 실패

Can't upgrade user to admin - unhandled server error 의 후속 내용입니다.

(@Discoursenaut 안녕하세요.) 오후 내내 이 문제를 해결하려 애썼습니다. 여전히 실제 문제의 원인을 파악하지 못했지만, 1099번째 줄(manager.run!) 주위에 rescue를 추가하면 "An unhandled server error has occurred."라는 신비로운 오류가 발생합니다. 소스 코드 어디에서도 해당 문자열을 찾을 수 없습니다.

result가 정의되어 있지 않아 나중에 실패하기 때문에, 오류를 잡아도 도움이 되지 않습니다.

2FA를 활성화/비활성화한 사용자와 enforce_second_factor가 꺼져/스태프인 경우의 모든 조합을 시도해 보았습니다. 이상하게도, 오늘 제 사용자를 추가하고 다른 관리자 계정으로 관리자 권한을 부여하려고 했을 때는 예상대로 작동했지만, 다른 어떤 관리자도 다른 사용자를 관리자로 승격할 수 없다고 합니다. 이들은 이 문제가 1년 동안 지속되어 왔다고 합니다. 데이터베이스에 문제가 있는 것일까요?

최근 빌드입니다(최소 오늘자). 표준 플러그인만 사용 중이며, 안전 모드에서도 마찬가지입니다.

@Osama, 몇 줄 뒤에 댓글을 남기셨는데, 혹시 아이디어가 있으신가요?

주어진 조건에서 result가 어떻게 undefined가 될 수 있는지 이해가 되지 않습니다:

정말 최신 버전으로 업데이트되어 있는지 확인해 보셨나요?

오늘 리빌드를 실행했습니다.

디버그 로그를 다른 위치에 저장할 수 있는 방법이 있을까요?

최소 재현 사례(예: 사이트 설정 목록과 해당 값)를 제공해 주시면 큰 도움이 될 것입니다.

메서드 전체를 rescue하여 에러를 로그로 기록할 수 있을까요?

def run_second_factor!(action_class, action_data: nil, target_user: current_user)
  if current_user && target_user != current_user
    # Anon can run 2fa against another target, but logged-in users should not.
    # This should be validated at the `run_second_factor!` call site.
    raise "running 2fa against another user is not allowed"
  end

  action = action_class.new(guardian, request, opts: action_data, target_user: target_user)
  manager = SecondFactor::AuthManager.new(guardian, action, target_user: target_user)
  yield(manager) if block_given?
  result = manager.run!(request, params, secure_session)

  if !result.no_second_factors_enabled? && !result.second_factor_auth_completed? &&
       !result.second_factor_auth_skipped?
    # should never happen, but I want to know if somehow it does! (osama)
    raise "2fa process ended up in a bad state!"
  end

  result
+rescue => err
+  Rails.logger.error(err.full_message)
+  raise
end

이 변경 사항을 적용한 후(Unicorn 워커를 재로드하면) /logs에 무언가 표시되어야 하며, 이를 통해 문제가 무엇인지 파악하는 데 도움이 될 것입니다.

아, 참. run_second_factor!의 오류는 제 디버깅 문장에서 비롯된 것 같습니다. 버그를 찾다가 오히려 버그를 만드는 것은 제 취미 중 하나이기도 하죠.

Started PUT "/admin/users/30591/grant_admin" for 174.50.213.142 at 2024-07-02 14:14:38 +0000
Processing by Admin::UsersController#grant_admin as */*
  Parameters: {"user_id"=>"30591"}
Completed 403 Forbidden in 6ms (Views: 0.1ms | ActiveRecord: 0.0ms | Allocations: 2263)

guardian이 어떤 이유로든 사용자를 관리자로 만들지 못하게 막고 있는 것 같습니다.

하지만 여전히 왜 실패하는지, 그리고 Discourse 코드 어디에서도 해당 오류를 찾을 수 없는데 왜 An unhandled server error has occurred.라는 오류 메시지가 뜨는지는 이해가 되지 않습니다.

아, 그리고 이것도 흥미롭네요. jay@example.com에서 myaddress@gmail.com으로 이메일을 변경할 수는 있었는데, myaddress+123@gmail.com 주소를 확인하려고 하면 역시 “An unhandled server error has occurred.” 메시지가 표시됩니다. normalize_emails는 설정되어 있지 않습니다.

run_second_factor!에 뭔가 문제가 있는 것 같지만, 정확히 무엇이 문제인지는 파악이 되지 않습니다. Rails.logger.warn와 몇 가지 xxx.inspect를 추가해서 뭔가 찾을 수 있을지 해볼 생각입니다.

제가 파악할 수 있는 바로는 auth_manager에 문제가 있는 것 같습니다. 어떤 이유로 리다이렉트를 시도하고 있는 것처럼 보이거든요. 일반 사용자에게는 2FA가 필수 사항이 아니기 때문에, 왜 일반 사용자가 이메일 주소를 변경하지 못하는지 모르겠습니다. 하지만 2FA가 없고 백업 코드가 없는 사용자로 시도해 보았고, 새 이메일 확인 링크를 클릭하기 전에 로그인한 상태와 로그인 후 상태 모두에서 시도해 보았지만, 모두 “An unhandled server error has occurred.” 오류로 실패했습니다.

이것과 관련이 있어 보입니다:

403 오류는 정상적이고 예상되는 것입니다 — 프론트엔드 앱은 403 응답을 포착하여 "2FA가 필요하여 관리자 권한을 부여할 수 없으므로 2FA 페이지로 이동하자"라고 해석합니다.

정상적이지 않은 부분은 다음과 같습니다:

이 오류를 어디서 보고 계신지 알려 주실 수 있을까요? 프론트엔드 팝업인가요? 로그에 기록된 오류인가요? 언급하신 대로 코드베이스 전체의 히스토리 어디에서도 이 오류 메시지를 찾을 수 없어 매우 이상합니다.

그러면 백엔드가 2FA URL을 포함하는 내용을 렌더링하지 않는 건가요? 하지만 이 에러는 사용자가 2FA를 켜고 있든 꺼두었든, force-2fa 사이트 설정이 활성화되어 있든 없든, 그리고 사용자가 이미 2FA로 로그인되어 있든 상관없이 발생합니다.

맞습니다. 세이프 모드를 시도해 보았지만, 현재 설치된 플러그인은 다음과 같습니다:

          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-topic-voting.git
          - git clone https://github.com/discourse/discourse-chat-integration.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/discourse/discourse-reactions.git
          - git clone https://github.com/discourse/discourse-docs.git
          - git clone https://github.com/discourse/discourse-user-notes.git

발견한 유일한 단서는 이 메시지가 Rails 자체에서 온다는 것을 시사한다는 점입니다. 하지만 그것이 어떻게 일어나는지는 아직 파악하지 못했습니다.

아마도 2FA가 실제로 필요하지 않은 상황에서 “2FA가 필요하다”는 신호를 트리거하는 어떤 요인이 작용하고 있는 것 같습니다. 2FA가 설정되어 있지 않은 상태에서 2FA 로그인을 유도하는 에러가 발생하는 것은 분명히 그럴듯합니다. 아마도 guardian 안에 그런 로직이 있는 것 같은데, 디버깅을 위해 Rails.logger를 어디에 배치해야 할지 모르겠습니다.

이것은 매우 희망적인 시도라, 완전히 터무니없는 말을 하고 있다면 양해 부탁드립니다… 하지만 " An unhandled server error has occurred"로 검색하면 단독으로 Bitwarden 코드를 가리키고 있습니다. 이는 로컬 시스템에서 요청을 가로채거나 방해하는 무언가가 있을 수 있다는 추측을 하게 만듭니다. 다른 컴퓨터에서 이를 재현할 수 있으신가요?

브라우저의 개발자 도구에서 네트워크 탭을 확인하고 grant_admin 엔드포인트에 대한 요청의 응답이 어떤지 확인해 주시겠어요?

페이로드 탭도 함께 보여 주세요.

image

이것은 서버에서 오는 것 같습니다. 데이터베이스(예: 사용자 정의 텍스트)에서 해당 문자열을 찾을 수 없으며, /var/www/discourse 전체를 grep으로 검색해도 나오지 않습니다.

Payload 탭도 없습니다:

image

잠깐!!! 데이터베이스를 다른 서버로 복원했는데, 2단계 인증 페이지로 올바르게 리디렉션됩니다. 그리고 2단계 인증 키를 받은 후, 즉시 사용자의 관리자 권한이 변경됩니다(이메일 확인이 필요 없었죠! 이 사실은 몰랐습니다!).

즉, 뭔가 . . . 무언가와 관련된 문제인 것 같습니다. 하지만 깨끗하고 표준적인 설치 환경에서는 문제가 해결됩니다. 어쨌든, (명백히) :discourse: :bug: 는 아닙니다. 카테고리를 변경했습니다.

또 다른 가능성으로, 이 역시 다소 터무니없지만, UserSecondFactor 모델에 뭔가 문제가 있는 것입니다. 테스트 서버의 도메인 이름이 달랐기 때문에 UserSecondFactor.all.destroy_all;UserSecurityKey.all.destroy_all;을 실행했거든요. 또한 Yubi 키 대신 Google Authenticator를 사용했습니다.