Udemy CKA course 7. Security (보안): Authorization (허가) - API 그룹, RBAC, 클러스터 역할/역할바인딩, 서비스 계정, 이미지 보안, 보안 컨텍스트, 네트워크 정책

jihyelee·2024년 1월 31일
0

kubernetes

목록 보기
9/15

Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)

  • 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
  • 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)

API 그룹

쿠버네티스 API

  • 클러스터에서 어떠한 동작을 수행하기 위해서는 API 서버와 통신해야 함
    • kubectl 활용해 접근 가능
    • REST를 통해 직접 접근 가능
      • e.g. curl https://kube-master:6443/version
      • e.g. curl https://kube-master:6443/api/v1/pods
      • 직접 접근 시 --key, --cert, --cacert를 옵션으로 넘겨줌으로써 인증 필요
      • 혹은 kubectl proxy 로 8001 포트에 프록시 서비스를 띄우면 kubeconfig를 사용하기 때문에 curl 명령어에 옵션을 넘겨줄 필요가 없음

kube proxy vs. kubectl proxy

  • kube proxy
    • 다른 노드에 위치한 pod와 service의 연결을 도움
  • kubectl proxy
    • kube-apiserver에 접근하기 위해 kubectl이 만드는 http 프록시 서비스

쿠버네티스 API 그룹

  • 쿠버네티스 API는 목적에 따라 여러 그룹으로 나뉨
    • e.g. /metrics, /healthz, /version, /api, /apis, /logs
    • api는 핵심(core) 그룹(/api)과 지정(named) 그룹(/apis)으로 나뉨
  • 핵심 그룹(/api)
    • 핵심 기능들 존재
    • e.g. v1 하위에 namespaces, pods, rc, event, nodes, endpoints, secrets, configmaps, services, ...
  • 지정 그룹(/apis)
    • 새롭게 만들어진 기능들 존재
    • e.g. /apps: v1 하위에 /deployments, /replicasets, /statefulsets
    • e.g. /networking.k8s.io: v1 하위에 /networkpolicies
    • e.g. /certificates.k8s.io: v1 하위에 /certificatesigningrequest
    • /apps, /networking.k8s.io 등이 API 그룹
    • 그 하위의 /deployments, /networkpolicies 등이 자원(Resource)
      • 해당 자원은 수행할 수 있는 동작들과 연계되어 있음 (동사(Verbs))
      • e.g. list, get, create, delete, update, watch..

허가 (Authorization)

  • 사용자마다 수행할 수 있는 동작이 달라져야 함
    • e.g. kubectl get 은 사용 가능하나 kubectl delete node 는 사용 불가
  • 사용자 혹은 조직마다 접근할 수 있는 네임스페이스를 구분할 필요가 있음

허가 메커니즘

  • Node
    • 클러스터 내부에서의 접근 허가 (kubelet-kubeapi)
    • kubelet은 kubeapi로부터 서비스, 엔드포인트, 노드, 파드에 대한 정보를 읽고(read) kubeapi에게 노드 상태, 파드 상태, 이벤트 등에 대한 정보를 작성함(write)
    • 이러한 작업을 가능하도록 허가해주는 것이 node authorizer
    • kubelet은 인증서에서 system:node:로 이름이 시작해야 하고, system:nodes 그룹에 속해야 함
  • ABAC (Attribute-Based Access Control)
    • 클러스터 외부에서의 접근 허가 (user-kubeapi)
    • 각 사용자 혹은 그룹의 정책에 대한 내용을 json 형태의 파일로 작성
      • e.g. {"kind": "Policy", "spec": {"user": "dev-user", "namespace": "*", "resource": "pods", "apiGroup": "*"}}
    • 허가 내용을 변경하고 싶을 경우 json 파일을 수정하고 kubeapi를 재구동해야 함
  • RBAC (Role-Based Access Control)
    • 클러스터 외부에서의 접근 허가 (user-kubeapi)
    • 특정 권한이 허용된 역할(role)을 생성, 사용자와 특정 역할을 연결
      • e.g. Developer의 경우 pod의 조회, 생성, 삭제 가능
  • Webhook
    • 접근권한을 빌트인이 아니라 외부 메커니즘을 활용해 설정
    • e.g. Open Policy Agent (제 3의 도구)

