안녕하세요, 짧은머리 개발자입니다.
클라우드는 보안이 매우 중요한 환경인데요, 오늘은 Google Cloud Platform에서 관리중인 여러 프로젝트간 서비스 접근을 어떻게 구성하는지 공유하려 해요.
클라우드는 서비스로 제공하는 XaaS에 대한 접근을 제어할 수 있도록 IAM을 제공하는데 AWS, GCP와 같은 거대 클라우드는 IAM Role for Service Account(IRSA)라 불리는 메커니즘을 통해 더 세밀한 제어를 가능하게 해요.
이름에서 유추할 수 있듯이 서비스 계정을 위한 IAM 역할을 부여함으로써 그 메커니즘이 동작해요.
GCP의 서비스에 등록된 Service Account는 구글의 메타데이터 서버를 통해 자격 증명에 접근하고, 필요한 토큰을 관리해요.
- 이전에 작성한 Github과 같이 GCP 외부에서 접근하는 경우에는 Security Token Services를 통해 단기 자격을 증명해주는 토큰을 발급받아야 하고, 이 때 roles/iam.serviceAccountTokenCreator과 같은 역할이 추가로 필요해요.
GCP는 구조를 계정 수준 리소스부터 서비스 수준 리소스로 나누어 관리할 수 있는데, 베스트 프랙티스로 GCP 내부에 생성할 그 구조를 회사의 조직 구조와 일치하게 만드는 것을 권장해요.
이는 곧 분리되어 있는 프로젝트 간 배포된 서비스간 접근을 허용해야 하는 경우가 발생할 수 있어요.
제가 수행했던 프로젝트의 경우에도 분리되어있는 프로젝트간 버킷에 접근해야 할 필요가 있었는데요, 이를 어떻게 구성했는지 공유하려 해요.
프로젝트 구성은 위와 같은 형태로, Project A에서 동작중인 Application A는 Project B의 Bucket B의 오브젝트에 접근할 수 있어야 하며, Bucket B는 Private하며 IAM을 통해 접근을 제한하고 있어요.
이를 해결하기 위해 우리는 싱글 프로젝트와 같이 Project A의 Application A에 서비스 계정을 추가한 뒤, Project B의 IAM을 구성해줘야 해요.
이 때 Project B에서 bucket-sa@project-a.iam.gserviceaccount.com 서비스 계정이 가져야할 역할은 다음과 같아요.
- Bucket B에서 행할 작업에 따른 Storage 접근 권한, roles/storage.objectViewer
💡 roles/iam.serviceAccountUser의 경우, 특정 사용자 혹은 서비스 계정이
bucket-sa와 같이 IAM 역할을 갖는 서비스 계정으로 가장(impersonate)해야 할 때 필요해요.
이 경우에는 Application에 부착된 서비스 계정이 직접적으로 사용하기 때문에 필요하지 않아요.
여기까지 수행하고 나면 RBAC이 구성되고, Application A에서 Bucket B에 정상적으로 접근할 수 있어요.
그런데 만약 Project B에 Bucket B 말고 여러 버킷이 존재한다며면, bucket-sa 서비스 계정을 이용해서 모든 버킷에 접근 가능하게 돼요. 이는 보안상 매우 취약한 설정이며, 따라서 Attribute Based Access Control(ABAC)을 구성해야 해요.
ABAC은 이름에서 유추할 수 있듯 속성 기반의 접근 제어 메커니즘이에요. 기존의 bucket-sa 서비스 계정은 역할을 기반으로 Bucket B에 접근 가능하도록 구성했다면, 여기에 속성을 추가하여 더 세밀한 제어를 할 수 있어요.
우리에게 필요한 세밀한 제어는 다음과 같아요.
- Bucket B에 접근할 수 있어야 한다.
- Bucket B 내부의 오브젝트를 볼 수 있어야 한다.
- Bucket B 내부의 디렉토리 구조를 볼 수 있어야 한다.
이를 해결하기 위해 GCP는 IAM 역할에 조건을 설정할 수 있고, 역할의 조건에 필요한 리소스 유형과 리소스 이름은 다음 링크에서 확인할 수 있어요.
- 리소스 유형: https://cloud.google.com/iam/docs/conditions-resource-attributes?hl=ko#resource-type
- 리소스 이름: https://cloud.google.com/iam/docs/conditions-resource-attributes?hl=ko#resource-name
우리에게 필요한 속성을 정리하면 다음과 같아요.
# 허용할 서비스 계정
member = "bucket-sa@project-a.iam.gserviceaccount.com"
# 허용할 역할
roles = [
"roles/storage.objectViewer",
]
# 역할 + 대상 = 서비스 계정이 접근할 수 있는 대상
target_resources = [
# 버킷의 이름이 bucket-b와 같아야 한다.
{
type = "storage.googleapis.com/Bucket",
name = "projects/_/buckets/bucket-b"
option = "equal"
},
# 접근하고자 하는 오브젝트는 bucket-b의 objects여야 한다.
{
type = "storage.googleapis.com/Object",
name = "projects/_/buckets/bucket-b/objects/"
option = "startsWith"
},
# 접근하고자 하는 폴더는 bucket-b의 관리형 폴더여야 한다.
{
type = "storage.googleapis.com/ManagedFolder",
name = "projects/_/buckets/bucket-b/managedFolders/"
option = "startsWith"
}
]
버킷 뿐만 아니라 다른 XaaS에 대한 접근이 필요할 때도 위와 같이 서비스 계정을 구성한다면 프로젝트간 IRSA를 구성할 수 있어요.
오늘도 읽어주셔서 감사합니다.
'DevOps > Cloud' 카테고리의 다른 글
GKE와 Cloud Load Balancing 연결하기 (1) | 2024.07.15 |
---|