GCP Multi Project에 대한 IRSA 구성하기
안녕하세요, 짧은머리 개발자입니다.
클라우드는 보안이 매우 중요한 환경인데요, 오늘은 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를 구성할 수 있어요.
오늘도 읽어주셔서 감사합니다.