Kube API 서버에서 허가 메커니즘 설정

  • 확인 가능한 명령어
    • kubectl describe pod [kube-api pod] -n kube-system
    • cat /etc/kubernetes/manifests/kube-apiserver.yaml
    • ps -aux | grep authorization
  • 설정하지 않을 경우 --authorization-mode=AlwaysAllow 기본값
  • --authorization-mode=Node,RBAC,Webhook 처럼 설정 가능
    • 여러 메커니즘을 사용할 경우 작성한 순서대로 접근가능 여부를 확인

Role Based Access Controls (RBAC)

role 객체 생성 (yaml 파일)

  • apiVersion: rbac.authorization.k8s.io/v1
  • kind: Role
  • metadata:
    • name: developer
  • rules:
    • -apiGroups: [""] # core group의 경우 빈칸으로 둬도 무방, 그렇지 않은 경우 그룹명 지정
    • resources: ["pods"]
    • verbs: ["list", "get", "create", "update", "delete"]
    • resourceNames: ["blue", "orange"] # 전체 pod가 아니라 특정 pod에 대해서만 권한 허가 필요 시
    • -apiGroups: [""]
    • resources: ["ConfigMap"]
    • verbs: ["create"]

role binding 객체 생성 (yaml 파일)

  • apiVersion: rbac.authorization.k8s.io/v1
  • kind: RoleBinding
  • metadata:
    • name: devuser-developer-binding
    • namespace: # 네임스페이스 지정하고 싶은 경우 해당 항목 작성
  • subjects: # 사용자 정보
    • -kind: User
    • name: dev-user
    • apiGroup: rbac.authorization.k8s.io
  • roleRef: # 역할 정보
    • kind: Role
    • name: developer
    • apiGroup: rbac.authorization.k8s.io

명령어

  • kubectl get roles
  • kubectl get rolebindings
  • kubectl describe role [역할명]
  • kubectl describe rolebinding [역할바인딩명]
  • kubectl auth can-i create deployments
    • 특정 작업을 수행할 수 있는지 여부를 확인 (yes, no)
    • --as dev-user
      • 특정 사용자가 작업을 수행할 수 있는지 여부를 확인하는 옵션
    • --namespace test
      • 특정 네임스페이스에서 작업을 수행할 수 있는지 여부를 확인하는 옵션
  • kubectl get roles -A --no-headers | wc -l
    • 전체 네임스페이스에 존재하는 role의 개수 파악
  • kubectl create role [이름] --verb=list,create,delete --resource=pods
    • yaml 파일 말고 간단하게 명령어로 role 객체 생성
  • kubectl edit role [이름] -n [네임스페이스명]
    • resource name, rule 등 수정 가능

클러스터 역할, 클러스터 역할바인딩

  • 네임스페이스 범위 (namespaced)
    • 역할과 역할바인딩은 네임스페이스 안에서 생성됨
      • 특정 네임스페이스를 생성해주지 않을 경우 default 네임스페이스에 생성됨
    • e.g. pods, replicasets, jobs, deployments, services, secrets, roles, rolebindings, configmaps, PVC, ...
    • kubectl api-resources --namespaced=true
  • 클러스터 범위 (cluster scoped)
    • 노드는 특정 네임스페이스 안에서 생성될 수 없음
    • e.g. nodes, PV, clusterroles, clusterrolebindings, certificatesigningrequests, namespaces, ...
    • kubectl api-resources --namespaced=false

