조건부 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"}