본 포스팅은 CKA 자격증 준비를 위해 해당 강의를 보고 정리한 자료입니다.
일부 생략되었으니 꼭 강의를 수강하시고 내용 정리 용도로만 참고하시길 바랍니다.
Kubernetes Security Primitives
kube api server는 쿠버네티스 모든 동작의 중심으로, api에 직접 접근하거나 kubectl 을 통해 상호작용하게된다. 첫 번째 방어선인 api 서버에 대한 접근을 어떻게 제어할 수 있을까?
Authentication - Who can access
- Files - Username and Passwords
- Files - Username and Tokens
- Certificates
- External Authentication providers - LDAP
- Service Accounts
Authorization - What can they do?
- RBAC Authorization (Role Based Access Control)을 이용해 구현될 수 있음
- ABAC Authorization (Attribute Based Access Control)
- Node Authorization
- Webhook Mode
- 모든 component(ETCD, kube controller manager, api server, kubelet, ...) 사이의 통신 ⇒ TLS 암호화에 의해 보호
- application 간의 통신 ⇒ Network Policy 에 의해 제한됨
Authentication
쿠버네티스는 기본적으로 사용자 계정을 관리하지 않으며, 사용자를 관리하기 위해 파일, 인증서, LDAP 같은 써드파티 서비스 등 외부 소스에 의존한다.
$ kubectl create serviceaccount sa1
- service account를 통해 관리 가능
Auth Mechanisms (권장x, 1.19버전에서 deprecated)
요청이 들어왔을때, kube-apiserver는 어떻게 인증을 할까?
- Static Password File
- 사용자 id, 비밀번호가 담긴 csv 파일을 만들고, kube-apiserver.service 옵션에 넣어준다. (--basic-auth-file=user-details.csv)
- (kube-apiserver.service 옵션 변경시 /etc/kubernetes/manifests/kube-apiserver.yaml 도 같이 변경해주어야함)
- kube-apiserver에 요청시 사용자 id, 비밀번호와 함께 요청
- Static Token File
- 마찬가지로 토큰과 사용자 id가 포함된 csv 파일을 등록 (--token-auth-file=user-details.csv)
TLS Certificates (참고)
- 서버는 CSR(certificate signing request)를 CA에 보낸다.
- CA는 private key를 통해 CSR에 서명하고, 서명된 certificate는 다시 서버로 보내진다. 서버는 서명된 certificate를 통해 web application을 확인한다.
- 사용자가 web application에 접근하려할때, 서버는 첫번째로 public key로 암호화한 certificate를 보낸다.
- 사용자 또는 사용자의 브라우저가 certificate를 읽고, CA의 public key를 통해 유효성을 검사하고 서버의 public key를 찾는다.
- 그리고 앞으로 통신을 위해 사용할 symmetric key를 생성한다.
- symmetric key는 서버의 public key를 통해 암호화되어 서버로 보내진다.
- 서버는 자신의 private key로 이를 복호화하여 symmetric key를 찾는다.
- Certificate(with public key)는 보통 crt 또는 pem 확장자로 된 파일
- private key는 보통 .key 또는 -key.pem 확장자를 가짐
TLS in Kubernetes
참고: https://kubernetes.io/ko/docs/setup/best-practices/certificates/
쿠버네티스 클러스터의 mater 노드와 worker 노드 간 통신, 또는 kube-api server와 admin(user)간의 통신은 모두 TLS 보안이 적용됨
- 클러스터 내 서비스들은 server certificate 를 통해 통신을 보호하고, 클라이언트는 client certificate를 통해 자신의 신분을 증명해야함
- 모든 certificate는 CA를 통해 서명이 되어야함
- server 는 server certificate를 통해 통신을 보호
- kube-apiserver → apiserver.crt, apiserver.key
- user가 kube-api 서버에 http요청을 통해 클러스터를 관리할 수 있으므로, 자격증명필요
- kube-api 서버의 경우 etcd 서버와 통신할 때는 client에 해당→ 기존 key pair를 사용하거나, etcd 통신용 key pair를 만들 수도 있음
- etcd server → etcdserver.crt, etcdserver.key
- kubelet → kubelet.crt, kubelet.key
- (kube-apiserver가 요청을 통해) 상태관리를 위한 api를 제공하므로 자격증명 필요
- kube-apiserver → apiserver.crt, apiserver.key
- CA는 root certificate를 통해 cerificate를 확인
- server certificate와 client certificate 서명 → ca.crt, ca.key
- client는 client certificate를 이용해 서버가 자신을 증명하도록 함
- kubectl를 사용한 client는 kube-api 서버와 통신하기 위해서 자격 증명 → admin.crt, admin.key
- kube-scheduler도 pod 정보를 위해 kube-api 서버와 통신하므로 필요 → scheduler.crt, scheduler.key
CA 생성
Root Certificate
1. private key 생성 (ca.key)
$ openssl genrsa -out ca.key 2048
2. Certificate Signing Request (ca.csr)
$ openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr
- 모든 detail이 있는 인증서지만, 서명이 되어있지 않은 상태
3. Signing Certificate (인증서 생성, ca.crt)
생성한 private key를 통해 CSR에 서명
$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
- CA가 자신의 private key와 root certificate file을 가지게 됨
Client Certificate
admin user를 위한 certificate 생성
1. private key 생성 (admin.key)
$ openssl genrsa -out admin.key 2048
2. Certificate Signing Request (admin.csr)
$ openssl req -new -key admin.key -subj "/CN=kube-admin" -out admin.csr
- 사용자 이름을 명시 (kube-admin)
3. Signing Certificate (admin.crt)
앞서 만든 ca.crt와 ca.key를 통해 인증서를 서명
$ openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt
위 과정은 새로운 user에 대해 새 계정을 만드는 것과 비슷하다고 볼 수 있다.
- user id는 certificate, key는 password와 같은 개념
✔ 다른 user와 admin user를 구분하는 방법
- certificate에 group detail을 추가할 수 있음
- 쿠버네티스의 system masters 그룹이 관리자 권한을 가지고 있음
- csr 생성시 다음과 같이 그룹 명시
$ openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr
✔ certificate 사용
- kube-apiserver 에 요청시 생성한 key pair을 넣어준다.
$ curl https://kube-apiserver:6443/api/v1/pods --key admin.key --cert admin.crt --cacert ca.crt
- 또는 kube config yaml에 명시
Serverside Certificate
certificate 생성 과정은 이전과 동일함
ETCD 서버 Certificate
- ETCD 서버는 고가용성을 위해 클러스터 내 여러 서버에 배포될 수 있음
- 각 멤버들 간 통신을 보호하기 위해, 추가적인 peer certificate를 생성해야함
- certiciate가 한번 생성되면, ETCD 서버를 시작할때 이를 명시해주어야함
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.187.2.31:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt #
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.187.2.31:2380
- --initial-cluster=k8s-test001=https://10.187.2.31:2380
- --key-file=/etc/kubernetes/pki/etcd/server.key #
- --listen-client-urls=https://127.0.0.1:2379,<https://10.187.2.31:2379>
- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-peer-urls=https://10.187.2.31:2380
- --name=k8s-test001
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt #
- --peer-client-cert-auth=true #
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key #
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt #
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt #
kube-apiserver Certificate
kube-apiserver는 많은 component의 요청이 들어오고, 많은 operation이 kube-api 서버를 통해 이루어지는 만큼, alias 가 많다.
- alias를 지정하는 방법
- open ssl config 파일 → openssl.cnf 파일을 생성
- alt_names 에 대체 DNS 또는 IP 지정
- cert signing request 시 해당 config 파일 지정 (-config 옵션)
- open ssl config 파일 → openssl.cnf 파일을 생성
$ openssl req -new -key apiserver.key -subj "/CN=kube-apiserver" -out apiserver.csr -config openssl.cnf
- 그 후 인증서 사인
$ openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -out apiserver.crt
kubelet certificate
kubelet은 node 마다 있기 때문에, 각 node에 certificate 필요 (이름이 node 에 따라 정해진다.)
certificate 를 생성하고, kubelet-config 파일에 해당 정보를 준다. (각 node에 수행)
kubelet 은 client로서 kube-apiserver와 통신하기 위해 client cert도 필요
- api 서버가 어떤 노드인지 알수있도록 이름이 지정됨
- 노드는 sytem component 이므로 system:node:node01 와 같이 지정
- 그리고 api 서버가 올바른 permission 을 주기 위해, node들을 SYSTEM:NODES 라는 group에 추가
Certificate 상세 확인
kube-apiserver config 확인 → cert path 확인
$ cat /etc/kubernetes/manifests/kube-apiserver.yaml
- certicate file ⇒ --tls-cert-file
특정 cert 정보 확인
$ openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout
Certificates API
새로운 cluster admin 을 추가하고자할 때
- 본인의 private key를 생성하고, certificate siging request를 요청 (기존 admin에게)
- 기존 admin은 request를 CA 서버를 통해 cert 생성 (CA서버의 private key와 root cert를 통해 서명)
- 새로운 관리자는 클러스터에 접근할 cert와 key를 가지게 됨
CA는 사실상 우리가 생성한 key, cert file pair 에 불과하다. 이 file을 보호하기 위해, 안전한 서버에 위치하도록하고, 이를 CA 서버라고 한다. 현재는 kubernetes 마스터 노드에 인증서가 위치하고, 따라서 master 노드 또한 CA 서버이다.
위 과정을 새로운 admin이 추가될 때마다 해야하고 cert가 만료되었을 때마다 cert를 교체해주어야하므로 더 나은 방법이 필요하다. => kubernetes Certificates API 를 통해 가능
- CertificateSigningRequest 생성 (master node에 logging하고 직접 cert를 서명하지 않음)
- Review Requests
- CertificateSigningRequest 가 생성되면, 클러스터의 admin들이 kubectl 을 통해서 확인 및 approve할 수 있음
- Approve Requests
- Share Certs to Users
참고: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/
EX) 새로운 user에 대해 certificate api를 통한 인증 과정
참고: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user
1. 새로운 user (jane) 은 private key 생성
$ openssl genrsa -out jane.key 2048
$ openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr
- 위 결과와 함께 cert siging request를 보냄
2. CertificateSigningRequest 생성
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: john
spec:
groups:
- system:authenticated
usages:
- client auth
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
- 받은 csr 내용은 base64를 통해 encode 후 넣는다. (request)
- cat jane.csr | base64
3. csr 확인 및 승인
$ kubectl get csr
$ kubectl certificate approve jane
생성된 cert는 yaml 로 뽑은 후 status.certificate 값을 base64 로 디코딩하여 사용한다.
$ kubectl get csr jane -o yaml
$ echo "..." | base64 —decode
쿠버네티스의 cert 관련 작업을 수행하는 component는 Controller Manager 이다.
KubeConfig
kubeconfig 파일을 통해 서버 및 cert 정보를 명시 → 일일이 해당 정보를 kubectl 사용시 반복할 필요 없음
- ~/.kube/config (default)
- clusters, contexts(어떤 cluster에 어떤 user?), users 로 구성
✔ context 정의시 namespace를 지정할 수 있음
→ 해당 context 사용시 자동으로 default namespace를 해당 namespace로 사용
✔ cluster의 ca는 path로 지정할 수도 있고 (certifiacte-authority: /etc/kubernetes/pki/ca.crt) ,
직접 encode된 data로 넣어줄 수도 있음 (certifiacte-authority-data: LS0t...)
config command
$ kubectl config view
$ kubectl config view --kubeconfig=my-custom-config
$ kubectl config use-config prod-user@production
API Groups
namespaces, pods, rc, nodes, services, .. 등 k8s 리소스 그룹
Authorization
access를 얻었다면, 무엇을 할 수 있는가
Node Authorizer
system:node (certificate)이름을 가진 user로부터의 요청은 node authorizer로 부터 인증되고 권한이 부여된다.
ABAC (Attribute Based Access Control)
참고: https://kubernetes.io/docs/reference/access-authn-authz/abac/
user 또는 user group을 권한 집합과 연결하는 역할
policy file을 생성해서 지정 가능
- ex. Alice can do anything to all resources:
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "alice", "namespace": "*", "resource": "*", "apiGroup": "*"}}
RBAC (Role Based access control)
user 또는 user group을 권한 집합과 연결하며 ABAC 보다 훨씬 쉽게 제어할 수 있음
- 특정 권한을 생성하고, user를 연결하는 방식
Webhook
open policy agent와 같이 admission control과 authorization를 돕는 써드파티 사용
- 쿠버네티스가 open policy agent에 권한 체크 요청을 하도록 할 수 있음
AlwaysAllow, AlwaysDeny
권한 체크 없이 모든 요청 수용, 거절
→ 이런 Auth mode 옵션은 kube-apiserver 옵션으로 지정됨 (--authorization-mode=AlwaysAllow)
$ kubectl describe pod kube-apiserver-controlplane -n kube-system
RBAC
참고: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
Role 생성
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: dev-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
$ kubectl get roles
$ kubectl get rolebindings
Check Access
$ kubectl auth can-i create deployments
$ kubectl auth can-i create pods --as dev-user
$ kubectl auth can-i create pods --as dev-user --namespace test # namespace test에 pod을 생성할 권한이 있는가
특정 pod에 대한 권한
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
resourceNames: ["blue", "orange"] # 해당 이름의 pod에 대한 권한
Cluster Roles and Role Binding
참고: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole
resource는 namespace 또는 cluster 범위로 categorize 된다.
- node는 cluster 범위의 resource (특정 namespace와 연관되지 않음)
cluster 범위의 resources에 대한 role ⇒ Cluster Role
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
Cluster RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
namespace 에 해당하는 resource도 cluster role을 사용할 수 있음
- 대신 모든 namespace에 대한 권한이 허용됨
Service Accounts
참고: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
application 이 쿠버네티스 클러스터와 상호작용하기 위해 사용되는 계정
- service account를 통해 요청이 인증됨
- ex. prometheus 같은 모니터링 app이 metrics를 가져오기위해 쿠버네티스 api에 요청할때 사용
$ kubectl create serviceaccount dashboard-sa
- serviceaccount가 생성되면, token이 자동으로 생성됨
- 이 token은 외부 application이 쿠버네티스 api에 인증하는 데 사용됨 → secret object로 생성됨
✔ 각 namespace는 default serviceaccount를 가지게 된다. pod이 생성되면, default serviceaccount와 그의 token이 자동으로 pod에 volume mount로 mount된다.
$ kubectl exec -it my-kubernetes-dashboard cat /var/run/secrets/kubernetes.io/serviceaccount/token
- pod내에 mount된걸 확인할 수 있음
- pod 생성시 다른 serviceaccount를 사용하려면, spec.serviceAccountName 에 지정하면 됨
- 존재하는 pod에 변경불가, 변경시 pod 삭제후 재생성 (deployment는 edit 가능, rollout됨)
- spec.automountServiceAccountToken을 false로 지정해 자동 mount 방지 가능
Images Security
참고: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-secret-by-providing-credentials-on-the-command-line (검색: pull an image)
쿠버네티스로 image를 받아오기 위한 credential 을 어떻게 넘기는가?
1. credential을 가진 docker-registry 타입의 secret 생성
$ kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
2. pod 생성시 imagePullSecrets 지정 → 생성한 secret 지정
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
Security Contexts
참고: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-pod
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000 # all processes run with user id 1000
containers:
- name: ubuntu
image: ubuntu
command: []
#securityContext: # 여기에 정의해서 container level로 지정 가능
- pod 레벨 / container 레벨 지정 가능 (pod 레벨 지정시 모든 container에 적용)
- pod 레벨/ container 레벨 모두 지정시 container 레벨의 설정이 적용됨
container 실행 user 확인
$ kubectl exec ubuntu-sleeper -- whoami
리눅스 기능 추가 및 제거
참고: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-capabilities-for-a-container
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
Network Policy
참고: https://kubernetes.io/docs/concepts/services-networking/network-policies/
기본적으로 쿠버네티스 클러스터 내 모든 pod들은 서로 통신이 가능한데, network policy를 통해 특정 통신만 허용할 수 있다.
→ 즉, pod 내부로 들어오는 ingress 트래픽과 외부로 나가는 egress 트래픽을 제한할 수 있다.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
name: api-pod
ports:
- protocol: TCP
port: 3306
- db pod에 network policy 를 적용하고자 함 → podSelector를 통해 어떤 pod에 적용할지 정의
- api pod으로부터의 ingress 통신만 허용하고 싶음 → policyTypes을 ingress 로 지정하고, ingress 필드 정의
- traffic을 허용할 port 정의 → ports
network policy는 쿠버네티스 클러스터에서 사용하는 네트워크 솔루션을 통해 동작
- Network Policy 적용 : Kube-router, Calico, Romana, Weave-net
- 적용 x : FlannelKubernetes Security PrimitivesAuthentication - Who can access
[DevOps/Kubernetes] - [CKA] CKA 자격증 준비 자료 정리 7 (Storage)
'DevOps > Kubernetes' 카테고리의 다른 글
[CKA] CKA 자격증 준비 자료 정리 8 (Networking) (0) | 2021.12.22 |
---|---|
[CKA] CKA 자격증 준비 자료 정리 7 (Storage) (0) | 2021.12.18 |
[CKA] CKA 자격증 준비 자료 정리 5 (Cluster Maintenance) (0) | 2021.12.11 |
[CKA] CKA 자격증 준비 자료 정리 4 (Application Lifecycle Management) (0) | 2021.12.11 |
[CKA] CKA 자격증 준비 자료 정리 3 (Logging & Monitoring) (0) | 2021.12.07 |