Lab 0 — 인가 as-code (클러스터 불필요)¶
직접 해보기 (재구현 트랙): 읽었다면 빈 파일에서 재구현하라 → M0 · Cedar 인가 (자동 채점 11/11, 클러스터 불필요).
목표: authz-as-code — 선언적 규칙을 단위테스트로 — 를 5분 만에, Python만으로 이해한다. 이건 Amazon Verified Permissions와 같은 Cedar 정책 언어다.
모델 — PARC (이 데모에서 구체적으로 무엇인가)¶
Cedar의 모든 결정은 네 조각의 튜플 (Principal, Action, Resource, Context)을 정책에 대해 평가한 것이다.
추상어가 아니라 이 repo에선 정확히 이렇다 (cedar/schema.json + cedar/entities.json):
- Principal =
User(alice/bob/carol).entities.json에서Role(customer/auditor)의 자식이고 — 그래서principal in Role::"auditor"가 동작한다(역할은 그룹 멤버십, ABAC 속성이 아니다) —transferLimit속성을 단다(carol은 0: 감사자는 이체 못 함). 신원 자체는 Cedar 밖에서 온다 (HTTP는X-User헤더, 그게 곧 정직한 한계다 — 아래). - Action =
ViewAccount/Transfer/ViewAuditLog. schema가 각각의appliesTo를 못 박는다 (Transfer는User→Account만,ViewAuditLog는User→AuditLog만) — 액션은 타입 수준에서 엮인다. - Resource =
Account(owner,frozen속성) 또는AuditLog.forbid가 보는resource.frozen, 소유권을 판정하는resource.owner == principal이 전부 여기서 온다. - Context = 요청별 부수 데이터. 여기선
Transfer에만amount(Long)가 붙는다 — schema가Transfer액션의context에만 선언하므로,ViewAccount요청에amount를 끼워 넣으면 검증이 잡는다. principal/resource 속성은 등록된 사실(누가 무엇을 소유)이고, context는 이번 한 번의 시도(이체액)다 — Cedar가 둘을 분리하는 이유다.
forbid(동결)가 permit을 덮는 우선순위, 그리고 permit이 하나도 안 맞으면 기본 거부(default-deny)인
것이 이 모델의 골격이다.
왜 policy-as-code가 검증을 가능케 하나 — 2단계 분리¶
cedar/authz.py는 의도적으로 두 단계를 분리해 돈다:
- schema-validate (요청 0건, 한 번):
cedarpy.validate_policies(policies, schema). 데이터·요청 없이 정책을 타입체크한다 —resource.frozn(오타) 같은 존재하지 않는 속성, 잘못 엮인 액션을 배포 전에 잡는다. 위 기대 출력의schema validation: OK가 이 줄이다. CI에서 깨지는 건 시나리오가 아니라 정책 자체의 타입 버그다. - per-request-evaluate (요청마다):
cedarpy.is_authorized(...)를requests.json의 각 케이스에 돌려 결정이expect와 맞는지 본다. 같은 정책·schema·엔티티에 입력만 바꿔 평가하므로 —amount: 500vs5000vs-100— 결정 경계가 표 한 장으로 드러난다.
이 분리가 핵심이다: 정책은 정적으로 맞는지(validate) 따로, 실제 시나리오에서 옳은지(evaluate) 따로 증명된다. 둘 다 같은 텍스트 파일이라 git diff로 리뷰되고 PR에서 빨개진다 — 그게 "as-code"의 실체다.
정직한 한계 — Cedar는 입력의 진실성은 증명하지 않는다. validate는 정책이 schema에 타입-정합임을, evaluate는 주어진 입력에 대해 정책이 옳음을 보일 뿐이다.
resource.owner == principal은 누군가entities.json의owner를 정직하게 채웠고 principal이 진짜 그 사람일 때만 의미가 있다 — 신원 위조 (헤더 스푸핑)·잘못된 엔티티 데이터는 Cedar 밖의 문제다. authz는 결정 계층이지 인증·데이터 무결성 계층이 아니다. 그 위조 경계를 실제로 닫는 건 Lab 4 — 신원이다.
실행¶
python -m venv .venv && ./.venv/bin/python -m pip install -r requirements-dev.txt
./.venv/bin/python cedar/authz.py
기대 결과:
schema validation: OK
scenario expect actual result
--------------------------------------------------------------------------
owner views own account Allow Allow PASS
non-owner views another's account Deny Deny PASS
owner transfers within limit Allow Allow PASS
owner transfers OVER limit Deny Deny PASS
owner transfers a NEGATIVE amount (value extraction) Deny Deny PASS
transfer from FROZEN account (forbid overrides) Deny Deny PASS
auditor reads audit log Allow Allow PASS
customer reads audit log (no role) Deny Deny PASS
--------------------------------------------------------------------------
8/8 scenarios passed
⚠️ M0 재구현 트랙이라면 — 정답지 주의: 아래 무엇을 읽나 / 망가뜨려 보기는 정답지
cedar/policies.cedar를 직접 읽고 편집한다. M0 랩(labs/m0)을 빈 파일에서 재구현할 계획이면 졸업 전에는 이 절을 건너뛰어라 —cedar/policies.cedar는 그 트랙의 잠긴 정답지다(이 개념 페이지는 개념 파악용으로만 M0 Step 1에서 가리킨다).
무엇을 읽나¶
cedar/policies.cedar— 규칙.forbid(동결 계좌)가permit을 덮고, 이체 규칙은context.amount > 0 && <= limit이 필요함에 주목.cedar/schema.json— 타입 모델(엔티티, 액션,Transfercontext).cedar/entities.json— 데이터(누가 무엇을 소유하나, 이체 한도, 역할).cedar/requests.json— 테스트 케이스 + 그 기대 결정.
망가뜨려 보기 (그리고 고치기)¶
cedar/policies.cedar에서Transferpermit의&& context.amount > 0을 지운다.python cedar/authz.py를 다시 돌린다. 음수 금액(negative-amount) 시나리오가Allow/ FAIL로 뒤집힌다 — 실제 핀테크 버그(음수 "이체"는 가치를 빼낸다)를 재도입한 것이고, 테스트가 그걸 잡아냈다.- 그 줄을 되살린다. 다시 green.
그 루프 — 정책을 바꾸면 테스트가 빨개진다 — 가 authz-as-code의 전부다. 다음: Lab 1 — 스캔.