AWS 기술 블로그

ABAC 구성을 위한 AWS IAM 정책 설정(EC2권한)하기

AWS에서 권한을 효율적으로 관리하기 위한 방법론 중 하나인 ABAC(Attribute Based Access Control)은 태그를 이용하여 보안 주체에 권한을 할당함으로써 조직에서 AWS 자원에 접근이 필요한 사용자에게 권한을 부여하는 방법입니다. ABAC에서의 Attribute는 태그를 이야기하는 것으로써 ABAC은 다시 말해 “태그에 기반한 접근 제어”라고 말할 수 있습니다. 따라서, AWS 환경에서의 ABAC을 잘 사용하기 위해서는 AWS Identity and Access Management(IAM) 정책을 생성할 때 사용할 수 있는 태그의 조건들과 태그 조건을 사용할 때 고려해야 하는 제약사항 등에 대한 이해가 선행되어야 합니다.  이 글에서는 여러분들이 IAM 정책 생성 시 사용할 수 있는 태그 사용 조건에 대해 살펴보고 실제 운영환경에서 ABAC을 사용하는 경우 참고할 수 있는 IAM 정책 구성하는 방법에 대해 알아보도록 하겠습니다.

그림. ABAC 개념도

ABAC을 구성하기 위한 IAM 정책에 대해 살펴보기에 앞서 IAM 정책에서 사용할 수 있는 태그에 대해 살펴보도록 하겠습니다. IAM 정책은 자격증명의 주체(Identity)가 특정 자원(Resource)에 어떤 행위(Action)를 할 때 해당 행위를 허용하거나 차단하는 내용을 담고 있습니다. 그리고 IAM 정책은 태그와 관련된 조건(Condition)을 이용하여 자격증명의 주체(Identity)에 부여된 태그값을 참고하거나, 새로운 태그 생성 시 그 값을 참고하거나, 접근하고자 하는 자원에 부여된 태그의 값을 참고할 수 있습니다. IAM 정책에 사용할 수 있는 태그 조건 키(Condition Key)는 그 사용 용도와 목적에 따라 아래와 같이 크게 4가지로 나뉩니다.

  • aws:RequestTag
  • aws:ResourceTag
  • aws:PrincipalTag
  • aws:TagKeys

1. 태그 조건 키(Condition Key)의 종류

그럼 태그와 관련된 각각의 조건 키(Condition Key)에 대해 살펴보도록 하겠습니다.

aws:RequestTag

보안 주체가 새로운 태그를 부여하려고 하는 경우 새로운 태그에 사용될 태그의 키(Key)나 값(Value)을 조건으로 지정하기 위한 용도로 사용됩니다. 예를 들어, 관리자가 Amazon Elastic Compute Cloud(EC2) 인스턴스에 특정 키(environment)에  지정된 태그 값(preprod, production) 중 하나를 반드시 설정하도록 강제하고 싶다면 aws:RequestTag 조건 키를 사용하여 아래와 같은 정책을 적용할 수 있습니다.

정책 예제

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "ec2:CreateTags",
        "Resource": "arn:aws:ec2:*:*:instance/*",
        "Condition": {
            "StringEquals": {
                "aws:RequestTag/environment": [
                    "preprod",
                    "production"
                ]
            },
            "ForAllValues:StringEquals": {"aws:TagKeys": "environment"}
        }
    }
}

aws:ResourceTag

사용자의 요청에 대해 접속하고자 하는 AWS 자원이 가지고 있는 태그 키/값을 비교하는 용도로 사용됩니다. 예를 들어, 관리자가 EC2 인스턴스에 Owner라는 태그 키를 부여한 후 각 사용자의 username을 EC2 인스턴스에 태그값으로 부여하여, 사용자별로 자신에게 부여된 username과 일치하는 태그값을 갖는 EC2 인스턴스에 대해서만 인스턴스를 시작/중지할 수 있는 권한을 부여하고 싶다면 아래와 같은 정책을 적용할 수 있습니다.

정책 예제

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {"aws:ResourceTag/Owner": "${aws:username}"}
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
        }
    ]
}

참고. aws:ResourceTag은 글로벌 조건 키(Global Condition Key)입니다. 그리고 일부 서비스의 경우 ResourceTag와 관련한 서비스 지정 조건 키(Service Specific Condition Key)가 있습니다. 예를 들어, EC2 서비스에서 사용하는 ResourceTag를 IAM 정책에 명시하려고 할 때에는  aws:ResourceTag가 아니라 ec2:ResourceTag를 사용해야 합니다.

aws:PrincipalTag

