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 and Engineer at LG CNS AI Lab

0개의 댓글

관련 채용 정보