들어가기 앞서
안녕하세요, 클래스메소드의 서은우 입니다.
좀 더 효율적으로 AWS 환경을 관리하기 위해 서비스나 기능을 기준으로 AWS 계정을 생성해 사용하는 것을 다중 계정 전략(Multi-Account Strategy) 라고 합니다.
하지만 계정이 늘어나면 늘어날 수록 오히려 각 계정을 관리는데에 어려움이 생기게 됩니다.
계정을 효율적으로 관리하기 위한 방법의 일환으로 AWS Single Sign-On(IAM Identity Center)를 사용할 수 있지만, AWS Organizations를 필수로 사용해야한다는 전제가 있습니다.
때문에 본 블로그에서는 AWS Single Sign-On의 대안이 될 수 있는 "점프 계정(Jump Account)"의 사용에 대해 설명하고자 합니다.
점프 계정이란
점프 계정은 Bation Host를 생각하시면 쉽게 이해하실 수 있습니다. Bastion Host는 주로 외부에서 내부 서버에 접근하기 위해 사용합니다.
점프 계정도 이와 비슷한 역할을 하며, 점프 계정을 통하여 다른 계정의 권한을 사용(Switch Role)할 수 있수 있습니다.
점프 계정에 필요한 IAM 유저/그룹을 모아두고, 이를 통해 다른 여러 개의 계정의 권한을 이용하는 방식이기 때문에, 하나의 점프 계정을 사용하는 것으로 다수의 계정을 더욱 효율적으로 관리할 수 있게 됩니다.
또한, 하나의 AWS 계정을 점프 계정으로 이용하기 때문에 AWS Organizations를 사용하지 않는 환경의 경우 AWS Single Sign-On의 좋은 대안이 될 수 있습니다.
직접 해봅시다
하고자 하는 것
본 블로그에서는 점프 계정을 운용을 위해 다음과 같은 리소스들을 생성합니다.
- 점프 계정
- IAM Group: 다른 계정으로의 전환을 위해 AssumeRole을 허용하는 권한, 자체적으로 MFA를 관리하고 비밀번호를 변경할 수 있는 권한, 소스 ip 액세스 제한
- 담당자가 사용할 IAM User
- 대상 계정
- 스위치 롤 대상 IAM Role: AmazonEC2ReadOnlyAccess, 특정 유저만 역할을 사용가능하게 제한
점프 계정의 IAM Group 과 IAM User에는 특정 사용자에 대해서만 해당 IAM 리소스의 액세스를 허가하기 위해 소스 ip로 액세스를 제한하는 정책을 설정합니다.
또한 대상 계정의 스위치 롤의 대상이 되는 IAM Role 에 대해서는 필요 최소한의 권한만 부여(본 블로그의 경우 AmazonEC2ReadOnlyAccess), 특정 유저만 역할을 사용할 수 있게 하기 위한 신뢰 관계를 정의합니다. (소스 ip로 제한하는 것도 가능합니다.)
점프 계정 IAM 리소스 생성
그렇다면 점프 계정으로 들어가 사용할 IAM Group / User 를 생성하도록 하겠습니다.
- Jump group
다른 계정에 스위치 롤을 할 수 있고 소스 IP로 액세스를 제한하는 정책을 추가합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "JumpAccount",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"x.x.x.x/x"
]
}
}
}
]
}
그리고 해당 그룹에 속한 유저 자신이 MFA를 자체적으로 관리할 수 있는 정책을 추가합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListActions",
"Effect": "Allow",
"Action": [
"iam:ListUsers",
"iam:ListVirtualMFADevices"
],
"Resource": "*"
},
{
"Sid": "AllowIndividualUserToListOnlyTheirOwnMFA",
"Effect": "Allow",
"Action": [
"iam:ListMFADevices"
],
"Resource": [
"arn:aws:iam::*:mfa/*",
"arn:aws:iam::*:user/${aws:username}"
]
},
{
"Sid": "AllowIndividualUserToManageTheirOwnMFA",
"Effect": "Allow",
"Action": [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice"
],
"Resource": [
"arn:aws:iam::*:mfa/${aws:username}",
"arn:aws:iam::*:user/${aws:username}"
]
},
{
"Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA",
"Effect": "Allow",
"Action": [
"iam:DeactivateMFADevice"
],
"Resource": [
"arn:aws:iam::*:mfa/${aws:username}",
"arn:aws:iam::*:user/${aws:username}"
],
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
},
{
"Sid": "AllowGetAccountPasswordPolicy",
"Effect": "Allow",
"Action": "iam:GetAccountPasswordPolicy",
"Resource": "*"
},
{
"Sid": "AllowChangePassword",
"Effect": "Allow",
"Action": "iam:ChangePassword",
"Resource": "arn:aws:iam::*:user/${aws:username}"
},
{
"Sid": "BlockMostAccessUnlessSignedInWithMFA",
"Effect": "Deny",
"NotAction": [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ListUsers",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice",
"iam:GetAccountPasswordPolicy",
"iam:ChangePassword"
],
"Resource": [
"arn:aws:iam::*:mfa/${aws:username}",
"arn:aws:iam::*:user/${aws:username}"
],
"Condition": {
"BoolIfExists": {
"aws:MultiFactorAuthPresent": "false"
}
}
}
]
}
대상 계정 IAM 리소스 생성
스위치 롤 대상 역할로의 액세스를 제어하기 위해 대상 역할에 다음과 같은 신뢰 관계 정책을 정의할 수 있습니다.
- 특정 IAM User를 보안 주체로 설정하여 엑세스를 제한
- 특정 IP 주소를 기준으로 액세스를 제한
-
Target IAM Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AWS-account-ID:user/user-name"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true" // MFA 사용을 확인
},
"IpAddress": {
"aws:SourceIp": [
"x.x.x.x/x"
]
}
}
}
]
}
확인
1. 점프 유저로 로그인 후 스위치 롤을 시도합니다
2. 대상 롤로 스위치 롤을 합니다
- 만약 액세스 제어 정책에 의해 스위치 롤을 할 수 없는 경우에는 다음과 같이 됩니다.
신뢰 정책에 해당하는 유저의 경우, 성공적으로 액세스할 수 있습니다.
3. 위임 받은 역할을 사용합니다.
본 블로그의 대상 역할의 경우, AmazonEC2ReadOnlyAccess 정책이 할당되어 있기 때문에, 해당 정책의 권한 이외의 동작은 모두 거부되게 됩니다.
- 현재 계정의 EC2 인스턴스 목록을 확인할 수 있습니다.
- S3 콘솔에 액세스하면 권한 거부 오류가 발생합니다.
참조
-
https://d0.awsstatic.com/events/jp/2017/summit/slide/D4T2-2.pdf