Site icon Mr. 沙先生

Amazon EKS Security series: Disable access to EC2 Metadata for your pods

這幾天跟客戶聊到 Amazon EKS 的安全性配置,其中一項我覺得很有趣而且多數人很容易忽略的問題就是「EC2 Metadata」訪問權限,在預設情況下 Kubernetes Pod 是能夠訪問 EC2 metadata 服務,而 EC2 metadata 是 Worker node 存有大量機敏資訊的一個服務,例如 IAM credential、IP Addresses、Instance ID 等等。在這個系列中作者將會特別探討有關於安全相關的設置。

Running test pod

# pod-amazonlinux.yaml
apiVersion: v1
kind: Pod
metadata:
  name: amazonlinux
spec:
  containers:
  - name: amazonlinux                                                                                                                                                                 
    image: public.ecr.aws/amazonlinux/amazonlinux:latest
    command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]

一開始先測試一下跑一個 Amazon Linux Pod 來訪問 EC2 Metadata 確認這個安全性問題的影響範圍

$ kubetctl apply -f pod-amazonlinux.yaml
$ kubectl get pod

再來透過 pod 來拿 EC2 Metadata 的資訊,我們直搗黃龍拿最有安全疑慮的 IAM credential 試試看

$ kubectl exec --stdin --tty amazonlinux -- curl http://169.254.169.254/latest/meta-data/iam/security-credentials/{RoleName}/

{
  "AccessKeyId" : "ASIA...",
  "SecretAccessKey" : "7nJs3...",
  "Token" : "IQoJb3JpZ2l...+DxeQesYCUQ==",
  "Expiration" : "2022-02-22T01:41:11Z"
}

假設 pod 被拿到 shell 之後如果 EC2 Metadata 沒有阻擋好,而 Worker node 的 IAM 也沒有將權限限縮好,那麼這把 Key 外流出去就會非常危險。

Install Calico Network Policy Engine for EKS

在 Kubernetes 中要實現 Network policy 必須採用 network plugin 來實現 pod-to-any 的安全性,在 AWS 文件中已經有 Calico add-on 的安裝方法,所以在這篇我們直接採納作為 Network policy plugin:

$ helm repo add projectcalico https://docs.projectcalico.org/charts
$ helm repo update                         
$ helm install calico projectcalico/tigera-operator --version v3.22.0

Network Policy:Disable access EC2 metadata for Pod

# disable-ec2-metadata.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-pod-access-ec2-metadata
spec:
  podSelector: {}
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0                                                                                                                                                               
        except:
        - 169.254.169.254/32

定義 NetworkPolicy 不允許 Egress 訪問 169.254.169.254/32 (IMDSv1)

$ kubectl apply -f disable-ec2-metadata.yaml -n {namespace}

在部署 NetworkPolicy 時特別注意是無法跨 namespace 的,所以每一個 namespace 都必須部署。

再次使用 pod 訪問 EC2 metadata 時應該已無法正確拿到 metadata。

$ kubectl exec --stdin --tty amazonlinux -- curl http://169.254.169.254/latest/meta-data/iam/security-credentials/{RoleName}/

curl: (28) Failed to connect to 169.254.169.254 port 80 after 132085 ms: Connection timed out

Exit mobile version