티스토리 뷰
PKOS - 쿠버네티스 온라인 스터디 (5)
카테고리 없음 2023. 4. 9. 02:12보안
Instance MetaData Service (IMDS):
- 해당 인스턴스의 메타데이터를 긁어갈 수 있는 서비스, IMDSv2에서는 토큰 기반 인증 과정이 추가됐다. https://halfmoon95.tistory.com/11
- 메타데이터 탈취 시 최악의 경우, 해당 인스턴스가 사용 중인 크레덴셜 정보를 획득해 타 자원에 접근할 수 있어 관련된 Server-Side Request Forgery (SSRF) 대응 필요
https://www.version1.com/ec2-metadata-evil-or-genius/
Server Side Request Forgery (SSRF) and AWS EC2 instances after Instance Meta Data Service version 2(IMDSv2) | by Riyaz Walikar | Appsecco
IMDS의 토큰 기반 인증 과정을 제거한다면?
$ kops edit ig nodes-ap-northeast-2a
>>
spec:
# instanceMetadata:
# httpPutResponseHopLimit: 1
# httpTokens: required
$ kops update cluster --yes
# 파드 배포 후 호스트 크레덴셜 확인
$ k exec -it -- netshoot-pod-7757d5dd99-8pfd4 \
curl 169.254.169.254/latest/meta-data/iam/security-credentials/nodes.$KOPS_CLUSTER_NAME | jq
{
"Code": "Success",
"Type": "AWS-HMAC", # Hash-based message authentication code
"AccessKeyId": "holyMoly",
"SecretAccessKey": "It'sreal..",
"Token": "Mamma Mia!!",
}
번외 - boto3 인증 과정
https://tech.cloud.nongshim.co.kr/2021/03/12/boto3%EA%B0%80-aws%EC%9D%98-%EC%9E%90%EA%B2%A9%EC%A6%9D%EB%AA%85credentials%EC%9D%84-%ED%99%95%EC%9D%B8%ED%95%98%EB%8A%94-%EC%88%9C%EC%84%9C-from-python/
boto3로 리소스 확인하는 코드 짤 때 참고한 글이었는데, AWS 크레덴셜에 대해 상세히 정리돼있다. 코드는 다음과 같은 우선순위로 자격증명을 확인, 인증 요청한다.
boto3.client()
함수에 전달된 자격증명- 환경 변수
- 공유 자격증명
~/.aws/credentials
- AWS 구성파일
~/.aws/config
- AssumeRole
- boto 구성파일
/etc/boto.cfg
- 인스턴스 메타데이터
IAM Role Service Account (IRSA)
쿠버네티스 클러스터에는 다양한 서비스가 올라갈 것이고, 이때 각 파드가 접근해야 하는 자원은 상이하기 때문에 파드 수준 인가가 필요하다. 이를 위해 EKS에서는 IRSA를 이용해 Service Account(SA)별 IAM Role을 부여할 수 있다.
- https://ssup2.github.io/theory_analysis/AWS_EKS_Service_Account_IAM_Role/
- https://tech.devsisters.com/posts/pod-iam-role/
https://kim-dragon.tistory.com/279
# SA 생성
kubectl create sa foo_sa
# SA ~ 클러스터롤 바인딩
kubectl create clusterrolebinding foo_service_rbind --clusterrole=cluster_role --serviceaccount=foo_sa
data "aws_eks_cluster" "foo_cluster" {
name = "foo_cluster"
}
# 사용할 EKS 클러스터의 OIDC URL 가져오기
data "aws_iam_openid_connect_provider" "foo_oidc" {
url = data.aws_eks_cluster.my_eks.identity[0].oidc[0].issuer
}
data "aws_iam_policy_document" "foo_irsa_policy" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
# 위에서 확인한 EKS OIDC와 연결
principals {
type = "federated"
identifiers = [aws_iam_openid_connect_provider.foo_oidc.arn]
}
condition {
test = "StringEquals"
variable = trimprefix(aws_iam_openid_connect_provider.foo_oidc.url, "https://")
values = [
"system:serviceaccount:default:foo_sa""
]
}
}
}
resource "aws_iam_role" "foo_irsa" {
name = "foo_irsa"
assume_role_policy = data.aws_iam_policy_document.foo_irsa_policy.json
}
Security Context
파드에게 허용되는 보안 행동의 폭을 정의
- Privileged: 파드가 할 수 있는 내용 (Pod can do X with privilege escalation)
- Restricted: 파드가 할 수 없는 내용 (Pod can't do X due to hardening limit)
- Baseline: 최소한으로 지정된, 파드 기본 설정
주로 다음과 컨텍스트를 설정할 수 있다.
- runAsNonRoot: 루트가 아닌 다른 사용자로 실행돼야 함
- Capabilities: 파드에
linux capabilities
명령어를 통해 기능 제어 - readOnlyRootFilesystem: root FS를 RO로 할지 결정
- seLinux: SETENFORCE!
- privileged: 해당 파드가 privileged 모드로 실행되도록 설정, 노드의 모든 리소스에 접근 가능하도록 power overwhelming
- runAsUser / runAsGroup: 실행유저/그룹
kubectl get pod -n kube-system -o jsonpath={.items[*].spec.containers[*].securityContext} | jq
>>
{
"allowPrivilegeEscalation": false,
"readOnlyRootFilesystem": true
}
{
"privileged": true
}
...
# 샘플 파드 배포
nano capabilities.yaml
>>
apiVersion: v1
kind: Pod
metadata:
name: sample-capabilities
spec:
containers:
- name: nginx-container
image: masayaaoyama/nginx:capsh
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
kubectl create -f capabilities.yaml
# 파드 권한 확인
kubectl exec -it sample-capabilities -- cat /proc/1/status | egrep 'CapPrm|CapEff'
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
혹은
kubectl exec -it sample-capabilities -- capsh --print | grep Current
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+ep
# 파드 권한 추가
nano capabilities.yaml
>>
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
drop: ["AUDIT_WRITE"]
# 파드 권한 재확인
kubectl exec -it sample-capabilities -- capsh --print | grep Current
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_sys_chroot,cap_sys_time,cap_mknod,cap_setfcap+ep
혹은
kubectl exec -it sample-capabilities -- cat /proc/1/status | egrep 'CapPrm|CapEff'
CapPrm: 000000008a0435fb
CapEff: 000000008a0435fb
sysctl
개인적으로 흥미로운 주제라고 생각한다. 파드에서 sysctl, 즉 커널 파라미터를 수정할 수 있으려면? https://kubernetes.io/ko/docs/tasks/administer-cluster/sysctl-cluster/
- safe parameter
- 오직 해당 파드에만 영향을 미치는 파라미터여야 한다. (다른 파드 및 노드에 영향 X)
- 파드 리소스 제한을 벗어나는 것을 허용하지 않아야 한다.
- safe sysctl은 기본적으로 활성화된다.
net.ipv4.ip_local_port_range, net.ipv4.ping_group_range
등이 존재
- unsafe parameter
- safe parameter를 제외한 대부분의 커널 파라미터
- kubelet에서 사용 허용해줘야 함
kubelet --allowed-unsafe-sysctls 'kernel.msg*,net.core.somaxconn'
- sysctl 파라미터도 네임스페이스를 따라가므로, 각 파드는 소속 네임스페이스의 sysctl을 구성할 수 있다.
- 따라서 소속 네임스페이스가 없는 파드는 노드 레벨 -> 노드 OS에서 sysctl 구성 혹은 privilege 파드 데몬셋으로 구성
파라미터 수정으로 동작 패턴이 달라지거나 제약 사항이 변경될 수 있기 때문에, 파라미터 튜닝이 필요한 파드의 경우 taint 명령을 통해 특정 노드에 스케일링 되도록 구성하는 것을 권장한다.
도전과제 - Polaris scan 및 조치
# 레디스 배포
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm pull bitnami/redis && tar -xzvf redis-17.9.3.tgz
kubectl create ns redis && kubectl ns redis
helm install redis -f values.yaml .
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm pull fairwinds-stable/polaris && tar -xzvf polaris-5.7.3.tgz
nano polaris/values.yaml
>>
service:
# dashboard.service.type -- Service Type
type: LoadBalancer # replace 'ClusterIP' with 'LoadBalancer'
kubectl create ns polaris && kubectl ns polaris
helm install polaris -f values.yaml .
kubectl annotate service polaris-dashboard "external-dns.alpha.kubernetes.io/hostname=polaris.$KOPS_CLUSTER_NAME" -n polaris
nano redis/my-values.yaml
>
master:
resources:
limits:
cpu: 150m
memory: 512Mi
containerSecurityContext:
enabled: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
...
kubectl ns redis
helm upgrade redis -f values.yaml .
댓글