clusterrole (클러스터 역할)

  • e.g. cluster admin
    • node 조회, 생성, 삭제하는 역할 부여 가능
  • e.g. storage admin
    • persistent volume(PV)과 persistent volume claim(PVC) 조회, 생성, 삭제하는 역할 부여 가능
  • yaml 파일 형식
    • apiVersion: rbac.authorization.k8s.io/v1
    • kind: ClusterRole
    • metadata:
      • name: cluster-administrator
    • rules:
      • -apiGroups: [""]
      • resources: ["nodes"]
      • verbs: ["list", "get", "create", "delete"]

clusterrolebinding (클러스터 역할바인딩)

  • yaml 파일 형식
    • apiVersion: rbac.authorization.k8s.io/v1
    • kind: ClusterRoleBinding
    • metadata:
      • name: cluster-admin-role-binding
    • subjects:
      • -kind: User
      • name: cluster-admin
      • apiGroup: rbac.authorization.k8s.io
    • roleRef:
      • kind: ClusterRole
      • name: cluster-administrator
      • apiGroup: rbac.authorization.k8s.io

서비스 계정

  • 사용자 계정은 사람에 의해 사용됨
    • e.g. 관리자, 개발자
  • 서비스 계정은 기계에 의해 사용됨
    • e.g. 모니터링 어플리케이션 (Prometheus), 빌드툴 (Jenkins)
    • 특정 어플리케이션이 쿠버네티스 API를 쿼링하고자 한다면 인증이 필요
    • kubectl create serviceaccount(sa) [서비스 계정명]
      • 외부 어플리케이션이 인증을 하기 위해 필요한 토큰 또한 생성 (secret 객체)
    • kubectl get serviceaccount
    • kubectl describe serviceaccount [서비스 계정명]
    • kubectl describe secret [토큰명]

토큰

  • REST로 호출할 때 사용 가능
    • e.g. curl https://.../api -insecure --header "Authorization: Bearer [토큰]
  • 만약 외부 어플리케이션이 pod의 형태로 쿠버네티스 클러스터 내에 존재한다면
    • 서비스 토큰 시크릿이 pod에 volume으로 자동으로 마운팅
    • kubectl exec -it [pod명] --ls [마운트 경로: /var/run/secrets/kubernetes.io/serviceaccount]
      • ca.crt, namespace, token 파일 확인 가능
    • kubectl exec -it [pod명] cat [마운트 경로 내 토큰파일: /var/run/secrets/kubernetes.io/serviceaccount/token]
      • 토큰 내용 확인 가능
    • 만약 기본이 아니라 특정 서비스 계정을 사용하고 싶다면 pod yaml 파일 > spec > serviceAccountName에 원하는 서비스 계정 사용
      • pod의 경우 삭제 후 재생성해야 반영 가능
      • deployment의 경우 수정 시 자동 반영
        • kubectl set serviceaccount deploy/[deploy명] [서비스 계정명]
        • 혹은 deployment yaml 파일 > spec > template > spec > serviceAccountName에 작성 후 kubectl apply -f [파일명]
    • 만약 서비스 계정을 자동으로 마운트하지 않고 싶다면 pod yaml 파일 > spec > automountServiceAccountToken: false 사용

최신 업데이트 내용

v1.22

  • TokenRequestAPI
    • 기존의 토큰은 사용제한 기간이 없었음
    • 이제 토큰은 Service Account Administration Controller가 TokenRequestAPI를 통해 생성 (pod 생성 시)
      • TokenRequestAPI는 Audience, Time, Object Bound
  • pod yaml 파일 예시 (volumes > projected: 링크)
    • sources:
      • -serviceAccountToken:
        • expirationSeconds: 3607
        • path: [volumeMount명]

v1.24

  • 이전에는 서비스 계정을 생성하면 시크릿 객체와 토큰이 생성되었음
  • 이제는 서비스 계정을 생성하면 서비스 계정만 생성
    • 토큰을 생성하기 위해서는 kubectl create token [서비스 계정명] 으로 별도 생성해야 함
    • 해당 토큰은 시크릿 객체가 아님
    • 만약 시크릿 객체로 만들고 싶다면 아래와 같은 yaml 파일로 생성 가능 (TokenRequestAPI 사용할 수 없을 때, 보안 문제가 중요하지 않을 때)
      • apiVersion: v1
      • kind: Secret
      • type: kubernetes.io/service-account-token
      • metadata:
        • name: [시크릿 이름]
      • annotations:
        • kubernetes.io/service-account.name: [서비스 계정명]