사용자에게 부여된 태그 키/값을 비교하는 용도로 사용됩니다. 예를 들어, IAM 사용자 혹은 역할에 부여된 태그의 키/값이 department/hr인 경우에 한해서만 IAM의 모든 권한을 허용하고자 한다면 아래와 같은 정책을 적용할 수 있습니다.

정책 예제

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:*",
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:PrincipalTag/department": "hr"
                }
            }
        }
    ]
}

aws:TagKeys

사용자의 요청에 포함되는 태그 키의 이름을 비교하는 용도로 사용됩니다. 예를 들어, AWS Secrets Manager를 통하여 새로운 Secret을 생성할 때 반드시 지정된 태그 키를 할당하도록 강제하고 싶다면 아래와 같은 정책을 적용할 수 있습니다.

참고. aws:TagKeysForAllValues 혹은 ForAnyValues와 같은 집합 연산자와 함께 사용됩니다.

정책 예제

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "secretsmanager:CreateSecret",
            "secretsmanager:TagResource"
        ],
        "Resource": "*",
        "Condition": {
            "ForAllValues:StringEquals": {
                "aws:TagKeys": [
                    "environment",
                    "cost-center"
                ]
            }
        }
    }
}

여기까지 간단하게 IAM 정책에서 사용할 수 있는 태그와 관련한 조건 키들을 살펴봤습니다.

2. ABAC을 위한 IAM 정책 생성 시 자주 하는 실수

그렇다면, 아래와 같은 조건들을 만족하는 ABAC을 위해서는 어떻게 IAM 정책을 생성하면 될까요?

  • 조건 1. ID 제공업체(IdP, Identity Provider)와 AWS IAM Identity Center를 SAML로 연동
  • 조건 2. ID 제공업체의 각 사용자에 Department 태그 키를 부여하고 부서별로 태그값 부여. (예, SA, SRE, DEV 등)
  • 조건 3. AWS IAM Identity Center를 통해 AWS 권한을 부여 받은 각 사용자는 자신에게 부여된 태그 키/값과 일치하는 태그 키/값을 부여한 경우에만 EC2 인스턴스 생성 및 관리 가능

“조건 1”과 “조건 2”는 외부 ID 제공업체(IdP)와 AWS IAM Identity Center를 연동하면 만족할 수 있는 조건이므로 이 글에서는 연동을 위한 자세한 설정은 생략하도록 하겠습니다. SAML을 이용하여 AWS IAM Identity Center와 연동 설정과 관련한 글은 링크를 참고하시기 바랍니다.

“조건 3”을 만족하기 위해서는 어떤 IAM 정책을 생성하면 가능할지 차근차근 살펴보도록 하겠습니다. 먼저, 사용자의 요청에서 사용자에 부여된 태그를 조건으로 사용할 수 있는 조건 키인 “aws:PrincipalTag”와 사용자가 접근하는 자원인 “aws:ResourceTag”를 이용하여 아래와 같은 정책을 생성하면 가능할까요?

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "ec2:*",
        "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}"
                }
          }
    }
}

위 정책의 내용 중 가장 중요한 부분인 “Condition” 부분을 살펴보도록 하겠습니다.

"ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}"

이 내용을 글로 풀어서 설명해본다면 사용자의 요청에 포함된 태그 키(PrincipalTag) 중 Department라는 키의 값과 접근하려고 하는 EC2에 부여된 키(ResourceTag) 중 Department라는 키의 값이 일치할 때 참으로 간주하겠다는 의미입니다. 즉, 사용자는 자신에게 부여된 태그 키/값과 일치하는 EC2에 접근하는 경우에만 권한을 부여 받을 수 있다는 것처럼 보입니다. 그렇다면 관리자는 이와 같은 IAM 정책을 사용했을 때 위에서 언급한 “조건 3”을 만족할 수 있을까요? 정답은 “만족할 수 없다” 입니다. 왜냐하면, EC2를 생성하고 관리하기 위해서는 다양한 Action이 사용됩니다. 예를 들면, 아래와 같은 EC2의 Describe 관련 Action 들을 생각해볼 수 있습니다.

                "ec2:DescribeInstances",
                "ec2:DescribeImages",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeKeyPairs",
                "ec2:DescribeVpcs",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",

정책에서 Action을 “ec2:*” 로 허용했기 때문에 당연히 이와 같은 Describe 관련한 Action 들은 포함되어 있습니다. 그렇다면 이 Describe 관련 Action 들은 허용될 수 있는지 살펴보도록 하겠습니다.

