Istio Authorization Policy 활용 deny/allow 접근 제한 구성 가이드
이 포스트에서는 Istio 의 Authorization Policy 리소스를 활용하여, Kubernetes 클러스터의 특정 네임스페이스/레이블의 pod의 deny/allow Access Control을 설정하는 방법에 관해 설명합니다.
Authorization Policy 설정을 통해 불필요한 워크로드간의 통신을 차단하여 보안을 향상하고, 정책을 중앙집중식으로 관리하게 되어 보다 효율적이고 일관된 보안 정책을 적용할 수 있습니다.
이 포스트에서는 Kubernetes 클러스터에 Istio Service Mesh가 사전에 배포되어있다고 가정하고 진행됩니다. Istio Service Mesh 배포 방법은 Istio Service Mesh를 클러스터에 배포하기 포스트를 참고하세요.
목차
1. Istio Authorization Policy 란?
2. 버전 정보
3. Istio Authorization Policy 적용
3-1. 테스트 환경 구성
3-2. Allow Istio Authorization Policy 구성
3-3. Deny Istio Authorization Policy 구성
4. 결론
1. Istio Authorization Policy 란?
Istio의 Authorization Policy 리소스는 Kubernetes 클러스터의 pod와 같은 워크로드간의 access control(접근 제어)을 구성할 수 있는 리소스입니다. 접근 제어 정책으로는 ALLOW, DENY, CUSTOM 정책을 사용할 수 있으며, 여러 정책이 동시에 적용 시 CUSTOM > DENY > ALLOW 순으로 적용됩니다. 적용 방식은 다음과 같습니다.
- 요청이 적용되는 CUSTOM 정책이 존재할 경우, 정책에 의한 결과가 DENY라면 요청을 거부합니다.
- 요청이 적용되는 DENY 정책이 존재할 경우, 요청을 거부합니다.
- ALLOW 정책이 존재하지 않을 경우, 요청을 허용합니다.
- 요청이 적용되는 ALLOW 정책이 존재할 경우, 요청을 허용합니다.
- 요청을 거부합니다.
이 포스트에서는 DENY, ALLOW 정책만을 다루고, CUSTOM 정책은 다루지 않습니다.

