[cilium] Mutual Authentication 테스트 해보기 (진행 중)

cilium에서도 istio처럼 Mutual Authentication이 가능한지 테스트해보려고 합니다.

 

환경 구성하기

cilium 설치하기

먼저 mutual spire를 활성화 합니다. 이렇게 설치하면 자동으로 cilium-spire에 spire도 설치되게 됩니다. 

helm install cilium cilium/cilium --namespace kube-system \
  --set k8sServiceHost=auto --set ipam.mode="cluster-pool" \
  --set k8s.requireIPv4PodCIDR=true --set ipv4NativeRoutingCIDR=10.244.0.0/16 \
  --set routingMode=native --set autoDirectNodeRoutes=true --set endpointRoutes.enabled=true \
  --set kubeProxyReplacement=true --set bpf.masquerade=true --set installNoConntrackIptablesRules=true \
  --set endpointHealthChecking.enabled=false --set healthChecking=false \
  --set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
  --set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=30003 \
  --set prometheus.enabled=true --set operator.prometheus.enabled=true --set hubble.metrics.enableOpenMetrics=true \
  --set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip\,source_namespace\,source_workload\,destination_ip\,destination_namespace\,destination_workload\,traffic_direction}" \
  --set localRedirectPolicy=true --set l2announcements.enabled=true \
  --set gatewayAPI.enabled=true \
  --set operator.replicas=1 --set debug.enabled=true --set bpf.tproxy=true \
  --set authentication.mutual.spire.enabled=true

 

샘플 애플리케이션 배포

테스트는 m-auth 네임스페이스에서 진행합니다.

kubectl create ns m-auth
kubectl config set-context --current --namespace m-auth

 

테스트를 위한 샘플 애플리케이션을 배포합니다. 

cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    app: echo
  name: echo
spec:
  ports:
  - port: 3000
    name: high
    protocol: TCP
    targetPort: 3000
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: echo
  name: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - image: gcr.io/k8s-staging-ingressconformance/echoserver:v20221109-7ee2f3e
        name: echo
        ports:
        - containerPort: 3000
        env:
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_IP
            valueFrom:
              fieldRef:
                fieldPath: status.podIP
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: pod-worker
  name: pod-worker
spec:
  containers:
  - name: netshoot
    image: nicolaka/netshoot:latest
    command: ["sleep", "infinite"]
EOF

 

 

이제 네트워크 정책도 배포해줍니다. 이 네트워크 정책으로는 /headers로의 요청은 정상이지만 그 외의 경우에는 통신이 되지 않게 합니다. 

cat << EOF | kubectl apply -f -
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: no-mutual-auth-echo
spec:
  endpointSelector:
    matchLabels:
      app: echo
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: pod-worker
    toPorts:
    - ports:
      - port: "3000"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/headers"
EOF

 

테스트를 해보면 잘 적용된 것을 확인할 수 있습니다. 

 

spire 설치확인하기

cilium을 설치하면서 spire도 설치되는데 정상적으로 설치가 되었는지 확인해보겠습니다.

아래와 같이 에러가 발생하면 

Server crashed" error="listen unix /tmp/spire-server/private/api.sock: bind: permission denied

 

spire-server 파드가 떠있는 서버에 들어가서 권한을 설정해줍니다.

chown 1000 -R /var/run/spire-server/sockets

 

이제 헬스체크를 확인해보겠습니다.

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server healthcheck

 

 

인증된 목록을 확인해봅니다.

SPIRE 서버는 Kubernetes Projected Service Account Token(PSAT) 을 사용해 Kubernetes 클러스터에서 실행 중인 SPIRE 에이전트의 ID를 검증합니다. PSAT는 기존의 Service Account Token보다 보안성이 높으며, 클러스터가 지원한다면 권장되는 인증 방식입니다.

 

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server agent list

 

SPIFFE 아이덴티티 확인

SPIRE 서비스가 정상임을 확인했으니, Cilium과 SPIRE 통합이 제대로 되었는지 확인합니다.

  • Cilium 에이전트와 오퍼레이터는 SPIRE 서버에 등록된 대리(delegate) 아이덴티티를 가져야 합니다.
  • Cilium 오퍼레이터는 워크로드(쿠버네티스 파드) 를 대신해 SPIRE 서버에 아이덴티티를 등록해야 합니다.

Cilium 에이전트와 오퍼레이터가 SPIRE 서버에 아이덴티티를 가지고 있는지 확인

kubectl exec -n cilium-spire spire-server-0 -c spire-server -- /opt/spire/bin/spire-server entry show -parentID spiffe://spiffe.cilium/ns/cilium-spire/sa/spire-agent

 

여기서부터 안되는데... 뭔가 통신이 안되는것 같당.. 확인 중 

 

상호 인증 강제(Enforce)

기존(또는 새) CiliumNetworkPolicy 의 egress/ingress 규칙에 아래 블록을 추가하면 상호 인증을 적용할 수 있습니다.

kubectl get ciliumnetworkpolicy no-mutual-auth-echo -o json \
| jq '.spec.ingress = (.spec.ingress // [])
      | .spec.ingress |= map(. + {authentication:{mode:"required"}})
      | .spec.egress = (.spec.egress // [])
      | .spec.egress |= map(. + {authentication:{mode:"required"}})' \
| kubectl apply -f -

 

다시한번 테스트로 호출해보겠습니다. 상호 인증을 하기 전과 동일한 결과가 나와야합니다.