Describe 관련 Action과 관련한 사용자의 요청에는 PrincipalTag가 포함되어 있습니다. 하지만 Describe 관련 Action은 특정 자원에 대해 ec2:ResourceTag를 조건으로 사용할 수 없는 Action 들입니다. 따라서, 위 정책을 그대로 사용하는 경우 Describe Action 들에 대해서는 조건의 내용이 모두 거짓으로 판명되게 됩니다. 따라서, 사용자가 Describe 관련 Action을 수행하는 경우 태그가 포함된 조건 때문에 권한이 부여되지 않아 결국 필요한 작업을 수행할 수 없게 됩니다.

3. ABAC을 위한 올바른 IAM 정책 생성

그렇다면 ABAC을 만족하기 위해서는 기존의 정책을 어떻게 변경해야 할까요?

ABAC을 위한 정책을 생성하기 위해서는 위의 예제로 나와 있는 기존 정책을 좀 더 세분화해서 생성해야 합니다. 예를 들면, 태그 조건 키를 사용할 수 없는 Action을 선별하고 태그 조건 키를 사용할 수 있는 Action 들에 대해서도 선별하여 하나의 Statement 안에 여러 가지 조건이 적용된 IAM 정책을 생성하여야 합니다.

이 글에서 예제로 다루고 있는 EC2 서비스와 관련한 ABAC을 만족하기 위해서는 아래와 같이 EC2 Action 들이 여러 블록으로 세분되어야 합니다.

  • aws:RequestTag, aws:ResourceTag와 함께 사용할 수 없으며 Read 권한만을 갖는 Action 블록
  • ABAC 구현이 가능한(aws:PrincipalTagResourceTag의 맵핑) Action 블록
  • AWS 관리 콘솔에서 EC2 인스턴스 실행을 위한 “ec2:RunInstances” Action 중 Tag 정책과 무관하게 허용하고자 하는 자원 정의 블록
  • EC2 인스턴스 생성 시 반드시 포함되어야 하는 태그 키/값을 정의하는 Action 블록
  • 볼륨을 생성하거나 새로운 EC2 인스턴스를 생성하는 단계에서만 태그를 생성할 수 있도록 허용하는 블록

다음은 위에서 언급된 각 Action 블록에 대한 예시입니다.

aws:RequestTag, aws:ResourceTag와 함께 사용할 수 없으며 Read 권한만을 갖는 Action 블록

설명: EC2 의 Action 중 Describe 와 관련한 Action은 태그와 관련한 Condition과 함께 사용할 수 없습니다. 따라서 별도의 블록으로 구분하여 작성하였으며 Resource의 경우 “*” 로 표기되어 있으나 필요시 최소한의 EC2 자원 경로를 지정할 수 있습니다.

       {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*"
            ],
            "Resource": "*"
        }

ABAC 구현이 가능한(aws:PrincipalTagResourceTag의 맵핑) Action 블록

설명: ABAC을 구현할 수 있는 "ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}" 조건 키를 사용할 수 있는 EC2 Action 들을 대상으로 권한을 부여하는 블록입니다. 이 블록을 통하여 사용자의 PrincipalTagDepartment라는 키의 값과 호출 대상 EC2 인스턴스의 ResourceTagDepartment라는 키의 값이 같은 경우에만 EC2 인스턴스를 시작/중지/종료하도록 권한을 부여할 수 있습니다.

        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:TerminateInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}"
                }
            }
        }

AWS 관리 콘솔에서 EC2 인스턴스 실행을 위한 “ec2:RunInstances” Action 중 태그 정책과 무관하게 허용하고자 하는 자원 정의 블록

설명: RequestTag를 이용하여 태그를 부여하거나 ResourceTag를 이용하여 EC2 인스턴스의 태그를 참조하는 조건 키를 사용할 수 있지만 태그로 권한을 제한하는 경우 AWS 관리 콘솔을 통해 EC2 인스턴스를 시작했을 때 권한 문제를 유발할 수 있는 자원에 대해서는 별도로 Resource를 구분하여  ec2:RunInstances에 대한 권한을 부여하는 블록입니다.

        {
            "Effect": "Allow",
            "Action": "ec2:RunInstances",
            "Resource": [
                "arn:aws:ec2:*::image/*",
                "arn:aws:ec2:*::snapshot/*",
                "arn:aws:ec2:*:*:subnet/*",
                "arn:aws:ec2:*:*:security-group/*",
                "arn:aws:ec2:*:*:key-pair/*"
            ]
        }

EC2 인스턴스 생성 시 반드시 포함되어야 하는 태그 키/값을 정의하는 Action 블록

