ES /docs

error occurred while reprocess. capture_id: 30152, reason:Permission denied, user_id: 3615

RCA: error occurred while reprocess. capture_id: 30152, reason:Permission denied, user_id: 3615

Overview#

What Happened#

2026-04-29 22:57 UTC, cupixworks-worker 서비스(eu-central-1)에서 capture_id 30152에 대한 reprocess 요청이 Permission denied로 실패했다. user_id 3615과 user_id 2012 두 사용자가 각각 시도했으며, 두 건 모두 Pundit policy의 reinvoke? 권한 검사에서 거부되었다.

Quick Facts#

Field Value
exception.class Cupix::Errors::PermissionDenied
exception.message Permission denied
top_frame app/invokers/capture_invoker.rb:273
env production, eu-central-1

Timeline#

  1. 2026-04-29T22:57:13Z — user_id 3615가 capture 30152 reprocess 시도, Permission denied
  2. 2026-04-29T22:57:47Z — user_id 2012가 capture 30152 reprocess 시도, Permission denied
  3. 2026-04-29T22:58:35Z — user_id 8이 capture 30152 reprocess 시도, "Model has invalid state to reprocess" (다른 에러 — 권한은 통과)

Error Log#

Datadog Logs

text
error occurred while reprocess. capture_id: 30152, reason:Permission denied, user_id: 3615

Impact#

  • Service: cupixworks-worker
  • 발생 횟수: 2
  • 최초 발생: 2026-04-29T22:57:13.641Z
  • 최근 발생: 2026-04-29T22:57:47.647Z

Root Cause Summary#

user_id 3615와 user_id 2012는 reinvoke? 정책에서 요구하는 administrator 또는 capture_qa_managers 관리 그룹에 속하지 않아 reprocess 권한이 거부되었다. CapturePolicy#reinvoke?admin_administrator? (admin 팀 + administrator 그룹) 또는 capture_qa_managers 그룹 멤버십만 허용하며, 해당 사용자들은 이 조건을 충족하지 못했다. 이는 의도된 보안 동작이지만, 에러가 error 레벨로 로깅되어 불필요한 알림을 유발하고 있다.

Technical Analysis#

Code Path#

  • Entry point: app/controllers/cli/v1/captures_controller.rb:10 — CLI reinvoke 엔드포인트가 CaptureOperation.reinvoke_captures를 호출
  • Operation: app/operations/capture_operation.rb:22-39 — captures를 순회하며 CaptureInvoker#reprocess_capture 호출
  • Permission check: app/invokers/capture_invoker.rb:273 — Pundit policy 검사에서 PermissionDenied 발생
  • Error logging: app/operations/capture_operation.rb:33 — rescue에서 Cupix::Logger.error로 기록
app/invokers/capture_invoker.rb:272-274ruby
def reprocess_capture(opts = {})
  raise Cupix::Errors::PermissionDenied.new(code: 'PERM10000', reason: 'Permission denied') unless Pundit.policy(self.current_user, @model).reinvoke?
  raise Cupix::Errors::Entity.new(code: 'ENT10000', reason: 'Model has invalid state to reprocess') unless @model.reprocessible?
app/policies/capture_policy.rb:34-36ruby
def reinvoke?
  admin_administrator? || user.member_of_admin_groups?(%w[capture_qa_managers])
end
app/policies/concerns/sales_team_policy/deprecated.rb:5-7ruby
def admin_administrator?
  user.member_of_admin_groups?(%w[administrator])
end
app/models/concerns/admin_permission.rb:16-19ruby
def member_of_admin_groups?(groups)
  groups = parse_groups(groups)
  self.team.domain == 'admin' && member_of_groups?(groups)
end
app/operations/capture_operation.rb:26-35ruby
captures.each do |capture|
  Cupix::Logger.info("start reprocess captures. capture_id: #{capture.id}, user_id: #{current_user.id}")
  begin
    capture_invoker = CaptureInvoker.new(model: capture, current_user: current_user)
    capture_invoker.reprocess_capture
    results << { id: capture.id, status: 'success' }
  rescue StandardError => e
    Cupix::Logger.error("error occurred while reprocess. capture_id: #{capture.id}, reason:#{e.message}, user_id: #{current_user.id}", reprocess: { error: e })
    results << { id: capture.id, status: 'error', error: e.message }
  end
end

기대 동작: reinvoke? 정책이 admin 팀 + administrator/capture_qa_managers 그룹 멤버만 허용. 실제 동작: user_id 3615, 2012는 해당 그룹에 속하지 않아 PermissionDenied 발생. 이 예외가 CaptureOperationrescue StandardError에 잡혀 error 레벨로 로깅됨.

