- 제로 트러스트 네트워크
1.1 분산 관리와 마이크로서비스 마이크로서비스 아키텍처는 일관된 기술 스택을 강요하지 않고, 팀이 언어 및 프레임워크 선택에 자유를 갖도록 설계된다. 이로 인해 개발 단계에서는 기술적 제약이 줄어들며 유연성이 증가한다. 그러나 운영 단계에서는 다양한 기술(예: Java, Go, Python, Node.js)이 혼합된 환경에서 보안 취약점 발생 가능성이 높아진다.
1.2 전통적인 경계 기반 보안 모델 기존의 보안 방식은 서버의 위치, IP 주소, 서브넷 등 물리적 특성에 따라 네트워크를 영역으로 나누고, 각 영역에 맞는 접근 권한과 보호 수준을 설정한다. 이 방식은 애플리케이션 복잡성 감소와 네트워크 성능 저하 완화에 도움이 된다. 하지만 내부 시스템 중 하나가 침입당하면 공격자가 해당 시스템을 거점으로 전체 내부망을 침투할 수 있으며, 이는 "내부 위험 요소"에 대한 방어가 불가능하다는 한계를 드러낸다.
1.3 제로 트러스트 보안 원칙 제로 트러스트는 어떤 요청도 기본적으로 신뢰하지 않으며, 명확한 신원 확인 절차 없이는 접근을 허용하지 않는다. 핵심 철학은 "서비스는 언제든 실패할 수 있다"는 가정이다. 적용 가능한 구현 원칙은 다음과 같다:
- 서비스 간 신원은 서비스 자체에서만 생성됨 (IP 또는 호스트명 기반 신뢰 금지)
- 모든 서비스 간에는 사전에 정의된 신뢰 관계가 없음
- 보안 정책은 중앙 집중형으로 관리되며, 클라우드 네이티브 인프라에서 자동화됨
- 실행되는 코드는 검증된 출처에서 오며, 신뢰할 수 있는 환경에서 동작해야 함
- 변경 관리는 자동화 및 표준화된 프로세스를 통해 수행됨
- 작업 부하는 가벼운 가상화 기술(예: gVisor, Kata Containers)을 활용해 강력하게 격리됨
1.4 구글의 제로 트러스트 실천 사례
- Google Front End: 외부 공격(예: DDoS)에 대응하는 엣지 프록시
- ALTS(Application Layer Transport Security): 양방향 인증 및 전송 암호화를 지원하는 서비스 인증 메커니즘
- Service Access Policy: 서비스 간 인증, 권한 부여, 감사 정책을 통합 관리
- Binary Authorization: 배포 시 소프트웨어 공급망의 모든 단계에서 보안 검사를 수행
- Host Integrity: BIOS, BMC, 부트로더, 커널 등 시스템 구성 요소의 디지털 서명 검증을 통한 안전 부팅
- gVisor: 고도로 격리된 컨테이너 실행 환경 제공
- 서비스 보안
2.1 신뢰 관계 형성 제로 트러스트 네트워크에서는 초기 신뢰가 존재하지 않으며, 모든 호출은 사전에 설정된 신뢰 기반에서만 가능하다.
-
실세계 신뢰 형성 방식
-
공유 비밀(비밀번호, 생체 정보 등)
-
신뢰할 수 있는 제3자(예: 인증서 발급기관)
-
네트워크 환경에서의 신뢰
-
공개 키 인프라**(PKI)**: TLS 계층의 기반이 되며, 신뢰 체인을 구축함
2.2 전송 계층 보안 (TLS) TLS는 중간자 공격을 방지하고 통신의 기밀성과 무결성을 보장한다. 공격자가 DNS 서버, 프록시, 로드 밸런서 등을 통해 데이터를 가로채거나 조작할 수 있으므로, 통신 채널을 암호화하는 것이 필수적이다.
-
구현 절차
-
CA 루트 인증서 미리 설치
-
서비스별로 해당 CA로부터 인증서 발급
-
도전 과제
-
대규모 및 동적 확장되는 서비스 노드에 대해 수동 인증서 배포 및 교체는 유지보수가 불가능
-
인프라 수준에서 자동화된 보안 정책 적용이 필요
2.3 단방향 vs 양방향 인증
-
단방향 인증 (One-way TLS)
-
서버만 인증서 제공, 클라이언트는 서버 신원 검증
-
외부 공개 서비스에 적합
-
목표: 위조 서버 연결 방지
-
양방향 인증 (mTLS)
-
클라이언트와 서버 모두 인증서 제출 및 상호 인증
-
특정 클라이언트만 접근 허용하는 내부 서비스에 적합
-
목표: 위조 서버 및 비인가 접근 모두 차단
2.4 인증 인증은 서비스 호출자의 신원을 확인하여 정당한 사용자만 접근하도록 하는 절차다.
- Istio 기반 예시: Fenix's Bookstore
- mTLS 활성화:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: authentication-mtls
namespace: bookstore-servicemesh
spec:
mtls:
mode: STRICT
-
PERMISSIVE모드는 기존 평문 통신과 함께 mTLS를 수용하여 점진적 마이그레이션 가능 -
Spring Cloud 기반 예시
-
OAuth 2.0 클라이언트 모드 사용:
private static final List<Client> clients = Arrays.asList(
new Client("bookstore_frontend", "bookstore_secret",
new String[]{GrantType.PASSWORD, GrantType.REFRESH_TOKEN},
new String[]{Scope.BROWSER}),
new Client("account", "account_secret",
new String[]{GrantType.CLIENT_CREDENTIALS},
new String[]{Scope.SERVICE})
);
- JWT 토큰 검증:
@Named
public class RSA256PublicJWTAccessToken extends JWTAccessToken {
RSA256PublicJWTAccessToken(UserDetailsService userDetailsService) throws IOException {
super(userDetailsService);
Resource resource = new ClassPathResource("public.cert");
String publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
setVerifierKey(publicKey);
}
}
2.5 권한 부여 인증 후, 사용자가 접근할 수 있는 리소스를 제어하는 과정이다. 일반적으로 역할 기반 접근 제어**(RBAC)** 방식을 사용하며, 인간 사용자든 머신이든 동일하게 적용된다.
- Istio 기반 권한 정책
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorization-peer
namespace: bookstore-servicemesh
spec:
action: ALLOW
rules:
- from:
- source:
namespaces: ["bookstore-servicemesh"]
to:
- operation:
paths:
- /restful/accounts/*
- /restful/products*
methods: ["GET", "POST", "PUT", "PATCH"]
- from:
- source:
namespaces: ["istio-system"]
- 외부 요청 차단:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authorization-request
namespace: bookstore-servicemesh
spec:
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
notNamespaces: ["bookstore-servicemesh"]
to:
- operation:
paths:
- /restful/accounts/*
- /restful/pay/*
- /restful/settlements*
-
장점: 코드 변경 없이 정책 파일로 관리, 중앙 집중화, 무침입, 통합 관리 가능
-
Spring Cloud 기반 권한 제어
-
ExpressionUrlAuthorizationConfigurer사용:
http.authorizeRequests()
.antMatchers("/restful/accounts/").hasScope(Scope.BROWSER)
.antMatchers("/restful/pay/").hasScope(Scope.SERVICE);
- 메서드 수준 보안:
@GET
@Path("/{username}")
@Cacheable(key = "#username")
@PreAuthorize("#oauth2.hasAnyScope('SERVICE', 'BROWSER')")
public Account getUser(@PathParam("username") String username) {
return service.findAccountByUsername(username);
}
- 장점: 세밀한 제어, SpEL 표현식으로 복잡한 로직 처리 가능
- 단점: 코드에 어노테이션 추가로 인한 복잡성 증가, 규모 확대 시 유지보수 부담 증가