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-api 서버 → 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-api 서버가 요청을 통해) 상태관리를 위한 api를 제공하므로 자격증명 필요
- kube-api 서버 → 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
- private key 생성
- openssl genrsa -out ca.key 2048
- ca.key
- Certificate Signing Request
- openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr
- ca.csr
- 모든 detail이 있는 인증서지만, 서명이 되어있지 않은 상태
- Signing Certificate (인증서 생성)
- 생성한 private key를 통해 CSR에 서명
- openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
- ca.crt
- CA가 자신의 private key와 root certificate file을 가지게 됨
Client Certificate
admin user를 위한 certificate 생성
- private key 생성
- openssl genrsa -out admin.key 2048
- Certificate Signing Request
- openssl req -new -key admin.key -subj "/CN=kube-admin" -out admin.csr
- 사용자 이름을 명시 (kube-admin)
- Singing Certificate
- openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt
- 앞서 만든 ca.crt 와 ca.key 를 통해 인증서를 서명
- 위 과정은 새로운 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-api 서버에 요청시 생성한 key pair을 넣어줌
- curl https://kube-apiserver:6443/api/v1/pods --key admin.key --cert admin.crt --cacert ca.crt
- 또는 kubeconfig 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-api 서버 certificate
- kube-api 서버는 많은 component의 요청이 들어오고, 많은 operation이 kube-api 서버를 통해 이루어지는 만큼, alias 가 많음
- alias를 지정하는 방법
- open ssl config 파일 → openssl.cnf 파일을 생성
- alt_names 에 대체 DNS 또는 IP 지정
- openssl req -new -key apiserver.key -subj "/CN=kube-apiserver" -out apiserver.csr -config openssl.cnf
- cert signing request 시 해당 config 파일 지정
- open ssl config 파일 → openssl.cnf 파일을 생성
- 그 후 인증서 사인
- openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -out apiserver.crt
kubelet certificate
node 마다 있기 때문에, 각 node에 certificate 필요
→ 이름이 node 에 따라 정해진다.
certificate 를 생성하고, kubelet-config 파일에 해당 정보를 준다. (각 node에 수행)
kubelet 은 client로서 kube-api 서버와 통신하기 위해 client cert도 필요
- api 서버가 어떤 노드인지 알수있도록 이름이 지정됨
- 노드는 sytem component 이므로 system:node:node01 와 같이 지정
- 그리고 api 서버가 올바른 permission 을 주기 위해, node들을 SYSTEM:NODES 라는 group에 추가
Certificate 상세 확인
kube-api서버 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.
- 새로운 사용자는 private key 생성
- openssl genrsa -out jane.key 2048
- openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr
- 위 결과와 함께 cert siging request를 보냄
- request를 받은 admin은 CertificateSigningRequest 생성
- apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: john spec: groups: - system:authenticated usages: - client auth request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRV...
- 받은 csr 내용은 base64를 통해 encode 후 넣음
- cat jane.csr | base64
- 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
새 user에 대해 인증하는 과정
https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user
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-api 서버 옵션으로 지정됨
(—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 ClusterRolename: pod-reader# this must match the name of the Role or ClusterRole you wish to bind toapiGroup: 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 을 어떻게 넘기는가?
- 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>
- 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
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
리눅스 기능 추가 및 제거
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
'Kubernetes (k8s)' 카테고리의 다른 글
[k8s] Static Pod (0) | 2023.04.17 |
---|---|
[k8s] Node resource usage, Pods and their containers resource usage 리소스 사용량 조회 (2) | 2023.04.13 |
[k8s] Cluster Maintenance (0) | 2023.04.08 |
[k8s] Application Lifecycle Management (0) | 2023.04.07 |
[k8s] kubernetes Scheduling (0) | 2023.04.05 |
댓글