조건부 OpenAPI

조건부 OpenAPI (Conditional OpenAPI)

필요하다면 설정(settings)과 환경 변수를 사용해서 환경에 따라 OpenAPI를 조건부로 구성할 수 있고, 심지어 완전히 비활성화할 수도 있어요.

출처: 공식문서

보안, API, 그리고 문서에 대해서

프로덕션에서 문서 사용자 인터페이스를 숨기는 것이 API를 보호하는 방법이 되어서는 안 돼요.

그건 API에 어떤 추가 보안도 더해주지 않아요. 경로 연산(path operations) 은 여전히 그 자리에서 사용 가능하니까요.

코드에 보안 결함이 있다면, 여전히 존재해요.

문서를 숨기는 것은 오히려 여러분의 API와 상호작용하는 방법을 이해하기 어렵게 만들 뿐이고, 프로덕션에서 디버깅하기도 더 어렵게 만들 수 있어요. 이는 단순히 일종의 졌보안(Security through obscurity) 으로 간주될 수 있어요.

API를 보호하고 싶다면, 더 나은 몇 가지 방법이 있어요, 예를 들면:

  • 요청 본문과 응답에 대해 잘 정의된 Pydantic 모델을 갖추세요.
  • 의존성(dependencies)을 사용해 필요한 권한과 역할을 구성하세요.
  • 평문 비밀번호를 절대 저장하지 말고, 오직 비밀번호 해시만 저장하세요.
  • pwdlib, JWT 토큰 같은 잘 알려진 암호화 도구를 구현하고 사용하세요.
  • 필요할 때 OAuth2 스코프로 더 세분화된 권한 제어를 추가하세요.
  • ...등등.

그럼에도 불구하고, 특정 환경(예: 프로덕션)이나 환경 변수의 구성에 따라 API 문서를 정말 비활성화해야 하는 아주 특수한 사용 사례가 있을 수 있어요.

설정과 환경 변수로 조건부 OpenAPI

같은 Pydantic 설정을 사용해서 생성되는 OpenAPI와 문서 UI를 쉽게 구성할 수 있어요.

예를 들어:

from fastapi import FastAPI
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    openapi_url: str = "/openapi.json"


settings = Settings()

app = FastAPI(openapi_url=settings.openapi_url)


@app.get("/")
def root():
    return {"message": "Hello World"}

여기서 openapi_url 설정을 "/openapi.json" 이라는 기본값과 함께 선언해요.

그런 다음 FastAPI 앱을 만들 때 그 값을 사용해요.

그리고 OPENAPI_URL 환경 변수를 빈 문자열로 설정하면 OpenAPI(문서 UI 포함)를 비활성화할 수 있어요:

$ OPENAPI_URL= uvicorn main:app
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

그러면 /openapi.json, /docs, /redoc URL에 가면 다음과 같은 404 Not Found 오류만 받게 돼요:

{"detail": "Not Found"}

더 알아보기 (Learn more)