본문으로 건너뛰기

OPA로 API 권한(인가)을 외부화하기

· 약 2분

권한 판단 로직을 각 서비스 코드에 흩지 않고, 정책 엔진(OPA)으로 빼서 한곳에서 결정하게 만드는 방법을 정리합니다.

결론부터 말하면, "이 사용자가 이 동작을 해도 되나"라는 판단을 코드 곳곳에 흩지 말고, 정책 엔진(OPA) 한곳으로 빼냅니다. 서비스는 묻기만 하고, 허용 여부는 정책이 답합니다.

인증과 인가는 다르다

먼저 용어를 구분합니다. 인증(authentication)은 "당신이 누구인지" 확인하는 것이고, 인가(authorization)는 "그 사람이 이 동작을 해도 되는지" 결정하는 것입니다. 이 글은 인가를 다룹니다.

토큰으로 로그인 사용자를 확인했더라도(인증), 그 사람이 특정 자원을 수정해도 되는지(인가)는 별개의 판단입니다.

권한 결정을 왜 밖으로 빼나

권한 판단을 코드에 직접 넣으면, 같은 규칙이 서비스마다 조금씩 다르게 흩어집니다. 규칙이 바뀌면 여러 곳을 동시에 고쳐야 하고, 어디가 어떤 규칙을 쓰는지 한눈에 보이지 않습니다.

건물 출입에 비유할 수 있습니다. 문마다 경비원이 각자 규칙을 외워 판단하면, 규칙이 바뀔 때 모든 경비원을 다시 교육해야 합니다. 대신 중앙 통제실 한 곳에 무전으로 물어보면, 규칙은 통제실만 바꾸면 됩니다. OPA가 그 통제실 역할입니다.

권한 규칙이 서비스마다 흩어진 경우와, OPA 한곳으로 외부화해 각 서비스가 묻기만 하는 구조 비교

PEP와 PDP, 역할 나누기

권한 외부화는 역할을 둘로 나눕니다.

역할하는 일위치
PEP (정책 시행 지점)요청을 가로채 "물어보고" 결과를 시행각 서비스(또는 게이트웨이)
PDP (정책 결정 지점)정책을 평가해 allow/deny를 "답함"OPA

서비스(PEP)는 판단하지 않습니다. 요청 정보를 모아 OPA(PDP)에 묻고, 돌아온 답대로 통과시키거나 막습니다.

정책 작성과 평가 (방법)

OPA의 정책은 Rego라는 언어로 작성합니다. "어떤 입력이면 허용인지"를 선언합니다.

package authz

default allow := false # 기본은 거부 (fail-close)

allow if {
input.action == "GetUser"
input.subject.role == "admin"
}

PEP는 요청에서 주체·동작·자원을 모아 OPA에 평가를 요청합니다.

# PEP: 요청 정보를 모아 OPA 에 질의
decision = http_post(
"http://opa:8181/v1/data/authz/allow",
json={"input": {
"subject": {"id": user_id, "role": role},
"action": operation_id, # 예: "GetUser"
"resource": {"type": "user", "id": target_id},
}},
)
if not decision["result"]:
raise Forbidden() # deny 면 차단

정책 파일은 번들로 묶어 OPA에 배포합니다. 규칙이 바뀌면 코드 배포 없이 정책 번들만 갱신하면 됩니다.

PEP가 주체·동작·자원을 모아 OPA에 질의하고, 정책 평가 결과가 allow면 통과 deny면 차단되는 흐름

흔한 함정

  • 정책과 코드의 동기화: 새 엔드포인트(동작)를 추가했는데 정책에 그 동작을 빠뜨리면, 기본 거부(fail-close)에 걸려 막힙니다. 엔드포인트 추가 시 정책에도 동작을 등록하는 절차를 둡니다.
  • 정책 번들 배포 누락: 정책을 고쳤는데 OPA에 새 번들이 안 올라가면, OPA는 옛 규칙으로 계속 판단합니다. 배포 후 실제 적용됐는지 확인합니다.
  • fail-open vs fail-close: OPA가 응답하지 않을 때 통과시킬지(open) 막을지(close)를 정해야 합니다. 보안이 중요하면 기본은 거부(close)입니다.

Q&A

  • 권한 체크를 게이트웨이에 두나요, 서비스에 두나요?
    • 둘 다 가능합니다. 게이트웨이에 PEP를 두면 공통 처리가 쉽고, 서비스에 두면 자원 단위의 세밀한 판단이 쉽습니다. 자원 소유권 같은 세밀한 규칙은 서비스 쪽 PEP가 유리합니다.
  • OPA 호출이 매 요청마다면 느리지 않나요?
    • OPA를 같은 노드(사이드카)에 두면 호출 비용이 작습니다. 그래도 부담되면 결정 결과를 짧게 캐시합니다.
  • 꼭 OPA여야 하나요?
    • 아니요. 핵심은 "권한 결정을 코드 밖으로 빼서 한곳에서 관리"하는 것입니다. OPA는 그 표준적인 구현일 뿐입니다.

참고자료

  • Open Policy Agent (OPA) Docs: Rego / Bundles
  • NIST: PEP / PDP (정책 시행·결정 지점)