Apache APISIX 권한 정책: API 보호하기
April 21, 2023
소개
오늘날 API는 데이터와 기능 측면에서 다양한 시스템과 애플리케이션을 연결하는 다리 역할을 하고 있습니다. API의 편리함을 누리는 동시에 데이터 보안을 보장하고 데이터 유출 및 기타 보안 문제를 방지하는 것이 사용자들의 주요 관심사가 되었습니다. 이때 접근 제어가 중요한 역할을 합니다. API에 적절한 접근 제어 정책을 수립함으로써, API를 방대한 사이버 공격으로부터 보호하고 데이터 보안을 보장할 뿐만 아니라, 기업이 규제 요구 사항을 충족하고 고객 신뢰를 높이는 데도 도움이 될 수 있습니다.
Apache APISIX는 동적, 실시간, 고성능의 클라우드 네이티브 API 게이트웨이로, 로드 밸런싱, 동적 업스트림, 카나리 릴리스, 서비스 서킷 브레이커, 인증, 관찰 가능성 등 다양한 트래픽 관리 기능을 제공합니다. 이 글에서는 Apache APISIX의 접근 제어 정책을 소개하고, API 보안을 보호하고 시스템의 안정적인 운영을 보장하기 위해 어떤 일반적인 전략을 사용할 수 있는지 논의하겠습니다.
접근 제어 정책이란?
접근 제어 정책은 컴퓨터 시스템, 네트워크 또는 애플리케이션에서 민감한 데이터나 리소스를 보호하기 위해 설계된 보안 메커니즘으로, 권한이 있는 사용자나 애플리케이션만이 접근할 수 있도록 합니다. 이를 통해 데이터 유출 및 보안 취약점의 위험을 줄일 수 있습니다. API 게이트웨이에서 접근 제어 정책은 필수 구성 요소입니다. 모든 트래�의 진입점인 API 게이트웨이는 모든 API 요청을 수신하고 전달하는 역할을 하기 때문에, API 게이트웨이의 접근 제어 정책은 업스트림 서비스의 보안과 안정성을 직접적으로 결정합니다.
Apache APISIX의 일반적인 접근 제어 정책
Apache APISIX는 다양한 접근 제어 정책을 제공하며, OAuth 2.0 인증 프로토콜을 지원하고 Keycloak, Ory Hydra, Okta, Auth0 등 다양한 외부 인증 서비스와 통합할 수 있습니다. 외부 인증 서비스 지원 외에도 APISIX는 강력한 내부 인증 방법을 제공합니다. APISIX의 Consumer 객체와 결합하여 인증, 권한 부여, 속도 제한, IP 블랙리스트 및 화이트리스트 플러그인을 자유롭게 조합하여 API를 보호하고 악의적인 요청으로부터 API 서비스를 보호할 수 있습니다.
1. IP 기반 접근 제어
IP 기반 접근 제어는 가장 간단하고 직접적인 방법으로, 특정 주소에서만 API에 접근할 수 있도록 제한할 수 있습니다.
APISIX의 ip-restriction 플러그인을 사용하여 이 기능을 활성화할 수 있으며, 허용 또는 거부할 IP 주소 목록, IP 주소 범위, 요청 거부 시 반환할 오류 메시지 등 다양한 구성 옵션을 제공합니다. 이러한 옵션을 필요에 따라 구성하여 더 세밀한 접근 제어를 구현할 수 있습니다. IP 기반 접근 제어는 IP 주소가 스푸핑되거나 공유될 수 있으므로 일부 제한이 있을 수 있습니다. 따라서 ip-restriction 플러그인을 사용할 때는 다른 접근 제어 플러그인과 결합하여 시스템의 보안과 유연성을 높이는 것이 좋습니다.
2. API Key 기반 접근 제어
이 접근 제어는 매우 일반적인 API 접근 제어 전략입니다. 기본 원리는 미리 생성된 API Key를 통해 요청을 인증하고 권한을 부여하는 것으로, API에 빠르게 인증 메커니즘을 추가할 수 있습니다. 그러나 API Key를 보호하여 유출 및 악의적인 공격을 방지하는 것이 중요합니다.
APISIX의 key-auth 플러그인을 사용하면 API에 쉽게 인증 메커니즘을 추가할 수 있으며, 요청을 보낼 때 쿼리 문자열 또는 헤더에 키를 추가하여 인증할 수 있습니다. APISIX 버전 3.1 이상에서는 암호화된 저장 필드 data_encryption
구성을 사용하여 etcd에 API Key를 암호화하여 저장할 수 있어 API의 보안을 더욱 강화할 수 있습니다.
3. 토큰 기반 접근 제어
이 방법은 요청 헤더에 토큰을 포함한 인증 필드를 추가하여 구현됩니다. 토큰은 일반적으로 문자열이나 숫자로, API 요청을 보낸 사용자가 API에 접근할 권한이 있는지 확인하는 데 사용됩니다. 일반적으로 토큰에는 사용자의 신원과 권한이 포함되어 있어, 사용자가 API 요청을 시작할 때 서버가 사용자의 접근 권한을 판단하고 적절한 승인 또는 거부 결정을 내릴 수 있습니다.
APISIX는 jwt-auth 플러그인을 제공하여 이 접근 제어 전략을 사용할 수 있으며, 토큰 저장 위치, 토큰 유효 기간, JWT 서명 알고리즘 및 키와 같은 구성 옵션을 지원합니다. 이러한 옵션을 필요에 따라 구성하여 다양한 인증 요구 사항을 충족할 수 있습니다.
4. 요청 경로 기반 접근 제어
요청 경로 기반 접근 제어는 요청 경로를 필터링하고 매칭하여 특정 API, 서비스 또는 리소스에 대한 접근을 제어하는 방법입니다. 이 전략은 리소스에 대한 세밀한 접근 제어가 필요한 시나리오에서 일반적으로 사용되며, 민감한 데이터를 보호하거나 시스템 내 특정 사용자가 특정 리소스에 접근하는 것을 제어하는 데 사용됩니다.
APISIX의 uri-blocker 플러그인은 정규식 규칙 목록을 구성하여 사용자 요청 URI를 차단하고, rejected_code
및 rejected_msg
를 구성하여 성공적으로 차단된 후 반환할 HTTP 상태 코드 및 응답 본문을 지정할 수 있습니다. 이를 통해 관리자는 사용자 권한을 세밀하게 제어하고 API의 보안과 제어 가능성을 높일 수 있습니다.
5. ACL 기반 접근 제어 정책
ACL(Access Control List)은 리소스에 대한 사용자 또는 사용자 그룹의 접근 권한을 제어하기 위한 목록 기반의 접근 제어 정책입니다. 기본 원리는 각 리소스에 대해 ACL 목록을 정의하고, 해당 리소스에 접근할 수 있는 사용자 또는 사용자 그룹을 나열하는 것입니다. 사용자가 리소스에 접근을 요청할 때 해당 ACL 목록을 기반으로 접근 여부를 결정합니다.
APISIX에서는 consumer-restriction을 사용하여 이 기능을 활성화할 수 있습니다. 관리자는 특정 리소스에 접근할 수 있는 사용자 또는 사용자 그룹을 쉽게 제어하고, 권한이 없는 사용자가 민감한 영역에 요청을 보내는 것을 방지하여 민감한 데이터 유출을 방지할 수 있습니다.
시나리오 소개: 세밀한 접근 제어
실제 애플리케이션 시나리오에서는 민감한 데이터를 포함한 리소스에 대해 더 세밀한 접근 제어를 구현하는 경우가 많습니다. 예를 들어, 현재 두 명의 사용자 A와 B가 있으며, 이들은 key-auth 또는 basic-auth와 같은 동일한 내부 인증 방법을 사용합니다. 또한 사용자 B에 대해 더 세밀한 접근 제어를 적용하여 특정 API에 접근하지 못하도록 하고 싶습니다.
APISIX의 consumer-restriction
플러그인을 사용하여 더 세밀한 제어를 할 수 있습니다. 이 플러그인은 Route, Service 또는 Consumer를 기반으로 접근 제한을 설정할 수 있으며, 네 가지 type
속성 값을 구성할 수 있습니다:
consumer_name
: Consumer의username
을 화이트리스트 또는 블랙리스트에 나열하여 Route 또는 Service에 대한 접근을 제한합니다.consumer_group_id
: Consumer Group의id
를 화이트리스트 또는 블랙리스트에 나열하여 Route 또는 Service에 대한 접근을 제한합니다.service_id
: Service의id
를 화이트리스트 또는 블랙리스트에 나열하여 Consumer의 Service 접근을 제한합니다. 이는 권한 부여 플러그인과 함께 사용해야 합니다.route_id
: Route의id
를 화이트리스트 또는 블랙리스트에 나열하여 Consumer의 Route 접근을 제한합니다.
이 시나리오에서는 두 가지 구성 방법을 사용하여 사용자 B가 특정 API 리소스에 접근하지 못하도록 할 수 있습니다.
Route에서 접근 제어 정책 설정
- 먼저 APISIX에 두 개의 Consumer 객체를 생성하고
basic-auth
플러그인을 활성화하며, 이름을 userA와 userB로 지정합니다.
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
"username": "userA",
"plugins": {
"basic-auth": {
"username":"userA",
"password": "123456"
}
}
}'
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
"username": "userB",
"plugins": {
"basic-auth": {
"username":"userB",
"password": "123456"
}
}
}'
- 그런 다음 제한을 적용할 route에서
consumer-restriction
의whitelist
속성을 활성화하고 구성하며, 이전에 생성한 consumer userA의username
을 추가합니다. 이렇게 하면 route는 userA의 요청만 수락합니다.
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -d '
{
"uri": "/get",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
},
"plugins": {
"basic-auth": {},
"consumer-restriction": {
"whitelist": [
"userA"
]
}
}
}'
- userA와 userB를 사용하여 각각 접근 요청을 보냅니다.
curl -u userA:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 200 OK
curl -u userB:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 403 Forbidden
...
{"message":"The consumer_name is forbidden."}
결과는 userB가 API 리소스에 접근하는 것이 제한되었음을 나타냅니다.
Consumer에서 권한 제어 정책 설정
- 먼저 ID가
forbidden-userB
인 route를 설정하고basic-auth
플러그인을 활성화합니다.
curl http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -d '
{
"id": "forbidden-userB",
"uri": "/get",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
},
"plugins": {
"basic-auth": {}
}
}'
- 두 개의 Consumer 객체를 생성하고
basic-auth
플러그인을 활성화합니다. userB에 대해consumer-restriction
플러그인을 구성하여 권한 제어 정책을 세밀하게 설정합니다.
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
"username": "userA",
"plugins": {
"basic-auth": {
"username":"userA",
"password": "123456"
}
}
}'
curl http://127.0.0.1:9180/apisix/admin/consumers -H 'X-API-KEY: {YOUR_API_KEY}' -X PUT -i -d '
{
"username": "userB",
"plugins": {
"basic-auth": {
"username":"userB",
"password": "123456"
},
"consumer-restriction": {
"type": "route_id",
"blacklist": [
"forbidden-userB"
],
"rejected_code": 403
}
}
}'
- userA와 userB를 사용하여 각각 요청을 보냅니다.
curl -u userA:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 200 OK
curl -u userB:123456 http://127.0.0.1:9080/get -i
HTTP/1.1 403 Forbidden
...
{"message":"The route_id is forbidden."}
테스트 결과를 통해 userB의 요청이 효과적으로 제한되었음을 확인할 수 있습니다.
결론
이 글에서는 APISIX에서 일반적으로 사용되는 권한 제어 정책을 소개하고, 클래식한 시나리오를 통해 APISIX에서 이를 활성화하고 구성하는 방법을 설명했습니다. 권한 제어는 API 게이트웨이에서 널리 사용되는 전략입니다. APISIX는 인증을 위한 다양한 플러그인을 제공할 뿐만 아니라, 보안, 트래픽 관리, 관찰 가능성 등 다양한 영역에서 광범위한 지원을 제공합니다. 권한 제어 정책 규칙을 선택하고 구성함으로써 API의 보안을 쉽게 강화할 수 있습니다.