데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [K8S 보안 3탄] Container 보안

      Kyu 24.05.17
      2,938 13 0
      DEVOTEE 요약
      Kubernetes는 다수의 컴퓨터에 컨테이너를 배포하고 관리하는 PaaS로, 컨테이너 기반의 가상화가 아닌 방식으로 동작하여 가상머신(Virtual Machine, VM)보다 세밀한 보안 정책이 필요하다. 컨테이너는 Host OS를 공유하면서 필요한 프로그램 언어 런타임 및 라이브러리를 포함하는 경량 패키지이다. 이에 더해, Kubernetes는 Admission Control 기능을 통해 컨테이너의 컴퓨팅 및 네트워크 격리의 취약점을 해결하는 다양한 보안 정책을 제공한다.
      DEVOTEE 추천 블로그

      서론

      Kubernetes는 다수의 Computer에 container를 Best Practice 를 기반한 구조로 배포하고 관리하는 PaaS 다.

      여기서 주목할 점은 Kubernetes는 가상화 플랫폼인 IaaS가 아니라는 점 이다.

      IaaS는 OS 가상화를 통해서 배포되는 서비스간 종속성 문제를 해결하고 더불어서 서비스간 Computing 환경을 분리하여 강한 보안성을 제공한다.

      즉 동일 Computer에서 동작하는 서로다른 VM에서 구동되는 서비스들은 서로를 볼 수 없고,

      OS level에서는 그 어떤 자원도 공유하지 않기 때문에 보안에 취약한 서비스를 통해 다른 서비스에 접근이 어렵다.

      하지만 Container는 가상화가 아니며, 기본적으로 Host OS에 동작하는 개별 Process 다.

      따라서 Container 배포 시 VM배포 보도 좀더 세밀한 보안 정책 수립이 필요하다.


      Container 보안취약점

      Host OS를 공유하는 Computing 환경

      Container는 소프트웨어를 실행 하는데 필요한 프로그램 언어 런타임 및 라이브러리와 같은 종속성과 소프트웨어를 포함하는 경량 package 다.

      아래는 Dockerfile의 예다. 종속성 이슈가 빈번히 발생하는 python 개발환경이다.

      FROM continuumio/miniconda3:latest
      RUN conda install jupyter
      RUN conda install pandas
      RUN conda install numpy
      RUN conda install matplotlib
      RUN conda install seaborn
      RUN useradd -ms /bin/bash jupyter
      USER jupyter
      WORKDIR home/jupyter
      EXPOSE 8888
      ENTRYPOINT ["jupyter", "notebook","--ip=0.0.0.0","--port=8888","--no-browser","--NotebookApp.token=''", "--NotebookApp.password=''"]

      ML/DL 관련 Package 관리를 하는 miniconda가 설치된 linux 환경을 기준으로(From), 필요 Library (numpy 등을 설치하고 응용이 사용할 사용자를 생성 후,

      최종서비스로 Jupyter notebook를 구동하고 외부에서 접근하게 할 수 있게 Port를 열어 놨다.

      VM golden image에 cloud init과 같은 script로 필요 SW library를 설치하고 응용을 실행하는 것과 유사해 보인다.

      하지만, 독립적인 환경을 제공하는 방식이 다르다.

      Container는 Container가 구동하는 소프트웨어에게 독립적인 Flie system이 주는 것과 같이 착각(?)을 제공하는 것으로 우리는 과거 이를 Jail 이라고 부른다.


      간단하게 특정 소프트웨어가 자신의 Working Directory를 Root Directory로 보이게 만들고,

      Working Directory 하위에 필요한 Library들에 OS환경과 똑같은 Directory 구조에 복사해서 사용하는 것 이다.

      Directory 구조상 Root Directory의 Parent Directory는 없음으로 소프트웨어는 bob directory나 원래 OS의 bin directory에 논리적으로 접근할 수 없다.

      하지만 이는 극히 기본적인 아이디어일뿐으로, 그 후 소프트웨어 Package의 격리를 위해 아래 2개의 Linux 기능이 활성화 되었다.

      • linux namespace

        Process / User / Network 그리고 FIle과 같은 자원에 대해서 container별로 독립적인 ID 쳬계를 제공한다.

      • cgroups

        특정 container가 사용하는 자원를 묶에서 특정 container가 자원의 독점을 막게 해준다.

      하지만, 결론적으로 보면 소프트웨어에게 독립적인 환경에 대한 Simulation을 제공하는 것이기 때문에, Host OS를 여러 Container가 동일하게 사용하는 것이고,

      권한 상승을 통해 OS의 Root 권한을 획득하면 Host의 전체 권한을 획득하게 된다. 이는 VM과 다른 보안 취약점이다.


      Single Network

      Container 자체는 Network 이라기 보다는 Host OS의 Network Interface에 연결되는 Linux Bridge Interface를 Container별로 제공하는 형태가 기본이다.

      하지만 Kubernetes는 CNI plug-in을 통해 Kubernetes Cluster내 Container간 Cluster Network을 제공한다.

      Cluster Network은 1개의 동일 AS(Autonomous System)이다. 즉 Cluster Network을 통해 Cluster내 모든 container는 동일 IP Network Domain에 속해 있음을 의미한다.

      즉 IaaS의 Tenant 별 Virtual Network을 제공하지 않는다. 따라서 이는 Network 보안 취약점이다.

      예를 들어 Kubernetes Cluster내 특정 container에 malware가 설치되면,

      무차별적인 Port scanning을 통해 취약점 공격 혹은 DDoS공격등으로 전체 Cluster내 Container들이 장애에 빠질 수 있다.


      Kubernetes Admission Control

      Kubernetes는 모든 기능이 REST API로 제공된다.

      또한 선언을 통해 모든 동작이 일이남으로 HTTP Payload의 JSON Representation으로 모든 동작을 알 수 있다.

      이런 특징을 반영하여 Kubernetes API Server는 2편에서 다른 AuthN과 AuthZ외 Admission Control 이란 기능을 제공한다.

      이는 인증과 인과를 통과한 자원에 대한 생성/변경/삭제에 여부에 대해서 검사해서 실시 여부를 판단하는 기능이다.


      Admission Control은 2개의 Webhook을 제공한다.

      Webhook point가 분리된 이유는 Validating전에 Mutating이 끝나야 하는 매우 당연한 이유를 만족시키기 위함이다.

      • Mutating

        사용자가 생성/삭제/변경을 요청한 자원에 대해서, 변경하는 것을 의미한다.

        OIDC 인증 시 받은 User name 이나 Group name을 Label로 추가 하는 것을 예로 들 수 있다.

      • Validating

        사용자가 생성/삭제/변경을 요청한 자원을 검토하여 특정 조건 만족 시 생성/삭제/변경을 거부하는 것 이다.

        root 사용자 생성을 막거나 Greedy한 자원 생성을 막기 위해 replica 수를 제한 하는 것을 예로 들 수 있다.

      Kubernetes는 위와 같은 Admission control 기능을 policy라 부른다.

      Admission control의 경우 조직의 업무형태가 지향점등에 따라 매우 다양하게 적용되서 Webhook을 제공하는 형태로 발전했지만,

      최근 Kubernetes의 활용이 폭팔적으로 늘어남으로 Webook을 통한 3rd party solution외 Kubernetes가 built-in으로 제공하는 정책제어 방식 또한 고도화 되고 있다.

      • Kubernetes built in policy resource

        • PSA (Pod Security Admission)

        • Network Policy

        • Validating Admission Policy (1.30 stable)

      • 3rd party solution : e.g OPA gatekeeper


      PSA(Pod Security Admission)

      Container 환경 이전의 대부분의 Linux Server에 동작하는 서비스들은 대 부분 당연하게도 Server다.

      또한 과거에는 Server SW는 대개의 경우 독점적으로 하나의 OS를 사용해 왔기에, Root 권한을 요구하는 경우가 많다.


      Container환경에서는 특정 Container가 OS의 root 권한을 부여하는 것은 다른 container에 보안 구멍을 제공할 수 있다.

      하지만 Host OS의 권한이 필요한 서비스가 엄연히 존재하기 때문에, 무작정 모든것을 막을 수는 없다.


      Kubernetes는 PSP(Pod Security Policy)라 container의 Host OS 권한 접근에 대한 정책을 제어하는 수단을 제공 했으나, PSP는 그 복잡성으로 설정요류를 빈번히 생성했다.

      따라서 Kubernetes community는 PSP를 포기하고 OPA Gatekeeper와 같은 외부 Solution을 사용을 권고 했었다.

      하지만 Kubernetes의 사용이 점점 대중화 되면서, 협업의 경험이 축적되면서 Best Pratice 기반의 Policy preset을 만들 수 있었다.


      PSS(Pod Security Standard)

      Kubernetes는 PSS(Pod Security Standards)라는 표준화된 Policy를 제공한다.

      이는 일종의 Policy preset이다. PSS는 3개의 Profile를 제공하는데 그 내용은 아래와 같다.

      이를통해 misconfiguration의 발생을 원천적으로 방지한다.

      [참고] https://kubernetes.io/ko/docs/concepts/security/pod-security-standards

      Profile

      설명

      특권(Privileged)

      무제한 정책으로, 가장 넓은 범위의 권한 수준을 제공한다. 이 정책은 알려진 권한 상승(privilege escalations)을 허용한다.

      기본(Baseline)

      알려진 권한 상승을 방지하는 최소한의 제한 정책이다. 기본(최소로 명시된) 파드 구성을 허용한다.

      제한(Restricted)

      엄격히 제한된 정책으로 현재 파드 하드닝 모범 사례를 따른다.


      PSA(Pod Security Admission) Controller

      Kubernetes는 PSS를 적용하기 위해 내장된 Pod Security Admission Controller를 제공한다.

      Pod Security Admission Controller는 PSS 위반시 아래와 같이 미리 정의된 조치 중 하나를 실시한다.

      Mode

      설명

      강제(enforce)

      정책 위반 시 파드가 거부된다.

      감사(audit)

      정책 위반이 감사 로그에 감사 어노테이션 이벤트로 추가되지만, 허용은 된다.

      경고(warn)

      정책 위반이 사용자에게 드러나도록 경고를 트리거하지만, 허용은 된다.

      Audit 설정은 Kuberentes 공식 문서를 참조하세요. (https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/)

      Kubernetes를 사용할 때, 보통은 업무나 특정 SW 단위로 namespace를 구성합니다.

      따라서 특정 업무/SW 단위로 PSS를 설정 할 수 있게, PSA Controller는 namespace의 label 기준으로 namespace 에 속한 모든 pod에 대한 PSS를 적용한다.


      아래는 namespace에 label 설정예 입니다.

      apiVersion: v1
      kind: Namespace
      metadata:
        name: my-baseline-namespace
        labels:
          pod-security.kubernetes.io/enforce: baseline
          pod-security.kubernetes.io/enforce-version: v1.29
      
          # We are setting these to our _desired_ `enforce` level.
          pod-security.kubernetes.io/audit: restricted
          pod-security.kubernetes.io/audit-version: v1.29
          pod-security.kubernetes.io/warn: restricted
          pod-security.kubernetes.io/warn-version: v1.29


      Network Policy

      [참조] https://kubernetes.io/docs/concepts/services-networking/network-policies/

      NetworkPolicy는 Pod입장에서 L3/4 통신을 허용하는 대상에 대한 선언으로 Pod Ingress/Egress 대해서 분리하여 대상을 선언할 수 있다.

      대상은 1)Pod 2)Namespace 3) IP range(CIDR) 이다.


      아래는 NetworkPolicy의 예제다. 아래 예제는 default namespace에 속한 pod중 role:db인 pod에 허용된 communication에 대한 정책이다.

      정책을 살펴 보면 default namespace에 있는 db pod는 특정 CIDR block에 속한 서버들(아마도 Kubernetes 외부에 있는 서버들)과

      특정 namespace에 속한 pod들 그리고 default namespace의 특정 role를 같는 pod로 부터만 TCP 6379 port로의 접근만을 허용한다.

      반면 db pod 입장에서는 인터넷에 있는 TCP 5978 Port로만 접속이 허용된다.

      apiVersion: networking.k8s.io/v1
      kind: NetworkPolicy
      metadata:
        name: test-network-policy
        namespace: default
      spec:
        podSelector:
          matchLabels:
            role: db
        policyTypes:
          - Ingress
          - Egress
        ingress:
          - from:
              - ipBlock:
                  cidr: 172.17.0.0/16
                  except:
                    - 172.17.1.0/24
              - namespaceSelector:
                  matchLabels:
                    project: myproject
              - podSelector:
                  matchLabels:
                    role: frontend
            ports:
              - protocol: TCP
                port: 6379
        egress:
          - to:
              - ipBlock:
                  cidr: 10.0.0.0/24
            ports:
              - protocol: TCP
                port: 5978

      좀더 자세히 들여다 보면, from element 는 namespaceSelector와 podSelector element를 독립적인 array로 가지고 있다.

      따라서 각 Selector는 별건이다.


      만약 아래와 같이 namespaceSelector와 podSelector가 하나의 array로 되어 있다. 두조건은 AND 조건으로 해석된다.

      즉, 특정 Namespace에 속한 pod중 특정 pod만 ingress를 허용한다는 의미다.

      ...
      ingress:
          - from:
              - namespaceSelector:
                  matchLabels:
                    project: myproject
                podSelector:
                  matchLabels:
                    role: frontend
      ...


      Implementation of Network Policy

      PSS/PSA의 경우와 다르게 Kubernetes는 ServicePolicy라는 Spec.은 제공하지만, 그 구현은 제공하지 않는다.

      앞서 이야기 했듯이, Container 기술은 기본적으로 OS(대부분의 경우 Linux)가 제공하는 기술을 활용하는 것 이다.

      역사적으로 기본적으로 OS들은 Process 및 Virtual Filesystem에 대한 것만 Kernel 제공하고 Network에 대해서는 기본기능외에는 Plug-in형태로 기능을 제공한다.


      따라서 실재 Linux의 Network Utility들은 Kernel의 기본 기능 외 부가 Utility로 제공되는 경우가 많다.

      이런 이유도 Network, Storage같은 자원은 CNI, CSI와 같은 Ad-on으로 Kubernetes에서 분류한다.


      NetworkPolicy를 Enforcement하는 Implementation은 CNI에 종속적이다.

      NetworkPolicy를 지원하는 대표적인 CNI로는 Calico(https://www.tigera.io/project-calico/)가 있다.


      참고 : Istio Traffic Management

      Service Mesh를 제공하는 Istio의 Traffic Management는 NetworkPolicy보다 더 다양하고 정교한 Ingress/Egress Traffic 제어가 가능하다.

      하지만 OPA Gatekeeper와 다르게 보안측면에서 보조제로 쓰이기는 어렵다.

      Istio는 Sidecar Pattern을 활용한 일종의 Overlay Network상에서의 Traffic 관리 기술이기 때문에, 하위 Level의 Traffic Isolation을 제공할 수 없다.


      결론

      Kubernetes는 Admission Control 기능을 통해 container의 약한 computing/Network 격리로 생기는 문제를 해결 할 수 있는 수단을 제공한다.

      하지만 Admission Control은 이 외에 더 다양한 가능성을 가지고 있는 기능이다. 4편에서 Admission Control에 대해서 더 자세히 알아보기로 한다.

      본 문서를 통해, 보다 안전한 Kubernetes 워크로드 운영에 도움을 줄 수 있길 바란다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      Kyu 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기