Linkerd 라우트별 인가 정책 구성하기
서비스 레벨에서 인가를 강제하는 것에 더해, 개별 HTTP 라우트에 대해 더 세밀한 인가 정책도 구성할 수 있어요. 이 예시에서는 Books 데모 앱을 사용해 특정 클라이언트가 서비스의 특정 라우트에 접근하는 것을 어떻게 제어하는지 보여 드릴게요.
이 예시는 더 복잡한 정책 구성을 보여주는 고급 예시예요. Linkerd 인가 정책의 기초를 배우려면 Restricting Access to Services 예시부터 시작하세요. 정책 리소스에 대한 더 포괄적인 문서는 Authorization policy 레퍼런스를 참고하세요.
사전 요구사항
이 가이드를 사용하려면 클러스터에 Linkerd와 그 Viz 확장이 설치되어 있어야 해요. 아직 하지 않았다면 Installing Linkerd 가이드를 따라 하세요.
Books 데모 애플리케이션 설치
Books 데모 애플리케이션을 주입하고 설치하세요:
$ kubectl create ns booksapp && \
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/booksapp.yml \
| linkerd inject - \
| kubectl -n booksapp apply -f -
이 명령은 데모용 네임스페이스를 만들고, 그 Kubernetes 리소스 매니페스트를 다운로드한 뒤, Linkerd를 애플리케이션에 주입하고, kubectl로 클러스터에 적용해요. 앱은 booksapp 네임스페이스에서 실행되는 Kubernetes 디플로이먼트와 서비스로 구성돼요.
Linkerd 데이터 플레인이 성공적으로 주입되었는지 확인하세요:
$ linkerd check -n booksapp --proxy -o short
클러스터에 추가된 모든 구성요소를 빠르게 확인하려면 다음을 실행하세요:
$ kubectl -n booksapp get all
롤아웃이 성공적으로 완료되면 webapp을 로컬로 포트 포워딩해서 앱에 접근할 수 있어요:
$ kubectl -n booksapp port-forward svc/webapp 7000 &
브라우저에서 http://localhost:7000/ 을 열면 프론트엔드를 볼 수 있어요. Frontend
Server 리소스 만들기
데모 앱의 books 서비스와 webapp 서비스는 모두 authors 서비스의 클라이언트예요.
하지만 이 서비스들은 authors 서비스에 서로 다른 요청을 보내요. books 서비스는 특정 책과 연결된 저자를 가져오기 위해 authors 서비스의 /authors/:id.json 라우트에 GET 요청만 보내야 해요. 반면 webapp 서비스는 사용자가 저자를 만들고 삭제할 수 있게 하므로 /authors에 DELETE와 PUT 요청을, /authors.json에 POST 요청을 보낼 수도 있어요.
books 서비스가 저자를 만들거나 삭제할 필요는 없으므로, webapp과 books 서비스에 대해 별도의 인가 정책을 만들어 authors 서비스의 개별 라우트에 어떤 서비스가 접근할 수 있는지 제한할 거예요.
먼저 linkerd viz authz 명령을 실행해 authors 디플로이먼트에 현재 존재하는 인가 리소스를 나열해 보겠어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default default:all-unauthenticated default/all-unauthenticated 0.0rps 70.31% 8.1rps 1ms 43ms 49ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.3rps 1ms 1ms 1ms
기본적으로 authors 디플로이먼트는 클러스터의 기본 인가 정책인 'all-unauthenticated'를 사용해요. 추가로 kubelet의 liveness 및 readiness 프로브를 허용하는 별도의 인가가 생성돼요.
먼저 authors 디플로이먼트의 서비스 포트에 대한 Server 리소스를 만들겠어요. Server 리소스에 대한 자세한 내용은 여기에서 확인할 수 있어요.
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: authors-server
namespace: booksapp
spec:
podSelector:
matchLabels:
app: authors
project: booksapp
port: service
EOF
이제 authors Deployment에 대한 Server를 정의했으니 linkerd viz authz 명령을 다시 실행해 보면, authors로 가는 모든 트래픽이 현재 인가되지 않은 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default authors-server 9.5rps 0.00% 0.0rps 0ms 0ms 0ms
probe authors-server default/probe 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
이제 authors 디플로이먼트로 가는 트래픽을 인가하기 위한 라우트별 정책 리소스를 만들겠어요.
라우트별 정책 리소스 만들기
HTTPRoute 리소스는 주어진 라우트에 대한 요청 일치 방식을 정의함으로써 개별 HTTP 라우트에 대한 정책을 구성하는 데 사용돼요. 이제 authors 서비스에 대한 HTTPRoute 리소스를 만들겠어요.
참고
서비스 프로파일에 구성된 라우트는 HTTPRoute 리소스와 다르다는 점에 주의하세요. 서비스 프로파일 라우트는 라우트별 메트릭을 수집하고 재시도와 타임아웃 같은 클라이언트 측 동작을 구성할 수 있게 해 줘요. 반면 HTTPRoute 리소스는 AuthorizationPolicy의 대상이 될 수 있고 라우트별 인가를 지정할 수 있게 해요.
먼저 authors 서비스의 API에 대한 GET 요청과 일치하는 HTTPRoute를 만들어 보겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-get-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/authors.json"
method: GET
- path:
value: "/authors/"
type: "PathPrefix"
method: GET
EOF
참고
HTTPRoute 리소스의 두 가지 버전을 Linkerd와 함께 사용할 수 있어요:
- Gateway API가 제공하는 업스트림 버전(
gateway.networking.k8s.ioAPI 그룹) - Linkerd가 제공하는 Linkerd 특화 CRD(
policy.linkerd.ioAPI 그룹)
두 HTTPRoute 리소스 정의는 비슷하지만, Linkerd 버전은 업스트림 Gateway API 리소스 정의에는 아직 없는 실험적 기능을 구현해요. 자세한 내용은 HTTPRoute 레퍼런스 문서를 참고하세요.
이렇게 하면 앞서 정의한 authors-server Server 리소스를 대상으로 하는 HTTPRoute가 만들어져요. rules 섹션은 어떤 요청이 HTTPRoute와 일치하는지 결정하는 매치 목록을 정의해요. 여기서는 /authors.json 경로에 대한 GET 요청과 일치하는 매치 규칙 하나, 그리고 /authors 경로 세그먼트로 시작하는 경로에 대한 GET 요청과 일치하는 매치 규칙 하나를 정의했어요.
이제 라우트를 만들었으니 그 라우트에 정책을 연결할 수 있어요. HTTPRoute에 대한 정책을 정의하는 AuthorizationPolicy 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-get-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-get-route
requiredAuthenticationRefs:
- name: authors-get-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: authors-get-authn
namespace: booksapp
spec:
identities:
- "books.booksapp.serviceaccount.identity.linkerd.cluster.local"
- "webapp.booksapp.serviceaccount.identity.linkerd.cluster.local"
EOF
이 명령은 targetRef가 방금 만든 authors-get-route HTTPRoute 리소스를 선택하는 AuthorizationPolicy를 만들어요. AuthorizationPolicy 리소스는 다양한 형태의 인증을 요구할 수 있어요. 이 경우에는 클라이언트의 TLS 아이덴티티가 books 서비스 또는 webapp 서비스의 ServiceAccount와 일치하도록 요구하는, authors-get-authn이라는 이름의 MeshTLSAuthentication 리소스를 정의했어요.
추가로, authors 서비스를 참조하는 HTTPRoute를 만들었기 때문에 liveness 및 readiness 프로브의 기본 라우트가 더 이상 사용되지 않게 되고, authors 서비스는 unready 상태가 돼요.
따라서 Kubelet의 프로브도 여전히 인가되도록 HTTPRoute와 AuthorizationPolicy를 만들어야 해요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-probe-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/ping"
method: GET
---
apiVersion: policy.linkerd.io/v1alpha1
kind: NetworkAuthentication
metadata:
name: authors-probe-authn
namespace: booksapp
spec:
networks:
- cidr: 0.0.0.0/0
- cidr: ::/0
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-probe-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-probe-route
requiredAuthenticationRefs:
- name: authors-probe-authn
kind: NetworkAuthentication
group: policy.linkerd.io
EOF
여기서는 (MeshTLSAuthentication 대신) NetworkAuthentication 리소스를 사용해 로컬 네트워크(0.0.0.0)에서 오는 프로브만 인증해요.
linkerd viz authz를 다시 실행하면 이제 새 정책이 존재하는 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy 0.0rps 100.00% 0.1rps 2ms 2ms 2ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 2ms 2ms 2ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
그리고 http://localhost:7000/ 을 열어 프론트엔드와 상호작용하면 저자와 책 목록이 여전히 올바르게 표시되는 것을 볼 수 있어요.
추가 라우트 인가하기
하지만 웹 UI에서 새 저자를 만들거나 기존 저자를 삭제하려고 하면 뭔가 잘못됐다는 것을 알 수 있을 거예요.
저자를 삭제하려고 하면 웹 UI에서 'not found' 오류가 발생해요: Not found 마찬가지로 새 저자를 추가하면 오류 페이지로 이동해요.
이는 저자를 만들거나 삭제하면 webapp에서 authors로 각각 PUT 또는 DELETE 요청이 보내지기 때문이에요. GET 요청을 인가하기 위해 만든 라우트는 PUT이나 DELETE 요청과 일치하지 않으므로 authors 프록시가 해당 요청을 404 오류로 거부해요.
이를 해결하기 위해 PUT, POST, DELETE 요청과 일치하는 추가 HTTPRoute 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-modify-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/authors/"
type: "PathPrefix"
method: DELETE
- path:
value: "/authors/"
type: "PathPrefix"
method: PUT
- path:
value: "/authors.json"
method: POST
EOF
이제 저자를 삭제하려고 하면 어떻게 될까요? 여전히 실패하지만, 이번에는 다른 실패가 보여요:
Internal server error
이는 DELETE, PUT, POST 요청과 일치하는 라우트는 만들었지만 그 라우트에 대한 요청을 인가하지 않았기 때문이에요. linkerd viz authz 명령을 다시 실행하면 이를 확인할 수 있어요. authors-modify-route에 대한 인가되지 않은 요청에 주목하세요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy - - - - - -
authors-modify-route authors-server 9.7rps 0.00% 0.0rps 0ms 0ms 0ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
이제 이 라우트를 인가하기 위한 인가 및 인증 정책 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-modify-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-modify-route
requiredAuthenticationRefs:
- name: authors-modify-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: authors-modify-authn
namespace: booksapp
spec:
identities:
- "webapp.booksapp.serviceaccount.identity.linkerd.cluster.local"
EOF
이 구성들은 이전 섹션에서 만든 AuthorizationPolicy와 MeshTLSAuthentication 리소스와 매우 비슷해요. 하지만 이 경우에는 이 라우트에 접근할 수 있도록 webapp 디플로이먼트의 ServiceAccount만 인증하고(books 디플로이먼트는 아니요) 있어요.
이제 프론트엔드에서 다시 한 번 저자를 삭제해 보면 성공할 거예요:
Author deleted
마찬가지로 새 저자도 이제 성공적으로 만들 수 있어요:
Author created
마지막으로 linkerd viz authz 명령을 한 번 더 실행하면 모든 트래픽이 인가된 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy 0.0rps 100.00% 0.1rps 0ms 0ms 0ms
authors-modify-route authors-server authorizationpolicy/authors-modify-policy 0.0rps 100.00% 0.0rps 0ms 0ms 0ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
다음 단계
이제 Linkerd로 라우트별 인가 정책을 구성하는 기초를 다뤘어요. 더 연습하려면 books 서비스에 대한 접근을 제한하는 추가 정책을 만들어 보세요. 또는 Linkerd 인가 정책 전반과 사용 가능한 다양한 구성에 대해 더 배우려면 Policy 레퍼런스 문서를 참고하세요.
본문
서비스 레벨에서 인가를 강제하는 것에 더해, 개별 HTTP 라우트에 대해 더 세밀한 인가 정책도 구성할 수 있어요. 이 예시에서는 Books 데모 앱을 사용해 특정 클라이언트가 서비스의 특정 라우트에 접근하는 것을 어떻게 제어하는지 보여 드릴게요.
이 예시는 더 복잡한 정책 구성을 보여주는 고급 예시예요. Linkerd 인가 정책의 기초를 배우려면 Restricting Access to Services 예시부터 시작하세요. 정책 리소스에 대한 더 포괄적인 문서는 Authorization policy 레퍼런스를 참고하세요.
사전 요구사항
이 가이드를 사용하려면 클러스터에 Linkerd와 그 Viz 확장이 설치되어 있어야 해요. 아직 하지 않았다면 Installing Linkerd 가이드를 따라 하세요.
Books 데모 애플리케이션 설치
Books 데모 애플리케이션을 주입하고 설치하세요:
$ kubectl create ns booksapp && \
curl --proto '=https' --tlsv1.2 -sSfL https://run.linkerd.io/booksapp.yml \
| linkerd inject - \
| kubectl -n booksapp apply -f -
이 명령은 데모용 네임스페이스를 만들고, 그 Kubernetes 리소스 매니페스트를 다운로드한 뒤, Linkerd를 애플리케이션에 주입하고, kubectl로 클러스터에 적용해요. 앱은 booksapp 네임스페이스에서 실행되는 Kubernetes 디플로이먼트와 서비스로 구성돼요.
Linkerd 데이터 플레인이 성공적으로 주입되었는지 확인하세요:
$ linkerd check -n booksapp --proxy -o short
클러스터에 추가된 모든 구성요소를 빠르게 확인하려면 다음을 실행하세요:
$ kubectl -n booksapp get all
롤아웃이 성공적으로 완료되면 webapp을 로컬로 포트 포워딩해서 앱에 접근할 수 있어요:
$ kubectl -n booksapp port-forward svc/webapp 7000 &
브라우저에서 http://localhost:7000/ 을 열면 프론트엔드를 볼 수 있어요. Frontend
Server 리소스 만들기
데모 앱의 books 서비스와 webapp 서비스는 모두 authors 서비스의 클라이언트예요.
하지만 이 서비스들은 authors 서비스에 서로 다른 요청을 보내요. books 서비스는 특정 책과 연결된 저자를 가져오기 위해 authors 서비스의 /authors/:id.json 라우트에 GET 요청만 보내야 해요. 반면 webapp 서비스는 사용자가 저자를 만들고 삭제할 수 있게 하므로 /authors에 DELETE와 PUT 요청을, /authors.json에 POST 요청을 보낼 수도 있어요.
books 서비스가 저자를 만들거나 삭제할 필요는 없으므로, webapp과 books 서비스에 대해 별도의 인가 정책을 만들어 authors 서비스의 개별 라우트에 어떤 서비스가 접근할 수 있는지 제한할 거예요.
먼저 linkerd viz authz 명령을 실행해 authors 디플로이먼트에 현재 존재하는 인가 리소스를 나열해 보겠어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default default:all-unauthenticated default/all-unauthenticated 0.0rps 70.31% 8.1rps 1ms 43ms 49ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.3rps 1ms 1ms 1ms
기본적으로 authors 디플로이먼트는 클러스터의 기본 인가 정책인 'all-unauthenticated'를 사용해요. 추가로 kubelet의 liveness 및 readiness 프로브를 허용하는 별도의 인가가 생성돼요.
먼저 authors 디플로이먼트의 서비스 포트에 대한 Server 리소스를 만들겠어요. Server 리소스에 대한 자세한 내용은 여기에서 확인할 수 있어요.
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: authors-server
namespace: booksapp
spec:
podSelector:
matchLabels:
app: authors
project: booksapp
port: service
EOF
이제 authors Deployment에 대한 Server를 정의했으니 linkerd viz authz 명령을 다시 실행해 보면, authors로 가는 모든 트래픽이 현재 인가되지 않은 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
default authors-server 9.5rps 0.00% 0.0rps 0ms 0ms 0ms
probe authors-server default/probe 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
이제 authors 디플로이먼트로 가는 트래픽을 인가하기 위한 라우트별 정책 리소스를 만들겠어요.
라우트별 정책 리소스 만들기
HTTPRoute 리소스는 주어진 라우트에 대한 요청 일치 방식을 정의함으로써 개별 HTTP 라우트에 대한 정책을 구성하는 데 사용돼요. 이제 authors 서비스에 대한 HTTPRoute 리소스를 만들겠어요.
참고
서비스 프로파일에 구성된 라우트는 HTTPRoute 리소스와 다르다는 점에 주의하세요. 서비스 프로파일 라우트는 라우트별 메트릭을 수집하고 재시도와 타임아웃 같은 클라이언트 측 동작을 구성할 수 있게 해 줘요. 반면 HTTPRoute 리소스는 AuthorizationPolicy의 대상이 될 수 있고 라우트별 인가를 지정할 수 있게 해요.
먼저 authors 서비스의 API에 대한 GET 요청과 일치하는 HTTPRoute를 만들어 보겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-get-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/authors.json"
method: GET
- path:
value: "/authors/"
type: "PathPrefix"
method: GET
EOF
참고
HTTPRoute 리소스의 두 가지 버전을 Linkerd와 함께 사용할 수 있어요:
- Gateway API가 제공하는 업스트림 버전(
gateway.networking.k8s.ioAPI 그룹) - Linkerd가 제공하는 Linkerd 특화 CRD(
policy.linkerd.ioAPI 그룹)
두 HTTPRoute 리소스 정의는 비슷하지만, Linkerd 버전은 업스트림 Gateway API 리소스 정의에는 아직 없는 실험적 기능을 구현해요. 자세한 내용은 HTTPRoute 레퍼런스 문서를 참고하세요.
이렇게 하면 앞서 정의한 authors-server Server 리소스를 대상으로 하는 HTTPRoute가 만들어져요. rules 섹션은 어떤 요청이 HTTPRoute와 일치하는지 결정하는 매치 목록을 정의해요. 여기서는 /authors.json 경로에 대한 GET 요청과 일치하는 매치 규칙 하나, 그리고 /authors 경로 세그먼트로 시작하는 경로에 대한 GET 요청과 일치하는 매치 규칙 하나를 정의했어요.
이제 라우트를 만들었으니 그 라우트에 정책을 연결할 수 있어요. HTTPRoute에 대한 정책을 정의하는 AuthorizationPolicy 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-get-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-get-route
requiredAuthenticationRefs:
- name: authors-get-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: authors-get-authn
namespace: booksapp
spec:
identities:
- "books.booksapp.serviceaccount.identity.linkerd.cluster.local"
- "webapp.booksapp.serviceaccount.identity.linkerd.cluster.local"
EOF
이 명령은 targetRef가 방금 만든 authors-get-route HTTPRoute 리소스를 선택하는 AuthorizationPolicy를 만들어요. AuthorizationPolicy 리소스는 다양한 형태의 인증을 요구할 수 있어요. 이 경우에는 클라이언트의 TLS 아이덴티티가 books 서비스 또는 webapp 서비스의 ServiceAccount와 일치하도록 요구하는, authors-get-authn이라는 이름의 MeshTLSAuthentication 리소스를 정의했어요.
추가로, authors 서비스를 참조하는 HTTPRoute를 만들었기 때문에 liveness 및 readiness 프로브의 기본 라우트가 더 이상 사용되지 않게 되고, authors 서비스는 unready 상태가 돼요.
따라서 Kubelet의 프로브도 여전히 인가되도록 HTTPRoute와 AuthorizationPolicy를 만들어야 해요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-probe-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/ping"
method: GET
---
apiVersion: policy.linkerd.io/v1alpha1
kind: NetworkAuthentication
metadata:
name: authors-probe-authn
namespace: booksapp
spec:
networks:
- cidr: 0.0.0.0/0
- cidr: ::/0
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-probe-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-probe-route
requiredAuthenticationRefs:
- name: authors-probe-authn
kind: NetworkAuthentication
group: policy.linkerd.io
EOF
여기서는 (MeshTLSAuthentication 대신) NetworkAuthentication 리소스를 사용해 로컬 네트워크(0.0.0.0)에서 오는 프로브만 인증해요.
linkerd viz authz를 다시 실행하면 이제 새 정책이 존재하는 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy 0.0rps 100.00% 0.1rps 2ms 2ms 2ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 2ms 2ms 2ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
그리고 http://localhost:7000/ 을 열어 프론트엔드와 상호작용하면 저자와 책 목록이 여전히 올바르게 표시되는 것을 볼 수 있어요.
추가 라우트 인가하기
하지만 웹 UI에서 새 저자를 만들거나 기존 저자를 삭제하려고 하면 뭔가 잘못됐다는 것을 알 수 있을 거예요.
저자를 삭제하려고 하면 웹 UI에서 'not found' 오류가 발생해요: Not found 마찬가지로 새 저자를 추가하면 오류 페이지로 이동해요.
이는 저자를 만들거나 삭제하면 webapp에서 authors로 각각 PUT 또는 DELETE 요청이 보내지기 때문이에요. GET 요청을 인가하기 위해 만든 라우트는 PUT이나 DELETE 요청과 일치하지 않으므로 authors 프록시가 해당 요청을 404 오류로 거부해요.
이를 해결하기 위해 PUT, POST, DELETE 요청과 일치하는 추가 HTTPRoute 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1beta1
kind: HTTPRoute
metadata:
name: authors-modify-route
namespace: booksapp
spec:
parentRefs:
- name: authors-server
kind: Server
group: policy.linkerd.io
rules:
- matches:
- path:
value: "/authors/"
type: "PathPrefix"
method: DELETE
- path:
value: "/authors/"
type: "PathPrefix"
method: PUT
- path:
value: "/authors.json"
method: POST
EOF
이제 저자를 삭제하려고 하면 어떻게 될까요? 여전히 실패하지만, 이번에는 다른 실패가 보여요:
Internal server error
이는 DELETE, PUT, POST 요청과 일치하는 라우트는 만들었지만 그 라우트에 대한 요청을 인가하지 않았기 때문이에요. linkerd viz authz 명령을 다시 실행하면 이를 확인할 수 있어요. authors-modify-route에 대한 인가되지 않은 요청에 주목하세요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy - - - - - -
authors-modify-route authors-server 9.7rps 0.00% 0.0rps 0ms 0ms 0ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
이제 이 라우트를 인가하기 위한 인가 및 인증 정책 리소스를 만들겠어요:
kubectl apply -f - <<EOF
---
apiVersion: policy.linkerd.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: authors-modify-policy
namespace: booksapp
spec:
targetRef:
group: policy.linkerd.io
kind: HTTPRoute
name: authors-modify-route
requiredAuthenticationRefs:
- name: authors-modify-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
---
apiVersion: policy.linkerd.io/v1alpha1
kind: MeshTLSAuthentication
metadata:
name: authors-modify-authn
namespace: booksapp
spec:
identities:
- "webapp.booksapp.serviceaccount.identity.linkerd.cluster.local"
EOF
이 구성들은 이전 섹션에서 만든 AuthorizationPolicy와 MeshTLSAuthentication 리소스와 매우 비슷해요. 하지만 이 경우에는 이 라우트에 접근할 수 있도록 webapp 디플로이먼트의 ServiceAccount만 인증하고(books 디플로이먼트는 아니요) 있어요.
이제 프론트엔드에서 다시 한 번 저자를 삭제해 보면 성공할 거예요:
Author deleted
마찬가지로 새 저자도 이제 성공적으로 만들 수 있어요:
Author created
마지막으로 linkerd viz authz 명령을 한 번 더 실행하면 모든 트래픽이 인가된 것을 볼 수 있어요:
$ linkerd viz authz -n booksapp deploy/authors
ROUTE SERVER AUTHORIZATION UNAUTHORIZED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99
authors-get-route authors-server authorizationpolicy/authors-get-policy 0.0rps 100.00% 0.1rps 0ms 0ms 0ms
authors-modify-route authors-server authorizationpolicy/authors-modify-policy 0.0rps 100.00% 0.0rps 0ms 0ms 0ms
authors-probe-route authors-server authorizationpolicy/authors-probe-policy 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
default default:all-unauthenticated default/all-unauthenticated 0.0rps 100.00% 0.1rps 1ms 1ms 1ms
probe default:all-unauthenticated default/probe 0.0rps 100.00% 0.2rps 1ms 1ms 1ms
다음 단계
이제 Linkerd로 라우트별 인가 정책을 구성하는 기초를 다뤘어요. 더 연습하려면 books 서비스에 대한 접근을 제한하는 추가 정책을 만들어 보세요. 또는 Linkerd 인가 정책 전반과 사용 가능한 다양한 구성에 대해 더 배우려면 Policy 레퍼런스 문서를 참고하세요.