이미지 보안

  • e.g. image: docker.io/library/nginx
    • 맨 마지막 부분(nginx)은 이미지, 레포지토리
    • 중간 부분(library)은 사용자, 계정명
      • 만약 해당 부분이 제공되지 않는다면 도커의 공식 이미지들이 저장된 기본 계정인 library가 사용됨
    • 맨 앞 부분(docker.io)은 레지스트리
      • 이미지가 풀(pull)되는 위치
      • 제공되지 않는다면 도커의 기본 레지스트리인 도커 허브 (docker.io)
      • e.g. gcr.io (구글 레지스트리)

프라이빗 레포지토리 (private repository)

  • 특정 자격 증명(credential)이 있어야지만 접근 가능할 수 있도록 지정 가능
  • docker login private-registry.io
    • 프라이빗 레지스트리에 로그인
  • docker run private-registry.io/apps/internal-app
    • 해당 레지스트리를 사용해 이미지 구동
  • kubectl create secret docker-registry [시크릿 이름] --docker-server=[private-registry.io] --docker-username=[사용자명] --docker-password=[비밀번호] --docker-email=[이메일 주소]
    • 도커 크레덴셜을 저장하기 위한 도커 레지스트리를 시크릿 객체 형태로 생성
  • pod yaml 파일 수정
    • (spec > containers > ) image: private-registry.io/apps/internal-app
    • (spec > ) imagePullSecrets:
      • -name: [시크릿 이름]

보안 맥락 (Security Context)

도커에서의 보안 설정 (사용자, 리눅스)

  • 도커가 설치된 호스트에서 OS 프로세스, 도커 데몬, SSH 서버 등 여러 프로세스가 돌아가고 있다고 가정
  • 호스트에서 새로운 도커 컨테이너 실행
    • 가상 머신과 다르게 컨테이너는 호스트와 완전히 분리되지 않음
      • 동일한 커널을 공유, 리눅스에서 네임스페이스를 통해 분리됨
    • 도커 컨테이너 내에서 프로세스 확인 시 컨테이너 내의 프로세스만 확인 가능하나, 호스트에서는 도커 컨테이너를 포함한 모든 프로세스 확인 가능
  • 도커 컨테이너 내 프로세스를 root user가 아닌 다른 사용자가 실행할 수 있도록 하려면
      1. docker run --user=[user ID] ...
      • docker run 시 사용자 ID 제공
      1. Dockerfile에 이미지 생성 당시 직접 지정
      • e.g. FROM [이미지명] USER [user ID]
      • docker build -t [이미지명] .
      • docker run [이미지명] ...
  • 도커 컨테이너에 리눅스에서 가능한 기능 추가/제거
    • /usr/include/linux/capability.h에 리눅스에서 가능한 기능들 제공됨
    • e.g. docker run --cap-add MAC_ADMIN [이미지명]
    • e.g. docker run --cap-drop KILL [이미지명]
    • e.g. docker run --privileged [이미지명]

쿠버네티스에서의 보안 설정 (사용자, 리눅스)

  • 도커 컨테이너를 실행할 때 사용자 ID, 리눅스 기능 등 다양한 보안 기준을 적용할 수 있음
  • 쿠버네티스에서도 유사한 보안 설정 가능
    • 일반적으로 pod 내에 container가 캡슐화되어 존재하는 형태
    • pod-level, container-level 등 설정 가능 (둘 다 있을 경우 container-level 우선)

