ICA — 이스티오 인증 어소시에이트 · 워크로드 보안 · 실습
제로트러스트 정책 쌓아 올리기
목표
mTLS 강제와 인가 정책을 순서대로 쌓아 올리면서, 평가 순서(CUSTOM → DENY → ALLOW)와 "ALLOW 가 하나라도 있으면 기본 거부로 뒤집힌다"는 성질을 매니페스트로 체득합니다.
왜 중요한가
메시 보안 도입이 실패하는 이유는 거의 항상 순서를 건너뛰기 때문입니다. 평문 출발지를 정리하지 않고 STRICT 를 켜면 사이드카 없는 클라이언트가 즉시 끊기고, 호출 그래프를 모른 채 기본 거부를 깔면 무엇을 열어야 할지 모른 채 장애가 납니다.
특히 잊기 쉬운 사실이 하나 있습니다. principals 는 mTLS 인증서에서 나오므로 PERMISSIVE 상태의 평문 요청에는 principal 이 비어 있고, 그러면 어떤 principals 조건에도 매칭되지 않습니다. "정책은 분명히 맞는데 403"의 가장 흔한 원인입니다. 그래서 이 실습은 mTLS → 기본 거부 → 최소 권한 → 안전망 → 최종 사용자 인증 순서를 그대로 따라갑니다.
Kubernetes 기본 리소스는 실제로 apply 하고, Istio CRD 는 /root/ica-security/ 아래 파일로 작성합니다.
단계
1. 네임스페이스 ica-security 를 만들고 라벨 istio-injection=enabled 를 붙이세요.
2. 네임스페이스 ica-security 에 서비스어카운트 payments-api 와 orders-api 를 만드세요.
3. 같은 네임스페이스에 디플로이먼트 payments-api 를 배포하세요. 파드 라벨은 app=payments-api, serviceAccountName 은 payments-api, 이미지는 nginx:1.27-alpine 입니다. 그리고 서비스 payments-api 를 포트 8080(이름 http)과 9090(이름 http-metrics) 두 개로 만드세요.
4. /root/ica-security/pa-mesh.yaml 에 PeerAuthentication 을 작성하세요. 이름 default, 네임스페이스 istio-system, mtls.mode: STRICT 이며 selector 는 두지 않습니다. 이어서 /root/ica-security/pa-workload.yaml 에 네임스페이스 ica-security, selector app: payments-api, mtls.mode: STRICT 이면서 portLevelMtls 로 포트 9090 만 PERMISSIVE 인 정책을 작성하세요.
5. /root/ica-security/ap-deny-all.yaml 에 AuthorizationPolicy 를 작성하세요. 이름 default-deny, 네임스페이스 ica-security, spec 은 비어 있는 객체입니다.
6. /root/ica-security/ap-allow-orders.yaml 에 AuthorizationPolicy 를 작성하세요. selector app: payments-api, action: ALLOW 이고 규칙 하나에 from.source.principals 는 cluster.local/ns/ica-security/sa/orders-api, to.operation.methods 는 POST, to.operation.paths 는 /v1/charges 입니다.
7. /root/ica-security/ap-deny-admin.yaml 에 AuthorizationPolicy 를 작성하세요. selector app: payments-api, action: DENY, 규칙은 to.operation.paths 에 /admin/* 하나뿐이며 from 은 두지 않습니다. metadata.annotations 에 istio.io/dry-run: "true" 를 붙이세요.
8. /root/ica-security/ra-jwt.yaml 에 RequestAuthentication 을 작성하세요. selector app: payments-api, jwtRules[0].issuer 는 https://idp.example.com/, jwksUri 는 https://idp.example.com/.well-known/jwks.json, audiences 는 payments-api 입니다. 이어서 /root/ica-security/ap-require-jwt.yaml 에 action: ALLOW 이고 from.source.requestPrincipals 가 https://idp.example.com//* 인 AuthorizationPolicy 를 작성하세요.
참고
- SPIFFE ID 를
principals에 쓸 때는spiffe://접두사를 생략하고cluster.local/ns/.../sa/...형태로 적습니다. requestPrincipals는iss/sub형식이므로 발급자 뒤에 슬래시가 하나 더 붙는 모양이 됩니다.- 흔한 실수 1: 기본 거부를 만들 때
spec키 자체를 빼는 것. 그러면 정책이 의도대로 해석되지 않습니다. - 흔한 실수 2: 메시 전역 PeerAuthentication 에 selector 를 붙이는 것. 그 순간 전역이 아니라 워크로드 정책이 됩니다.
- dry-run 애너테이션 값은 문자열
"true"입니다. 따옴표 없이 쓰면 불리언이 되어 애너테이션 규칙에 어긋납니다.
단계 8개
- 보안 실습 네임스페이스 만들기
- 워크로드별 전용 서비스어카운트 만들기
- 서비스어카운트를 붙인 워크로드 배포
- 메시 전역 STRICT 와 포트 예외
- 네임스페이스 기본 거부 만들기
- 호출 그래프대로만 열어 주기
- 관리 경로를 DENY 로 한 겹 더 막기
- 최종 사용자 토큰 필수화