# 11 ways not to get hacked

<https://kubernetes.io/blog/2018/07/18/11-ways-not-to-get-hacked/> 요약

psp관련 내용은 삭제

Kubernetes 보안은 프로젝트가 시작된 이후로 먼 길을 걸어왔지만 여전히 몇 가지 문제가 있습니다. 컨트롤 플레인에서 시작하여 워크로드 및 네트워크 보안을 통해 구축하고 보안의 미래에 대한 예측으로 마무리하는 다음은 클러스터를 강화하고 손상된 경우 복원력을 높이는 데 도움이 되는 유용한 팁 목록입니다.

## Part One: The Control Plane

control plane은 Kubernetes의 두뇌입니다. 클러스터에서 실행 중인 모든 컨테이너와 포드에 대한 전체 보기가 있고 새 포드(부모 노드에 대한 루트 액세스 권한이 있는 컨테이너를 포함할 수 있음)를 예약할 수 있으며 클러스터에 저장된 모든 비밀을 읽을 수 있습니다. 이 귀중한 것은 접근할 때나, 저장되어 있을 때나, 네트워크를 통해 운송될 때도 우발적인 누출 및 악의적인 의도로부터 보호해야 합니다.

### 1. TLS Everywhere

트래픽 스니핑을 방지하고, 서버의 ID를 확인하고, (상호 TLS의 경우) 클라이언트의 ID를 확인하려면 **TLS를 지원하는 모든 구성 요소에 대해 TLS를 활성화해야 합니다.**

Source

Lucas Käldström이 작성한 이 네트워크 다이어그램은 TLS가 이상적으로 적용되어야 하는 일부 위치, 즉 마스터의 모든 구성요소 사이, Kubelet과 API 서버 사이를 보여줍니다.

