속성 기반 접근 제어
고친 사람 github-actions[bot]
속성 기반 접근 제어는 요청이 올 때마다 여러 값을 모아 보고 허용할지 정하는 방식입니다. 요청한 사람에게 붙은 값, 만지려는 자원에 붙은 값, 그때의 상황이 판단의 재료입니다. 사람마다 무엇을 해도 되는지 미리 적어 두지 않고, 어떤 값이 맞아떨어질 때 허용한다는 규칙만 적어 둡니다.
쉽고 빠른 이해
속성 기반 접근 제어는 「누구에게 허락했나」 대신 「어떤 조건이면 허락한다」를 적어 두는 방식입니다. 「영업팀 사람이 영업팀 문서를 사내망에서 열 때만 읽게 한다」 같은 규칙 하나가 사람이 몇 명이든 그대로 돕니다.
이게 없으면 사람이 늘고 단서가 붙을 때마다 허락 목록이 같이 불어납니다. 「계약직은 근무 시간에만」 같은 단서 하나에 새 권한 묶음을 하나 더 만들어 붙이게 됩니다.
어떻게 도나.
- 요청을 막아 세우고, 요청한 사람과 자원에 붙은 값을 모읍니다
- 모은 값을 미리 적어 둔 규칙에 맞춰 봅니다
- 맞으면 통과시키고, 아니면 거기서 끊습니다
대가가 있습니다. 규칙이 여럿 겹치면 누가 무엇을 할 수 있는지 사람이 훑어서 알기 어려워집니다. 모아 온 값이 낡으면 판단도 같이 틀립니다. 요청마다 값을 모으고 규칙을 따지는 품도 듭니다.
상세
이 절은 먼저 무엇을 속성이라고 부르는지, 속성으로 판단한다는 것이 무슨 뜻인지 봅니다. 그다음 판단이 도는 순서와 이 방식을 고르게 만든 불편을 봅니다. 끝으로 쓸 때 나빠지는 것과 안 쓰는 편이 나은 경우를 짚습니다.
속성 기반 접근 제어는 줄여서 ABAC(Attribute-Based Access Control)라고 부릅니다. 누가 무엇을 해도 되는지 요청마다 판단해서 통과시키거나 막는 일이 접근 제어이고, 그중 판단의 재료를 속성으로 삼는 갈래가 이것입니다. 만져도 된다고 내주는 승인 자체는 인가라고 부릅니다.
비유로 보는 속성 기반 접근 제어
공연장 입장을 떠올려 봅시다. 이름을 적은 초대 명단을 문 앞에 두고 한 사람씩 찾아보는 방법이 있습니다. 「성인 손목띠를 찬 사람만 이 구역에 들어온다」는 규칙 한 줄을 붙여 두는 방법도 있습니다.
뒤엣것은 명단을 고치지 않아도 손목띠만 보고 통과를 정합니다. 손님이 몇 명이든 규칙은 한 줄 그대로입니다.
무엇을 속성이라고 부르나
속성은 어떤 대상에 딸린 이름 있는 값입니다. 「부서는 영업팀」이나 「기밀 등급은 3」처럼 이름과 값이 짝을 이룹니다.
요청하는 쪽을 주체, 만져지는 쪽을 객체라고 부릅니다. 사람이나 프로그램이 주체가 되고, 문서 한 건이나 계좌 하나나 서비스가 밖에 내주는 기능이 객체가 됩니다.
속성은 이 둘에만 붙는 것이 아닙니다. 하려는 동작에도 붙고, 요청이 벌어진 때의 상황에도 붙습니다.
| 어디에 붙나 | 어떤 값인가 |
|---|---|
| 주체 | 부서 · 직급 · 고용 형태 · 이수한 교육 |
| 객체 | 소유 부서 · 기밀 등급 · 만든 때 |
| 동작 | 읽기 · 쓰기 · 지우기 |
| 상황 | 시각 · 접속한 망 · 기기 상태 |
표의 넷 가운데 마지막 줄만 성격이 다릅니다. 주체와 객체의 값은 대상에 오래 붙어 있지만, 상황 값은 요청하는 순간에만 생겼다 사라집니다. 같은 사람이 같은 문서를 열어도 사무실에서 열 때와 카페에서 열 때의 답이 갈리는 것은 이 줄 덕분입니다.
정책이 판단을 대신한다
정책은 「어떤 속성이 어떠할 때 무엇을 허용한다」를 적어 둔 규칙 묶음입니다. 사람 이름도 자원 이름도 적히지 않고, 값들 사이에 성립해야 하는 관계만 적힙니다.
규칙 한 줄과 그 규칙이 요청 셋에 내리는 답을 나란히 놓으면 이렇습니다.
규칙 주체.부서 == 객체.부서 그리고 상황.망 == 사내망
영업팀 · 사내망 → 읽기 // 허용
영업팀 · 카페 와이파이 → 읽기 // 거부
총무팀 · 사내망 → 읽기 // 거부
세 요청 모두 같은 문서를 읽으려 했는데 답이 갈렸습니다. 둘째는 부서가 맞았지만 망이 어긋났고, 셋째는 망이 맞았지만 부서가 어긋났습니다. 규칙에 적힌 조건이 전부 맞아야 허용이 나옵니다.
이 규칙은 새 직원이 들어와도 고칠 것이 없습니다. 그 사람에게 부서 값만 붙여 주면 다음 요청부터 같은 규칙이 판단합니다.
판단이 도는 순서
요청을 실제로 막아 세우는 곳과 허용 여부를 계산하는 곳은 갈라 둡니다. 앞엣것을 정책 시행 지점(Policy Enforcement Point, PEP), 뒤엣것을 정책 결정 지점(Policy Decision Point, PDP)이라고 부릅니다.
갈라 두는 까닭은 규칙을 한 군데서 고쳐 여러 서비스에 같이 먹이기 위해서입니다. 서비스마다 판단 규칙을 따로 들고 있으면 정책을 바꿀 때 서비스 수만큼 고쳐야 합니다.
sequenceDiagram
participant 요청자
participant 시행 as 시행 지점
participant 결정 as 결정 지점
participant 저장소 as 속성 저장소
요청자->>시행: 영업팀 문서를 읽겠다
시행->>결정: 이 요청을 허용하나
결정->>저장소: 이 사람과 문서의 값을 달라
저장소-->>결정: 부서 · 기밀 등급 · 접속한 망
Note over 결정: 모은 값을 규칙에 맞춰 본다
결정-->>시행: 허용한다
시행-->>요청자: 문서를 내준다
그림을 말로 옮기면 이렇습니다. 요청은 서비스에 바로 닿지 않고 시행 지점에서 한 번 멈춥니다. 시행 지점은 스스로 판단하지 않고 결정 지점에 묻습니다. 결정 지점은 사람 정보와 자원 정보가 있는 저장소들에서 값을 모아 규칙에 맞춰 보고, 허용이나 거부 한 마디를 돌려줍니다.
거부가 돌아오면 시행 지점이 요청을 거기서 끊습니다. 서비스는 애초에 그 요청을 본 적이 없습니다.
역할만으로 모자라지는 때
사람마다 권한을 적지 않고 역할에 붙여 두는 역할 기반 접근 제어(Role-Based Access Control, RBAC)가 오래 쓰여 왔습니다. 사람에게는 역할만 주고, 권한은 역할에 답니다.
역할은 사람 수가 많아질 때 잘 버팁니다. 버티지 못하는 것은 단서가 붙을 때입니다. 「영업팀 문서를 읽는다」에 「사내망에서만」과 「근무 시간에만」과 「계약직은 빼고」가 차례로 붙으면, 조건 조합마다 역할을 하나씩 더 만들게 됩니다.
단서가 하나 붙을 때마다 역할 수가 배로 뜁니다. 「사내망에서만」이 붙으면 같은 일을 하는 역할이 망 안쪽용과 바깥쪽용 둘로 갈라지고, 그 상태에서 「근무 시간에만」이 붙으면 다시 둘씩 갈라집니다.
flowchart TD
R0["역할 1개 · 단서 없음"] --> R1["역할 2개 · 사내망 여부"]
R1 --> R2["역할 4개 · 근무 시간 여부"]
R2 --> R3["역할 8개 · 계약직 여부"]
이렇게 역할이 불어나는 것을 역할 폭발이라고 부릅니다. 역할이 사람 수에 가까워지면 역할에 권한을 붙여 둔 뜻이 사라집니다.
속성으로 판단하면 단서가 조건 하나로 들어갑니다. 규칙 한 줄에 「그리고 상황.시각이 근무 시간 안」을 더하면 끝나고, 사람에게 붙은 값은 손대지 않습니다.
미리 등록해 두지 않은 상대에게 허용을 내주는 것도 이 방식이 쉽습니다. 협력사 직원에게 계정을 만들어 역할을 배정하는 대신, 「소속 회사가 협력사 명단에 있고 담당 과제가 같으면 읽게 한다」는 규칙으로 받습니다.
쓰면 나빠지는 것
규칙이 여럿 쌓이면 최종 판단을 사람이 눈으로 못 읽습니다. 한 규칙은 허용하는데 다른 규칙은 거부하는 요청이 생기고, 그때 무엇이 이기는지를 미리 정해 둬야 합니다. 대개는 거부가 이기게 둡니다.
거부된 이유를 설명하기도 어려워집니다. 허용 목록을 보면 답이 나오는 방식과 달리, 거부는 여러 값과 여러 규칙이 맞물린 결과입니다. 그래서 판단할 때 본 값을 감사 로그에 같이 남깁니다. 값을 안 남기면 나중에 같은 요청을 재현할 수 없습니다.
값이 낡으면 판단도 같이 틀립니다. 부서를 옮긴 사람의 부서 값이 늦게 바뀌면 옛 권한이 그동안 살아 있습니다. 「잘못된 값으로 판단한 것」은 「규칙이 잘못된 것」과 원인이 다른데 증상이 같아서 찾는 데 시간이 걸립니다.
품도 듭니다. 요청마다 값을 모으고 규칙을 따지므로 앞의 그림에 있던 왕복이 요청 수만큼 늘어납니다. 값을 캐시해 두면 왕복은 줄지만 낡음 문제가 그만큼 커집니다.
언제 안 쓰나
권한 갈래가 손에 꼽히고 조건이 잘 안 바뀌는 시스템이라면 역할만으로 충분합니다. 규칙 언어와 결정 지점을 들여오는 비용이 얻는 것보다 큽니다.
값을 믿을 수 없을 때도 쓰면 안 됩니다. 판단은 모아 온 값이 맞는 만큼만 맞습니다. 부서나 고용 형태를 관리하는 쪽이 따로 없어 값이 손으로 들어가고 아무도 고치지 않는다면, 규칙을 아무리 잘 적어도 답이 틀립니다.
규칙을 넓게 적어 두고 조건을 나중에 붙이려는 것도 위험합니다. 허용 범위를 필요한 만큼만 좁게 주는 최소 권한 원칙과 어긋나서, 조건 하나를 빠뜨린 규칙이 곧바로 넓은 허용이 됩니다.
관련 항목
속성 기반 접근 제어가 속하는 상위 분류
접근 제어 · 인가 · 인증과 인가 · 보안 엔지니어링 · 최소 권한
같은 판단을 두고 겨루는 접근 제어 방식
역할 기반 접근 제어 · 임의적 접근 제어 · 강제적 접근 제어 · 접근 제어 목록 · 규칙 기반 접근 제어 · 관계 기반 접근 제어
판단을 나눠 맡는 구성 요소
정책 시행 지점 · 정책 결정 지점 · 정책 정보 지점 · 정책 관리 지점 · 속성 저장소 · 속성
정책을 적는 언어와 규격
XACML · Rego · Open Policy Agent · Cedar · NGAC
속성을 실어 나르는 규격
JWT · OAuth 2.0 · OpenID Connect · SAML · 클레임 · LDAP
정책을 잘못 적을 때 터지는 사고
다른 이름: ABAC · Attribute-Based Access Control · attribute based access control · 속성기반 접근제어 · 속성기반 접근 제어