설명: EC2 인스턴스를 생성하고자 하는 사용자가 지정된 태그 키/값을 반드시 사용하여 생성하도록 강제하여 EC2 인스턴스 생성 이후 EC2 인스턴스에 대한 시작/중지/종료와 관련한 권한을 ABAC 기반으로 부여할 수 있도록 하는 블록입니다.

        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateVolume",
                "ec2:RunInstances"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:volume/*",
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ec2:*:*:network-interface/*"
            ],
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/Department": [
                        "SA",
                        "SRE",
                        "DEV"
                    ],
                    "aws:RequestTag/Name": "*"
                },
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "Department",
                        "Name"
                    ]
                }
            }
        }

태그 생성을 볼륨을 생성하거나 새로운 EC2 인스턴스를 생성하는 단계에서만 허용하도록 하는 블록

설명: 사용자에게 태그를 생성할 수 있는 권한을 부여하지만, EC2 인스턴스를 생성하는 단계에서 volume, instance, network-instance에 대해서 요청 Action이 RunInstances/CreateVolume일 경우에만 허용하도록 하는 블록입니다.

        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:volume/*",
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ec2:*:*:network-interface/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": [
                        "RunInstances",
                        "CreateVolume"
                    ]
                }
            }
        }

4. ABAC 기반 EC2 제어를 위한 IAM 정책

위에서 예시를 통해 목적과 태그에 대한 지원 여부 등을 기반으로 하여 세분화한 다섯 가지 Action 블록을 모두 모아 하나의 IAM 정책으로 정리하면 아래와 같습니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Describe*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:TerminateInstances",
                "ec2:StopInstances"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Department": "${aws:PrincipalTag/Department}"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "ec2:RunInstances",
            "Resource": [
                "arn:aws:ec2:*::image/*",
                "arn:aws:ec2:*::snapshot/*",
                "arn:aws:ec2:*:*:subnet/*",
                "arn:aws:ec2:*:*:network-interface/*",
                "arn:aws:ec2:*:*:security-group/*",
                "arn:aws:ec2:*:*:key-pair/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateVolume",
                "ec2:RunInstances"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:volume/*",
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ec2:*:*:network-interface/*"
            ],
            "Condition": {
                "StringLike": {
                    "aws:RequestTag/Department": [
                        "SA",
                        "SRE",
                        "DEV"
                    ],
                    "aws:RequestTag/Name": "*"
                },
                "ForAllValues:StringEquals": {
                    "aws:TagKeys": [
                        "Department",
                        "Name"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateTags"
            ],
            "Resource": [
                "arn:aws:ec2:*:*:volume/*",
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ec2:*:*:network-interface/*"
            ],
            "Condition": {
                "StringEquals": {
                    "ec2:CreateAction": [
                        "RunInstances",
                        "CreateVolume"
                    ]
                }
            }
        }
    ]
}

참고. 위 정책은 ABAC을 구현하기 위한 예제 중 하나입니다. 실제 업무 환경에 필요한 Action, 자원, 조건 등이 필요한 경우 요구 사항에 따라 수정되어 사용되어야 합니다.

5. 마무리

이 글에서는 EC2에 대한 사용 권한을 PrincipalTag를 기반으로 하여 ABAC을 구현하는 경우 필요한 IAM 정책을 예제로 살펴보았습니다. 이를 통해, ABAC 구현을 위해서는 각 사용자에게 부여하고자 하는 권한의 대상이 되는 서비스와 Action 등에 따라서 IAM 정책이 세분되어야 한다는 것을 알 수 있었습니다. 따라서, ABAC을 구현하고자 하신다면 아래와 같은 사항을 파악 후 IAM 정책을 생성하시기를 권고드립니다.

  1. 태그 조건 키를 사용할 수 없는 Action 선별
  2. AWS 서비스 승인 참조 문서를 참고하여 사용할 수 있는 태그 관련 조건 키
  3. 태그를 부여할 수 있는 Action 선별

ABAC과 관련한 좀 더 자세한 사항이 궁금하시다면 태그를 기반으로 AWS 리소스에 액세스할 수 있는 권한 정의에 관한 튜토리얼을 참고하시기 바라며 ID 제공업체(IdP, Identity Provider)로 Okta 솔루션을 사용하는 환경에서의 ABAC 설정은 AWS SSO 및 Okta를 사용한 속성 기반 액세스 제어 전략 구축에 관한 블로그에서 확인하실 수 있습니다.

감사합니다.

Eunsu Shin

Eunsu Shin

신은수 Security Specialist Solutions Architect 는 보안 담당 SA로서 다양한 산업군의 고객들이 AWS 환경에서 수행해야하는 규정 준수 및 인증획득(개인정보보호법, 전자금융감독규정, ISMS-P 인증 등)을 위한 기술적인 도움을 제공해드리고 있습니다. 또한, 고객이 보다 안전하게 AWS 클라우드를 구성하고 운영할 수 있도록 다양한 모범 사례 공유, AWS 보안 서비스 교육 및 기술자문 등의 업무를 수행하고 있습니다.