설명
Role 또는 ClusterRole에 secrets 리소스의 get, list, watch 또는 광범위한 권한이 포함되고 이 권한이 ServiceAccount에 바인딩되면, 해당 계정을 사용하는 파드가 허용 범위의 Secret 값을 읽을 수 있습니다. Secret에는 토큰, 비밀번호, 인증서 같은 민감한 정보가 들어가는 경우가 많습니다.
모든 워크로드가 Secret 읽기 권한을 가질 필요는 없습니다. 필요한 애플리케이션에만 좁은 범위로 부여하고 나머지 ServiceAccount에서는 제거하세요.
잠재적 영향
- 허용 범위의 비밀번호, 토큰, 키 같은 민감한 정보가 노출될 수 있습니다.
- 탈취된 자격 증명을 통해 다른 시스템으로 추가 침해가 이어질 수 있습니다.
- Secret 접근 주체가 많아질수록 권한 통제와 사고 추적이 어려워집니다.
해결 방법
- Role과 ClusterRole에서
secrets에 대한 불필요한 읽기 권한을 제거하세요. - Secret 접근이 필요한 ServiceAccount에는 필요한 네임스페이스·리소스·동작만 허용하세요.
- 기본 계정 대신 용도가 분명한 ServiceAccount를 사용하고 실제 바인딩과 권한을 정기적으로 점검하세요.
예시
RoleBinding은 default 네임스페이스의 Role을 kube-system의 default ServiceAccount에 연결합니다. 해당 계정은 별도로 존재해야 합니다. 변경 후의 Pod 조회 권한도 실제 업무에 필요한 경우에만 남기세요.
변경 전
hcl
resource "kubernetes_role" "role_name" {
metadata {
name = "terraform-example"
}
rule {
api_groups = [""]
resources = ["secrets"]
verbs = ["*"]
}
}
resource "kubernetes_role_binding" "example" {
metadata {
name = "terraform-example"
namespace = "default"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = kubernetes_role.role_name.metadata[0].name
}
subject {
kind = "ServiceAccount"
name = "default"
namespace = "kube-system"
}
}
변경 후
hcl
resource "kubernetes_role" "role_name" {
metadata {
name = "terraform-example"
}
rule {
api_groups = [""]
resources = ["pods"]
verbs = ["get", "list", "watch"]
}
}
resource "kubernetes_role_binding" "example" {
metadata {
name = "terraform-example"
namespace = "default"
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = kubernetes_role.role_name.metadata[0].name
}
subject {
kind = "ServiceAccount"
name = "default"
namespace = "kube-system"
}
}
설명:
- 변경 전: Secret에 대한 모든 동작을 허용하는 Role을 연결합니다.
- 변경 후: Secret 권한을 제거하고 Pod 조회 권한을 연결합니다.