pod yaml 파일

  • spec:
    • securityContext:
      • runAsUser: [사용자 ID] # pod-level
    • containers:
      • -name: ubuntu
      • image: ubuntu
      • command: ["sleep", "3600"]
      • securityContext: # container-level
        • runAsUser: [사용자 ID]
        • capabilities: # container-level에서만 적용 가능
          • add: ["MAC_ADMIN"]

네트워크 정책

  • 트래픽
    • ingress: 들어오는 방향의 트래픽
    • egress: 나가는 방향의 트래픽
  • 네트워크 보안
    • 노드, 파드, 서비스는 모두 각자 별개의 IP 주소를 가짐
    • 파드는 추가적인 세팅 없이도 서로 소통이 가능 (전제 조건)
      • all allow 규칙
  • 네트워크 정책 (객체)
    • 네트워크 정책을 한 개 이상의 파드와 연결
    • 트래픽 정책을 결정할 수 있음
      • e.g. DB 서버의 경우 API 서버(포트)로부터 오는 ingress 트래픽만 허용
    • selector를 이용해 네트워크 정책과 파드를 연결
      • 네트워크 정책 객체
        • podSelector:
          • matchLabels:
            • role: [역할]
      • pod 객체
        • labels:
          • role: [역할]
  • Kube-router, Calico, Romana, Weave-net의 경우 네트워크 정책 지원
  • Flannel의 경우 네트워크 정책 미지원

네트워크 정책 yaml 파일

ingress

  • e.g. DB 파드의 경우 API 파드로부터 오는 ingress 트래픽만 허용할 것 (포트: 3306)
  • apiVersion: networking.k8s.io/v1
  • kind: NetworkPolicy
  • metadata:
    • name: db-policy
  • spec:
    • podSelector:
      • matchLabels:
        • role: db # DB 역할을 하는 pod와 연결
    • policyTypes:
      • -Ingress # ingress, egress 중 고립하려는 트래픽을 명시
    • ingress:
      • -from: # from 하위에 podSelector & namespaceSelector 그리고 ipblock 이라는 2 가지 규칙이 존재하는 상황 (둘 중 하나만 만족하면 됨; -로 규칙 분리)
        • -podSelector:
          • matchLabels:
            • name: api-pod
        • namespaceSelector: # 특정 네임스페이스의 api-pod로 트래픽을 제한하고 싶을 때
          • matchLabels:
            • name: prod
        • -ipblock: # 특정 범위의 IP의 경우 DB 파드에 접근 허용 (e.g. 쿠버네티스 클러스터에 배포되지 않은 백업서버 등)
          • cidr: 192.168.5.10/32
      • ports:
        • -protocol: TCP
        • port: 3306

egress

  • apiVersion: networking.k8s.io/v1
  • kind: NetworkPolicy
  • metadata:
    • name: db-policy
  • spec:
    • podSelector:
      • matchLabels:
        • role: db # DB 역할을 하는 pod와 연결
    • policyTypes:
      • -Ingress
      • -Egress
    • ingress:
      • -from:
        • -podSelector:
          • matchLabels:
            • name: api-pod
      • ports:
        • -protocol: TCP
        • port: 3306
    • egress: # DB 서버가 외부 백업서버에 트래픽을 보내는 경우
      • -to:
        • -ipBlock:
          • cidr: 192.168.5.10/32
      • ports:
        • -protocol: TCP
        • port: 80

참고

기타 명령어

  • kubectl api-resources
    • 객체 이름, 단축어, api 버전, namespaced 여부, 종류 등을 확인할 수 있음
  • jq -R 'split(".") | select(length > 0) | .[0],.[1] | @base64d | fromjson' <<< [토큰내용]
    • 토큰 정리된 형태로 디코딩
  • kubectl exec [pod명] -- whoami
    • 해당 pod 내에서 프로세스를 실행할 수 있는 사용자 확인 가능
  • kubectl get networkpolicies(netpol)
    • 네트워크 정책 객체 확인
profile
Graduate student at Seoul National University, majoring in Artificial Intelligence (NLP). Currently AI Researcher at LG CNS AI Lab

0개의 댓글