Log Evidence#

검색 쿼리:

text
service:cupixworks-worker status:error "error occurred while reprocess"
Time range: 2026-04-29T21:00:00Z to 2026-04-29T23:59:00Z
text
service:cupixworks-worker "capture_id: 30152"
Time range: 2026-04-29T21:00:00Z to 2026-04-29T23:59:00Z

핵심 로그 (시간순):

json
{"timestamp": "2026-04-30 07:57:13 KST", "status": "info", "message": "start reprocess captures. capture_id: 30152, user_id: 3615"}
json
{"timestamp": "2026-04-30 07:57:13 KST", "status": "error", "message": "error occurred while reprocess. capture_id: 30152, reason:Permission denied, user_id: 3615"}
json
{"timestamp": "2026-04-30 07:57:47 KST", "status": "info", "message": "start reprocess captures. capture_id: 30152, user_id: 2012"}
json
{"timestamp": "2026-04-30 07:57:47 KST", "status": "error", "message": "error occurred while reprocess. capture_id: 30152, reason:Permission denied, user_id: 2012"}
json
{"timestamp": "2026-04-30 07:58:35 KST", "status": "info", "message": "start reprocess captures. capture_id: 30152, user_id: 8"}
json
{"timestamp": "2026-04-30 07:58:35 KST", "status": "error", "message": "error occurred while reprocess. capture_id: 30152, reason:Model has invalid state to reprocess, user_id: 8"}

user_id 8은 권한 검사를 통과했으나(admin 사용자로 추정), capture가 이미 유효하지 않은 상태여서 ENT10000 에러 발생. 이는 user 3615/2012의 시도가 실패한 후 admin이 수동으로 개입한 것으로 보임.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 사용자가 reinvoke 권한이 없는 그룹에 속함 CapturePolicy#reinvoke?가 admin_administrator 또는 capture_qa_managers만 허용 (capture_policy.rb:34-36). user_id 8은 동일 capture에서 권한 통과. Confirmed
H2 인증 토큰 만료/무효화로 인한 일시적 권한 실패 동일 사용자의 요청이 인증까지는 성공(info 로그 "start reprocess" 기록됨). 두 명의 서로 다른 사용자에서 동일 에러 발생으로 토큰 문제 아님. Rejected
H3 에러 로그 레벨이 과도 — 권한 거부는 예상 시나리오 rescue StandardErrorPermissionDenied를 포함한 모든 에러를 error 레벨로 로깅 (capture_operation.rb:33). 권한 부족은 버그가 아닌 정상적인 접근 제어 동작. Confirmed

Fix Recommendation#

즉시 조치 (Critical)#

없음. 권한 검사 자체는 정상 동작하고 있으며 보안 문제 없음.

단기 개선 (1주 이내)#

  • app/operations/capture_operation.rb:33Cupix::Errors::PermissionDenied를 별도 rescue 절로 분리하여 warn 레벨로 로깅. 권한 거부는 예상되는 운영 시나리오이므로 error 레벨이 적절하지 않다.
app/operations/capture_operation.rb:26-35
 captures.each do |capture|   Cupix::Logger.info("start reprocess captures. capture_id: #{capture.id}, user_id: #{current_user.id}")   begin     capture_invoker = CaptureInvoker.new(model: capture, current_user: current_user)     capture_invoker.reprocess_capture     results << { id: capture.id, status: 'success' }+  rescue Cupix::Errors::PermissionDenied => e+    Cupix::Logger.warn("permission denied while reprocess. capture_id: #{capture.id}, user_id: #{current_user.id}")+    results << { id: capture.id, status: 'error', error: e.message }   rescue StandardError => e     Cupix::Logger.error("error occurred while reprocess. capture_id: #{capture.id}, reason:#{e.message}, user_id: #{current_user.id}", reprocess: { error: e })     results << { id: capture.id, status: 'error', error: e.message }   end end

장기 개선 (재발 방지)#

  • CLI/Admin API 엔드포인트에서 reprocess 호출 전에 사전 권한 검사를 수행하여, 권한 없는 사용자의 요청이 invoker까지 도달하지 않도록 필터링.
  • API 응답에 권한 부족 사유를 명확하게 반환하여, 프론트엔드/CLI에서 사용자에게 적절한 안내 제공.

Monitoring#

  • 권한 거부 빈도 추적:
text
service:cupixworks-worker "permission denied while reprocess"
  • 특정 사용자의 반복적 권한 거부 패턴 감지 (비인가 접근 시도 모니터링):
text
service:cupixworks-worker status:warn "permission denied" @user_id:*

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial