Site icon GRIP.News

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 설정에 문제가 있는 것. 간단한 경험을 공유하고자 한다.

내가 생각하는 조건

  1. 주요 서비스 목록은 확인할 수 있어야 한다.
  2. 자원 제어를 위해선 특정 Tag 를 생성해야 한다.
  3. 특정 Tag 가 있는 경우는 제어할 수 없다.
  4. 삭제는 할 수 없다.

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": "*"
        }
    ]
}

 

정책 시뮬레이터를 통해 올바르게 동작하는지 확인해보자.

 

문제가 없어 보인다. 그럼 정상적으로 동작할 것이고 이 글을 왜 쓰는가!?

“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 는 찾을 수 없었다. (힘들다 ㅠㅠ)

 

 

Exit mobile version