![](https://d33wubrfki0l68.cloudfront.net/d35c2b375b43b4fa374ae834f95224975418e33f/6b47b/images/blog/2018-06-05-11-ways-not-to-get-hacked/kubernetes-control-plane.png)

### 2. RBAC활성화(Least Privilege 최소 권한 법칙으로) , ABAC는 사용하지 않기 , 그리고 로그 모니터링 하기

![](https://d33wubrfki0l68.cloudfront.net/5ffaca47a78a1e02787d105772eb7a72e28c281a/0a9d3/images/blog/2018-06-05-11-ways-not-to-get-hacked/rbac2.png)

Role-based access control은 네임스페이스 액세스와 같은 리소스에 대한 사용자 액세스에 대한 세분화된 정책 관리를 제공합니다.

Kubernetes의 ABAC(속성 기반 액세스 제어)는 릴리스 1.6부터 RBAC로 대체되었으며 API 서버에서 활성화하면 안 됩니다. 대신 RBAC를 사용하십시오.

잊지 마세요: 이러한 로그를 클러스터 내부에 보관하는 것은 침해 시 보안 위협이 됩니다. 이는 다른 모든 보안에 민감한 로그와 마찬가지로 위반 시 변조를 방지하기 위해 클러스터 외부로 전송되어야 합니다.

### 3. API 서버에 타사 인증 사용

조직 전체에서 인증 및 권한 부여(Single Sign On이라고도 함)를 중앙 집중화하면 사용자에 대한 온보딩, 오프보딩 및 일관된 권한이 도움이 됩니다.

Kubernetes를 타사 인증 제공자(예: Google 또는 GitHub)와 통합하면 원격 플랫폼의 ID 보증(2FA와 같은 것으로 백업됨)을 사용하고 관리자가 사용자를 추가하거나 제거하기 위해 Kubernetes API 서버를 재구성해야 하는 것을 방지합니다.

### 4. etcd 클러스터 분리 및 방화벽

etcd는 상태 및 비밀에 대한 정보를 저장하며 중요한 Kubernetes 구성 요소입니다. 클러스터의 나머지 부분과 다르게 보호해야 합니다.

API 서버의 etcd에 대한 쓰기 액세스는 전체 클러스터에서 루트를 얻는 것과 동일하며 읽기 액세스를 사용하여 권한을 상당히 쉽게 에스컬레이션할 수 있습니다.

Kubernetes 스케줄러는 노드가 없는 포드 정의에 대해 etcd를 검색합니다. 그런 다음 찾은 포드를 예약을 위해 사용 가능한 kubelet으로 보냅니다. 제출된 포드에 대한 유효성 검사는 API 서버가 etcd에 쓰기 전에 수행하므로 etcd에 직접 쓰는 악의적인 사용자는 많은 보안 메커니즘을 우회할 수 있습니다. 예)PodSecurity정책.

etcd는 피어 및 클라이언트 TLS 인증서로 구성하고 전용 노드에 배포해야 합니다. 개인 키가 도난당하고 작업자 노드에서 사용되는 것을 방지하기 위해 클러스터를 API 서버로 방화벽으로 설정할 수도 있습니다.

### 5. 암호화 키 교체

보안 모범 사례는 키 손상의 "폭발 반경"을 제한하기 위해 암호화 키와 인증서를 정기적으로 교체하는 것입니다.

Kubernetes는 기존 자격 증명이 만료되면 새 CSR을 생성하여 일부 인증서(특히 kubelet 클라이언트 및 서버 인증서)를 자동으로 교체합니다.

그러나 API 서버가 etcd 값을 암호화하는 데 사용하는 대칭 암호화 키는 자동으로 순환되지 않으며 수동으로 순환해야 합니다. 이를 위해서는 마스터 액세스가 필요하므로 관리 서비스(예: GKE 또는 AKS)는 운영자로부터 이 문제를 추상화합니다.

## Part Two: Workloads

컨트롤 플레인에서 최소한의 실행 가능한 보안으로 클러스터는 안전하게 작동할 수 있습니다. 배포 시 신뢰할 수 있지만 인터넷에 연결되어 있으면 나중에 악용될 위험이 항상 있습니다. 최소한의 권한으로 워크로드를 실행하고 런타임 구성을 강화하면 이러한 위험을 완화하는 데 도움이 될 수 있습니다.

### 6. Use Linux Security Features and PodSecurityPolicies

Linux 커널에는 응용 프로그램에 최소 권한을 제공하도록 구성할 수 있는 여러 중첩 보안 확장(기능, SELinux, AppArmor, seccomp-bpf)이 있습니다.

bane과 같은 도구는 AppArmor 프로필을 생성하고 seccomp 프로필을 위한 docker-slim을 생성하는 데 도움이 될 수 있지만 이러한 정책 적용의 부작용이 있습니다. 애플리케이션의 포괄적인 테스트를 주의하여 하십시오.

### 7. Statically Analyse YAML

Sensitive information should not be stored in pod-type YAML resource (deployments, pods, sets, etc.), and sensitive configmaps and secrets should be encrypted with tools such as vault (with CoreOS's operator), git-crypt, sealed secrets, or cloud provider KMS.

Static analysis of YAML configuration can be used to establish a baseline for runtime security. `kubesec` generates risk scores for resources:

```json
{
  "score": -30,
  "scoring": {
    "critical": [
      {
        "selector": "containers[] .securityContext .privileged == true",
        "reason": "Privileged containers can allow almost completely unrestricted host access"
      }
    ],
    "advise": [
      {
        "selector": "containers[] .securityContext .runAsNonRoot == true",
        "reason": "Force the running image to run as a non-root user to ensure least privilege"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop",
        "reason": "Reducing kernel capabilities available to a container limits its attack surface",
        "href": "/docs/tasks/configure-pod-container/security-context/"
      }
    ]
  }
}
```

And `kubetest` is a unit test framework for Kubernetes configurations:

```python
#// vim: set ft=python:
def test_for_team_label():
    if spec["kind"] == "Deployment":
        labels = spec["spec"]["template"]["metadata"]["labels"]
        assert_contains(labels, "team", "should indicate which team owns the deployment")

test_for_team_label()
```

### 8. 루트가 아닌 사용자로 컨테이너 실행

루트로 실행되는 컨테이너는 작업 부하가 요구하는 것보다 훨씬 더 많은 권한을 갖고 있으며, 이는 손상될 경우 공격자가 공격을 계속하는 데 도움이 될 수 있습니다.

Kubernetes에서 사용자 네임스페이스가 활성화되어 있지 않습니다. 즉, 컨테이너의 사용자 ID 테이블이 호스트의 사용자 테이블에 매핑되고 컨테이너 내에서 루트 사용자로 프로세스를 실행하면 호스트에서 루트로 실행됩니다. 컨테이너 브레이크아웃을 방지하기 위해 계층화된 보안 메커니즘이 있지만 컨테이너 내부에서 루트로 실행하는 것은 여전히 권장되지 않습니다.

많은 컨테이너 이미지는 루트 사용자를 사용하여 PID 1을 실행합니다. 해당 프로세스가 손상되면 공격자가 컨테이너에 루트를 갖게 되며 잘못된 구성을 악용하기가 훨씬 쉬워집니다.

```yaml
# Required to prevent escalations to root.
allowPrivilegeEscalation: false
runAsUser:
  # Require the container to run without root privileges.
  rule: 'MustRunAsNonRoot'
```

루트가 아닌 컨테이너는 1024 미만의 권한 있는 포트에 바인딩할 수 없지만(이것은 CAP\_NET\_BIND\_SERVICE 커널 기능에 의해 제어됨) 서비스를 사용하여 이 사실을 위장할 수 있습니다. 이 예에서 가상의 MyApp 애플리케이션은 컨테이너의 포트 8443에 바인딩되지만 서비스는 targetPort에 대한 요청을 프록시하여 443에서 이를 노출합니다.

```yaml
kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 443
      targetPort: 8443
```

루트가 아닌 사용자로 워크로드를 실행해야 하는 것은 사용자 네임스페이스를 사용할 수 있거나 루트가 없는 컨테이너를 실행하기 위한 지속적인 작업이 컨테이너 런타임에 있을 때까지 변경되지 않습니다.

### 9. Use Network Policies

![](https://d33wubrfki0l68.cloudfront.net/ae5d2e59e5c0b6d65a78be9356b679e510edea1f/83ae3/images/blog/2018-06-05-11-ways-not-to-get-hacked/kubernetes-networking.png) 기본적으로 Kubernetes 네트워킹은 모든 포드 간 트래픽을 허용합니다. 이것은 \`Network Policy\`을 사용하여 제한할 수 있습니다.

Kubernetes는 모든 시스템 상태를 etcd에 저장하므로 CNI 네트워킹 플러그인에서 지원하는 경우 동적 방화벽을 구성할 수 있습니다.

Calico, Cilium, kube-router, Romana 및 Weave Net은 모두 `Network Policy`을 지원합니다.

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector:
Here's an example NetworkPolicy that denies all egress except UDP 53 (DNS), which also prevents inbound connections to your application. NetworkPolicies are stateful, so the replies to outbound requests still reach the application.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: myapp-deny-external-egress
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
  - Egress
  egress:
  - ports:
    - port: 53
      protocol: UDP
  - to:
    - namespaceSelector: {}
```

Kubernetes 네트워크 정책은 DNS 이름에 적용할 수 없습니다. 고정 IP 또는 podSelector(동적 Kubernetes IP의 경우)에만 네트워크 정책을 적용할 수 있기 때문입니다.

모범 사례는 네임스페이스에 대한 모든 트래픽을 거부하는 것으로 시작하고 애플리케이션이 수락 테스트 제품군을 통과할 수 있도록 경로를 점진적으로 추가하는 것입니다.

```yaml
k8s: # used for Kubernetes pods
  deployment: # only deployments currently supported
    test-frontend: # pod name, defaults to `default` namespace
      test-microservice: 80 # `test-microservice` is the DNS name of the target service
      test-database: -80 # `test-frontend` should not be able to access test-database’s port 80
      169.254.169.254: -80, -443 # AWS metadata API
      metadata.google.internal: -80, -443 # GCP metadata API

    new-namespace:test-microservice: # `new-namespace` is the namespace name
      test-database.new-namespace: 80 # longer DNS names can be used for other namespaces
      test-frontend.default: 80
      169.254.169.254: -80, -443 # AWS metadata API
      metadata.google.internal: -80, -443 # GCP metadata API
```

### 10. Scan Images and Run IDS(침입 탐지 시스템)

![](https://d33wubrfki0l68.cloudfront.net/5f3d1a3d4218bd80611c1b761c8addcd63475df9/81472/images/blog/2018-06-05-11-ways-not-to-get-hacked/admission-controllers.png)

웹 서버는 외부에서 http/https를 통해서 pod내부코드를 실행할수 있음

이미지 스캔하면 공격자가 컨테이너에 원격 액세스하기 위해 악용할 수 있는 알려진 취약점이 없는지 확인합니다.

IDS(침입 탐지 시스템)을 사용합니다.

이러한 웹훅은 컨테이너 이미지 스캔 도구에서 이미지를 클러스터에 배포하기 전에 유효성을 검사하는 데 사용할 수 있습니다. 검사에 실패한 이미지는 입장이 거부될 수 있습니다.

알려진 취약점에 대해 컨테이너 이미지를 스캔하면 공격자가 공개된 CVE를 악용할 수 있는 시간을 줄일 수 있습니다. CoreOS의 Clair 및 Aqua의 Micro Scanner와 같은 무료 도구는 배포 파이프라인에서 사용되어 중요하고 악용 가능한 취약점이 있는 이미지의 배포를 방지해야 합니다.

`Grafeas`와 같은 도구는 컨테이너의 고유 서명(콘텐츠 주소 지정 가능 해시)에 대한 지속적인 규정 준수 및 취약성 검사를 위해 이미지 메타데이터를 저장할 수 있습니다. 즉, 해당 해시를 사용하여 컨테이너 이미지를 스캔하는 것은 프로덕션에 배포된 이미지를 스캔하는 것과 동일하며 프로덕션 환경에 액세스할 필요 없이 계속 수행할 수 있습니다.

알려지지 않은 Zero Day 취약점은 항상 존재하므로 Twistlock, Aqua 및 Sysdig Secure와 같은 침입 탐지 도구를 Kubernetes에 배포해야 합니다.

IDS는 컨테이너에서 비정상적인 동작을 감지하고 이를 일시 중지하거나 종료합니다. Sysdig의 Falco는 오픈 소스 규칙 엔진이며 이 생태계의 출발점입니다.

## Part Three: The Future

![](https://d33wubrfki0l68.cloudfront.net/1369cff9a50c46b58834dbfc302a6cda35548adf/e8abc/images/blog/2018-06-05-11-ways-not-to-get-hacked/service-mesh-@sebiwicb.png)

보안의 "클라우드 네이티브 진화"의 다음 단계는 서비스 메시로 보이지만 채택에는 시간이 걸릴 수 있습니다. 마이그레이션에는 애플리케이션에서 메시 인프라로의 복잡성 이동이 포함되며 조직은 모범 사례를 이해하기를 열망할 것입니다.

### 11. Run a Service Mesh

서비스 메시는 Envoy 및 Linkerd와 같은 고성능 "사이드카" 프록시 서버 간에 만들어진 암호화된 영구 연결의 웹입니다. 마이크로서비스 변경 없이 트래픽 관리, 모니터링 및 정책을 추가합니다.

마이크로서비스 보안 및 네트워킹 코드를 공유하고 전투 테스트를 거친 라이브러리 세트로 오프로드하는 것은 Linkerd를 통해 이미 가능했으며 Google, IBM 및 Lyft의 Istio 도입으로 이 분야에 대안이 추가되었습니다. 포드당 암호화 ID를 위한 SPIFFE 및 기타 다양한 기능을 추가함으로써 Istio는 차세대 네트워크 보안의 배포를 단순화할 수 있습니다.

"제로 트러스트" 네트워크에서는 모든 상호 작용이 mTLS(상호 TLS)를 통해 발생하므로 기존 방화벽이나 Kubernetes 네트워크 정책이 필요하지 않을 수 있습니다.

전통적인 네트워킹에서 클라우드 네이티브 보안 원칙으로의 이러한 전환은 전통적인 보안 사고방식을 가진 사람들에게 쉽지 않을 것으로 예상되며 SPIFFE의 Evan Gilman이 쓴 Zero Trust Networking 책은 이 멋진 신세계를 소개하는 데 적극 권장됩니다.

Istio LTS가 출시되었으며 프로젝트는 1.0 릴리스에 빠르게 접근하고 있습니다. 안정성 버전 관리는 Kubernetes 모델과 동일합니다. 개별 API가 자체 알파/베타 안정성 네임스페이스에서 자신을 식별하는 안정적인 코어입니다. 앞으로 몇 달 동안 Istio 채택이 증가할 것으로 예상됩니다.