2. 버전 정보
- Kubernetes 버전 : 1.30.3
- Isito 버전 : 1.21.1
3. Istio Authorization Policy 적용
Authorization Policy를 istio 네임스페이스에 적용하고 default, test 네임스페이스에 각각 배포된 pod를 통해 istio 네임스페이스의 pod에 요청을 전송하여 확인해보겠습니다.
예제에 사용된 yaml 파일들은 NGINX STORE Git Hub 리포지토리에서 확인하실 수 있습니다.
3-1. 테스트 환경 구성
1. 테스트 환경 구성을 위해, istio 네임스페이스와 test 네임스페이스를 생성합니다.
$ kubectl create namespace istio
namespace/istio created
$ kubectl create namespace test
namespace/test created
2. default 네임스페이스와 생성한 네임스페이스에 Istio의 Auto Sidecar Injection 설정을 적용하기 위해 레이블을 추가합니다. 레이블된 네임스페이스에 배포되는 pod에 자동으로 Istio sidecar proxy 컨테이너가 주입되어 배포됩니다.
$ kubectl label namespaces istio istio-injection=enabled
namespace/istio labeled
$ kubectl label namespaces test istio-injection=enabled
namespace/test labeled
$ kubectl label namespaces default istio-injection=enabled
namespace/default labeled
3. 테스트를 위한 nginx pod를 각 네임스페이스에 배포합니다. version: v1 레이블이 설정되어 있습니다.
# nginx.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
version: v1
name: nginx
spec:
containers:
- image: nginx
name: nginx
$ kubectl create -f nginx.yaml -n default
pod/nginx created
$ kubectl create -f nginx.yaml -n istio
pod/nginx created
$ kubectl create -f nginx.yaml -n test
pod/nginx created
# 모든 네임스페이스의 app=nginx 레이블이 있는 pod 확인
$ kubectl get po -A -l app=nginx
NAMESPACE NAME READY STATUS RESTARTS AGE
default nginx 2/2 Running 0 9s
istio nginx 2/2 Running 0 22s
test nginx 2/2 Running 0 34s
nginx pod 내부에 NGINX 컨테이너와, Istio sidecar proxy 컨테이너가 구성되어 2/2 상태로 배포됩니다.
4. istio 네임스페이스의 nginx pod를 위한 service를 배포하고 확인합니다.
# nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
version: v1
name: istio-nginx-svc
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
version: v1
$ kubectl apply -f nginx-svc.yaml -n istio
service/istio-nginx-svc created
$ kubectl get svc -n istio
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-nginx-svc ClusterIP 10.97.25.107 <none> 80/TCP 56s
3-2. Allow Istio Authorization Policy 구성
1. test 네임스페이스의 요청을 허용하는 Authorization Policy 리소스를 생성합니다. istio 네임스페이스 전체에 적용되는 설정으로, test 네임스페이스의 GET 메서드 요청을 허용하고, 이외의 요청은 거부됩니다.
# allow-test-get.yaml
apiVersion: security.istio.io/v1 # Istio의 보안 관련 리소스를 정의하는 API 버전
kind: AuthorizationPolicy
metadata:
name: allow-test-get # 리소스의 이름 정의
namespace: istio # 해당 리소스를 생성(정책을 적용)할 네임스페이스 정의
spec:
action: ALLOW # 정책의 규칙을 정의. 기본값은 ALLOW
rules:
- from:
- source:
namespaces: ["test"] # 허용 할 네임스페이스 정의
to:
- operation:
methods: ["GET"] # 허용 할 요청 정의
$ kubectl apply -f allow-test-get.yaml -n istio
authorizationpolicy.security.istio.io/allow-test-get created
$ kubectl get authorizationpolicies.security.istio.io -n istio
NAME AGE
allow-test-get 26s
2. 명령어를 사용하여 default 네임스페이스의 nginx pod에서 istio 네임스페이스의 nginx pod로 요청을 전송합니다.
$ kubectl exec -it -n default nginx -- curl 10.97.25.107
RBAC: access denied
앞서 istio 네임스페이스에 생성한 service IP로 요청을 전송하면 요청이 거부됩니다.
$ kubectl exec -it nginx -n default -- curl istio-nginx-svc.istio.svc.cluster.local
RBAC: access denied
위와 같이 요청을 service IP가 아닌 <서비스명>.<네임스페이스>.svc.cluster.local 형식으로 전송할 수도 있습니다.
3. test 네임스페이스의 nginx pod에서 요청을 전송하여 Authorization Policy 설정에 따라 응답하는 것을 확인합니다.
$ kubectl exec -it nginx -n test -- curl istio-nginx-svc.istio.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
allow 설정에 따라 test 네임스페이스의 pod의 요청은 성공하고, default 네임스페이스의 pod의 요청은 거부되는 것을 확인할 수 있습니다.
4. test 네임스페이스의 nginx pod에서 GET 메서드가 아닌 요청을 전송하면 요청이 거부됩니다.
$ kubectl exec -it nginx -n test -- curl -X DELETE istio-nginx-svc.istio.svc.cluster.local
RBAC: access denied
3-3. Deny Istio Authorization Policy 구성
1. 기존에 생성한 Authorization Policy를 제거하고, test 네임스페이스의 요청을 거부하는 Authorization Policy 리소스를 생성합니다.
레이블 설정에 따라 istio 네임스페이스의 version=v2 레이블이 적용된 pod에 적용됩니다.
$ kubectl delete authorizationpolicies.security.istio.io allow-test-get
authorizationpolicy.security.istio.io "allow-test-get" deleted
# deny-test-get-v2.yaml
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-test-get-v2
namespace: istio
spec:
selector: # 지정한 네임스페이스의 특정 레이블을 가진 pod에 정책 적용
matchLabels:
version: v2 # version=v2 레이블에 적용
action: DENY # DENY 설정
rules:
- from:
- source:
namespaces: ["test"]
to:
- operation:
methods: ["GET"]
$ kubectl apply -f deny-test-get-v2.yaml -n istio
authorizationpolicy.security.istio.io/deny-test-get-v2 created
$ kubectl get authorizationpolicies.security.istio.io -n istio
NAME AGE
deny-test-get-v2 2m1s
2. 레이블에 따른 요청 거부를 확인하기 위해 nginx-v2 pod와 service를 배포합니다.
# nginx-v2.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: nginx
version: v2 # 레이블 변경 v1 > v2
name: nginx-v2
spec:
containers:
- image: nginx
name: nginx
# nginx-svc-v2.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
version: v2
name: istio-nginx-svc-v2
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
version: v2 # 레이블 변경
$ kubectl apply -f nginx-v2.yaml -f nginx-svc-v2.yaml -n istio
pod/nginx-v2 created
service/istio-nginx-svc-v2 created
$ kubectl get all -n istio
NAME READY STATUS RESTARTS AGE
pod/nginx 2/2 Running 0 101m
pod/nginx-v2 2/2 Running 0 1m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-nginx-svc ClusterIP 10.97.25.107 <none> 80/TCP 73m
service/istio-nginx-svc-v2 ClusterIP 10.101.165.100 <none> 80/TCP 1m
3. test 네임스페이스의 pod에서 version=v2 레이블이 설정된 istio-nginx-svc-v2 서비스로 요청을 전송해 확인합니다.
$ kubectl exec -it nginx -n test -- curl istio-nginx-svc-v2.istio.svc.cluster.local
RBAC: access denied
설정에 따라 test 네임스페이스의 요청은 거부됩니다.
4. version=v1으로 설정된 기존의 서비스로 요청을 전송하면 정책의 레이블에 해당하지 않아 요청이 허용됩니다.
$ kubectl exec -it nginx -n test -- curl istio-nginx-svc.istio.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
....
5. default 네임스페이스의 pod에서 version=v2 레이블이 설정된 nginx-svc-v2 서비스로 요청을 전송시, 정책에 해당되지 않아 정상적으로 허용됩니다.
$ kubectl exec -it nginx -n default -- curl istio-nginx-svc-v2.istio.svc.cluster.local
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
Authorization Policy 구성에 따라 test 네임스페이스의 요청을 거부하는 설정이 istio 네임스페이스의 version=v2 레이블이 적용된 pod에만 적용되는 것을 확인했습니다.
4. 결론
이번 포스트에서는 Istio의 Authorization Policy 리소스를 활용하여, Kubernetes 클러스터의 특정 네임스페이스/레이블의 pod의 deny/allow Access Control을 설정하는 방법을 알아봤습니다. Allow 설정을 통해 정책에 해당하는 pod의 요청만 허용하도록 설정하고, deny 설정을 통해 정책에 해당하는 pod의 요청을 거부하고, 해당되지 않는 pod의 요청은 허용하도록 설정하는 과정을 예제와 함께 살펴보았습니다.
이와 같은 구성을 통해서 Kubernetes 환경에서 불필요한 서비스 간의 통신을 차단하고 최소 권한의 원칙(Principle of Least Privilege)을 준수하며, 정책을 중앙집중식으로 관리하여 보다 효율적이고 일관된 보안 정책을 적용할 수 있습니다.
추가 질문, 궁금한 점이 있으시거나 Kubernetes 클러스터에 Istio를 통합하여 보다 효율적으로 클러스터를 관리하고 싶으시다면 언제든지 NGINX STORE를 통해 문의해 보세요.
댓글을 달려면 로그인해야 합니다.