AWS, IAM 에 특정 TAG KEY/VALUE 조건을 사용한 리소스 제어
AWS Identity and Access Management(IAM)는 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스다. IAM 에 대한 자세한 내용은 AWS Documents 를 참고하길 바라며, 이 글에서는 IAM 을 통한 권한 제어를 간단히 설명하고자 한다.
인프라를 설계하고, 형상을 만들어 개발자들에게 Access Key 를 제공해 직접 해당 Service/Instance에 접근하는 형태가 일반적이다. 하지만, 불가피하게 AWS Web Console 을 사용해야 하거나, AWS API 를 사용해야 하는 경우 Account 생성 및 권한을 부여해야 하는 경우가 있다. 문제는 IAM Role 설정에 문제가 있는 것. 간단한 경험을 공유하고자 한다.
내가 생각하는 조건
- 주요 서비스 목록은 확인할 수 있어야 한다.
- 자원 제어를 위해선 특정 Tag 를 생성해야 한다.
- 특정 Tag 가 있는 경우는 제어할 수 없다.
- 삭제는 할 수 없다.
AWS IAM 의 기본 권한 구조는 다음과 같다.
Step 1. IAM 정책을 생성하자. Describe* 는 기본적인 목록을 볼 수 있게 만들어준다. 이외에 ‘태그 지정’은 기본적으로 사용할 수 있도록 제한을 풀자.

Step 2. 특정 Tag 가 존재하는 경우에만 쓰기(=제어) 가 가능하다. RequestTag 로 지정하면 된다. 아래 내용은 WorkerName Tag 에 내 ID 가 있는 경우에만 제어할 수 있다는 의미다.

Step3. 특정 Tag 가 있는 경우 제어할 수 없다. 제어하지 말아야하는 서비스/인스턴스가 있는 경우에 사용한다.

Step4. 기본적으로 ‘삭제’, ‘차단(Terminate)’ 는 막는다. 참고로, 이 부분을 지정하지 않고, 위에 ‘허용/쓰기’ 부분에서 이 요소드를 제거해도 무관하다.

자, 생성된 IAM ROLE 은 다음과 같다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DisassociateAddress",
"ec2:CopySnapshot",
"ec2:ImportVolume",
"ec2:UnmonitorInstances",
"ec2:PurchaseReservedInstancesOffering",
"ec2:ExportTransitGatewayRoutes",
"ec2:MoveAddressToVpc",
"ec2:DetachClassicLinkVpc",
"ec2:MonitorInstances",
"ec2:PurchaseHostReservation",
"ec2:WithdrawByoipCidr",
"ec2:CopyImage",
"ec2:A*",
"ec2:UpdateSecurityGroupRuleDescriptionsIngress",
"ec2:StartInstances",
"ec2:UnassignIpv6Addresses",
"ec2:R*",
"ec2:UnassignPrivateIpAddresses",
"ec2:ImportImage",
"ec2:EnableVpcClassicLink",
"ec2:PurchaseScheduledInstances",
"ec2:DetachVolume",
"ec2:DisassociateTransitGatewayRouteTable",
"ec2:Create*",
"ec2:UpdateSecurityGroupRuleDescriptionsEgress",
"ec2:Can*",
"ec2:DetachNetworkInterface",
"ec2:ImportInstance",
"ec2:BundleInstance",
"ec2:ImportKeyPair",
"ec2:DisassociateClientVpnTargetNetwork",
"ec2:ProvisionByoipCidr",
"ec2:ImportSnapshot",
"ec2:Disable*",
"ec2:DetachInternetGateway",
"ec2:CopyFpgaImage",
"ec2:StopInstances",
"ec2:DisassociateRouteTable",
"ec2:DisassociateSubnetCidrBlock",
"ec2:EnableVolumeIO",
"ec2:DetachVpnGateway",
"ec2:ImportClientVpnClientCertificateRevocationList",
"ec2:Modify*",
"ec2:DisassociateIamInstanceProfile",
"ec2:EnableVgwRoutePropagation",
"ec2:EnableVpcClassicLinkDnsSupport",
"ec2:EnableTransitGatewayRouteTablePropagation",
"ec2:ConfirmProductInstance"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/WorkerName": "${aws:username}"
}
}
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"ec2:Desc*",
"iam:PassRole",
"ec2:DeleteTags",
"ec2:CreateTags",
"ec2:RunInstances"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Deny",
"Action": [
"ec2:Terminate*",
"ec2:Delete*"
],
"Resource": "*"
}
]
}
정책 시뮬레이터를 통해 올바르게 동작하는지 확인해보자.
- https://policysim.aws.amazon.com/home/index.jsp

문제가 없어 보인다. 그럼 정상적으로 동작할 것이고 이 글을 왜 쓰는가!?
“You are not authorized to perform this operation.”

정상적으로 Tag 가 있음에도 불구하고 제어할 수 없기 때문. 그리고 이 오류에는 별도의 메시지를 동반하기 때문에 능동적으로 조치할 수가 없다. 이상한건, RunInstance/StopInstance 등의 명령은 사용할 수 있지만, 수정(Modify), 추가(Add) 계열 기능에서 주로 오류가 발생한다. 원인은 정확하지 않다. 하지만 이래 저래 테스트 해 본 결과 Condition 부분을 수정해야 한다는 것을 찾았다.
단순히 StringEquals 만 있는 경우 특정 기능 동작 시 ResourceTag 부분이 동작하지 않는다는 걸 발견했다. 이 문제는 “ForAllValues” 를 추가해 줌으로서 해결 가능했던 것. 참고로 ForAllValue는 에디터에서 선택할 수 있는 방법이 없다.
"Condition": {
"ForAllValues:StringEquals": {
"ec2:ResourceTag/WorkerName": "${aws:username}"
}
}
이외에 AWS IAM 에 여러가지 문제를 발견했다. RDS 의 Tag 를 추가하려면 req-tag 를 사용하라 메뉴얼에 나와 있지만, 실제 IAM 해당 Key 는 찾을 수 없었다. (힘들다 ㅠㅠ)

