AWS

[AWS][IAM] IAM ABAC(속성 기반 액세스 제어) 실습편

Always-Try 2022. 2. 1. 17:56
https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html

 

  • 시나리오
    • Example Corporation이라는 대기업의 수석 개발자이자 숙련된 IAM 관리자가 있다고 가정해 보겠습니다. 이 관리자는 IAM 사용자, 역할 및 정책을 생성하고 관리하는 데 익숙합니다. 개발 엔지니어와 품질 보증 팀 멤버가 필요한 리소스에 액세스할 수 있도록 해야 하며 기업의 성장에 따라 확장 가능한 전략도 준비해야 합니다.엔지니어링 및 품질 보증 팀 멤버는 Pegasus 또는 Unicorn 프로젝트에 참여하고 있습니다. 다음 세 글자로 된 프로젝트 및 팀 태그 값을 선택합니다.또한 사용자 지정 cost-center 결제 보고서를 활성화할 때 AWS 비용 할당 태그가 필요하도록 선택할 수 있습니다. 자세한 내용은 AWS Billing and Cost Management 사용 설명서의 비용 할당 태그 사용을 참조하세요.이 자습서에서는 각 리소스에 태그를 지정하고 프로젝트 역할에 태그를 지정하고 역할에 정책을 추가하여 앞에서 설명한 동작을 허용합니다. 결과 정책은 동일한 프로젝트 및 팀 태그로 태그가 지정된 리소스에 대한 역할 Create, Read, Update  Delete 액세스를 허용합니다. 또한 이 정책은 동일한 팀으로 태그가 지정된 리소스에 대해 프로젝트 간 Read 액세스를 허용합니다.
    •  
    • 주요 의사 결정 요약
      • 직원은 IAM 사용자 자격 증명으로 로그인한 다음 팀 및 프로젝트의 IAM 역할을 맡습니다. 회사에 자체 자격 증명 시스템이 있는 경우 직원이 IAM 사용자 없이 역할을 맡을 수 있도록 연동을 설정할 수 있습니다. 자세한 내용은 섹션을 참조하세요IAM 튜토리얼: ABAC에 SAML 세션 태그 사용
      • 동일한 정책이 모든 역할에 연결됩니다. 작업은 태그에 따라 허용되거나 거부됩니다.
      • 직원은 자신의 역할에 적용되는 리소스에 동일한 태그를 연결하는 경우에만 새 리소스를 생성할 수 있습니다. 이렇게 하면 직원이 리소스를 생성한 후 해당 리소스를 볼 수 있습니다. 관리자는 더 이상 새 리소스의 ARN으로 정책을 업데이트할 필요가 없습니다.
      • 직원은 프로젝트에 관계없이 자신의 팀이 소유한 리소스를 읽을 수 있습니다.
      • 직원은 자신의 팀과 프로젝트가 소유한 리소스를 업데이트하고 삭제할 수 있습니다.
      • IAM 관리자는 새 프로젝트에 대한 새 역할을 추가할 수 있습니다. 해당 역할에 대한 액세스를 허용하도록 새 IAM 사용자를 생성하고 태그를 지정할 수 있습니다. 관리자는 새 프로젝트 또는 팀 멤버를 지원하기 위해 정책을 편집할 필요가 없습니다.
      • Pegasus 프로젝트에 대해 access-project = peg
      • Unicorn 프로젝트에 대해 access-project = uni
      • 엔지니어링 팀에 대해 access-team = eng
      • 품질 보증 팀에 대해 access-team = qas
    • AWS 리소스 태그와 IAM 역할 보안 주체 태그를 사용하여 이를 지원하는 서비스에 대한 ABAC 전략을 구현하도록 선택합니다(AWS Secrets Manager로 시작). 태그를 기반으로 권한 부여를 지원하는 서비스에 대한 자세한 내용은 AWS IAM으로 작업하는 서비스 단원을 참조하십시오. 각 서비스의 작업 및 리소스와 함께 정책에서 사용할 수 있는 태그 지정 조건 키에 대한 자세한 내용은 AWS 서비스에 사용되는 작업, 리소스 및 조건 키를 참조하세요. 세션 태그를 AWS에 전달하도록 SAML 기반 또는 웹 자격 증명 공급자를 구성할 수 있습니다. 직원이 AWS에 연동되면 해당 속성이 AWS의 결과 보안 주체에 적용됩니다. 그런 다음 ABAC를 사용하여 이러한 속성에 따라 권한을 허용하거나 거부할 수 있습니다. SAML 페더레이션 자격 증명과 함께 세션 태그를 사용하는 것이 이 자습서와 어떻게 다른지 알아보려면 IAM 튜토리얼: ABAC에 SAML 세션 태그 사용 단원을 참조하십시오.
    • 보안 주체 및 리소스 태그가 일치하는 경우에만 Secrets Manager 리소스 액세스

 

 

 

  • 실습
    • 1단계:
      • access-assume-role이라는 고객 관리형 정책을 생성
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "TutorialAssumeRole",
                    "Effect": "Allow",
                    "Action": "sts:AssumeRole",
                    "Resource": "arn:aws:iam::354913817145:role/access-*",
                    "Condition": {
                        "StringEquals": {
                            "iam:ResourceTag/access-project": "${aws:PrincipalTag/access-project}",
                            "iam:ResourceTag/access-team": "${aws:PrincipalTag/access-team}",
                            "iam:ResourceTag/cost-center": "${aws:PrincipalTag/cost-center}"
                        }
                    }
                }
            ]
        }

        위 정책은 사용자가 access- 이름 접두사가 있는 계정의 모든 역할을 맡을 수 있도록 허용합니다. 역할에는 사용자와 동일한 프로젝트, 팀 및 비용 센터 태그가 지정되어 있어야 합니다.
      • IAM 사용자를 생성하고 access-assume-role 권한 정책을 연결하고 다음 태그를 추가
      • 결과:
    • 2단계:
      •  access-same-project-team이라는 정책을 생성합니다. 
        {
         "Version": "2012-10-17",
         "Statement": [
             {
                 "Sid": "AllActionsSecretsManagerSameProjectSameTeam",
                 "Effect": "Allow",
                 "Action": "secretsmanager:*",
                 "Resource": "*",
                 "Condition": {
                     "StringEquals": {
                         "aws:ResourceTag/access-project": "${aws:PrincipalTag/access-project}",
                         "aws:ResourceTag/access-team": "${aws:PrincipalTag/access-team}",
                         "aws:ResourceTag/cost-center": "${aws:PrincipalTag/cost-center}"
                     },
                     "ForAllValues:StringEquals": {
                         "aws:TagKeys": [
                             "access-project",
                             "access-team",
                             "cost-center",
                             "Name",
                             "OwnedBy"
                         ]
                     },
                     "StringEqualsIfExists": {
                         "aws:RequestTag/access-project": "${aws:PrincipalTag/access-project}",
                         "aws:RequestTag/access-team": "${aws:PrincipalTag/access-team}",
                         "aws:RequestTag/cost-center": "${aws:PrincipalTag/cost-center}"
                     }
                 }
             },
             {
                 "Sid": "AllResourcesSecretsManagerNoTags",
                 "Effect": "Allow",
                 "Action": [
                     "secretsmanager:GetRandomPassword",
                     "secretsmanager:ListSecrets"
                 ],
                 "Resource": "*"
             },
             {
                 "Sid": "ReadSecretsManagerSameTeam",
                 "Effect": "Allow",
                 "Action": [
                     "secretsmanager:Describe*",
                     "secretsmanager:Get*",
                     "secretsmanager:List*"
                 ],
                 "Resource": "*",
                 "Condition": {
                     "StringEquals": {
                         "aws:ResourceTag/access-team": "${aws:PrincipalTag/access-team}"
                     }
                 }
             },
             {
                 "Sid": "DenyUntagSecretsManagerReservedTags",
                 "Effect": "Deny",
                 "Action": "secretsmanager:UntagResource",
                 "Resource": "*",
                 "Condition": {
                     "ForAnyValue:StringLike": {
                         "aws:TagKeys": "access-*"
                     }
                 }
             },
             {
                 "Sid": "DenyPermissionsManagement",
                 "Effect": "Deny",
                 "Action": "secretsmanager:*Policy",
                 "Resource": "*"
             }
         ]
        }

        AllActionsSecretsManagerSameProjectSameTeam 문은 리소스 태그가 보안 주체 태그와 일치하는 경우에만 모든 관련 리소스에 대해 이 서비스의 모든 작업을 허용합니다. 정책에 "Action": "secretsmanager:*"를 추가하면 Secrets Manager가 커질수록 정책도 커집니다. Secrets Manager에서 새 API 작업을 추가하는 경우 문에 해당 작업을 추가할 필요가 없습니다. 이 문은 세 가지 조건 블록을 사용하여 ABAC를 구현합니다. 세 블록 모두 true를 반환하는 경우에만 요청이 허용됩니다.
        지정된 태그 키가 리소스에 있고 해당 값이 보안 주체의 태그와 일치하는 경우 이 문의 첫 번째 조건 블록은 true를 반환합니다. 이 블록은 일치하지 않는 태그 또는 리소스 태그 지정을 지원하지 않는 작업에 대해 false를 반환합니다. 이 블록에서 허용되지 않는 작업에 대한 자세한 내용은 AWS Secrets Manager에 대한 작업, 리소스 및 조건 키를 참조하십시오 . 이 페이지에서는 비밀 리소스 유형에 대해 수행된 작업이 secretsmanager:ResourceTag/tag-key 조건 키를 지원한다는 것을 보여 줍니다. 일부 Secrets Manager 작업에서는 GetRandomPassword  ListSecrets를 포함하여 해당 해당 리소스 유형을 지원하지 않습니다. 이러한 작업을 허용하려면 추가 문을 생성해야 합니다.

        두 번째 조건 블록은 요청에 전달된 모든 태그 키가 지정된 목록에 포함된 경우 true를 반환합니다. 이 작업은 ForAllValues 조건 연산자와 함께 StringEquals를 사용하여 수행됩니다. 키 또는 키 세트의 일부가 전달되지 않으면 조건이 true를 반환합니다. 이 경우 요청에서 태그 전달을 허용하지 않는 Get* 작업을 사용할 수 있습니다. 요청자가 목록에 없는 태그 키를 포함하는 경우 조건은 false를 반환합니다. 요청에 전달되는 모든 태그 키가 이 목록의 멤버와 일치해야 합니다. 자세한 내용은 섹션을 참조하세요다수의 키와 값 사용

        세 번째 조건 블록은 요청이 태그 전달을 지원하고, 세 개의 태그가 모두 존재하고, 보안 주체 태그 값과 일치하는 경우 true를 반환합니다. 요청이 태그 전달을 지원하지 않는 경우에도 이 블록은 true를 반환합니다. 그 이유는 조건 연산자의 ...IfExists 때문입니다. 지원하는 작업 중에 전달된 태그가 없거나 태그 키 및 값이 일치하지 않으면 블록이 false를 반환합니다.

        AllResourcesSecretsManagerNoTags 문은 첫 번째 문에서 허용되지 않는 GetRandomPassword  ListSecrets 작업을 허용합니다.

        ReadSecretsManagerSameTeam 문은 보안 주체가 리소스와 동일한 액세스 팀 태그로 태그가 지정된 경우 읽기 전용 작업을 허용합니다. 이는 프로젝트 또는 비용 센터 태그에 관계없이 허용됩니다.

        DenyUntagSecretsManagerReservedTags 문은 Secrets Manager에서 “access-”로 시작하는 키가 있는 태그를 제거하라는 요청을 거부합니다. 이러한 태그는 리소스에 대한 액세스를 제어하는 데 사용되므로 태그를 제거하면 권한이 제거될 수 있습니다.

        DenyPermissionsManagement 문은 Secrets Manager 리소스 기반 정책을 생성, 편집 또는 삭제할 수 있는 권한을 거부합니다. 이러한 정책을 사용하여 비밀의 권한을 변경할 수 있습니다.
    • 3단계:
      • 다음 IAM 역할을 생성하고 이전 단계에서 생성한 access-same-project-team 정책을 연결합니다. 
      • 결과
    • 4단계:
      • 역할에 연결된 권한 정책을 통해 직원이 비밀을 생성할 수 있습니다. 이 작업은 비밀에 프로젝트, 팀 및 비용 센터 태그가 지정된 경우에만 허용됩니다. Secrets Manager에서 사용자로 로그인하고, 올바른 역할을 맡고, 활동을 테스트하여 권한이 예상대로 작동하는지 확인합니다.

        새로운 AWS Console 창을 열고, access-Arnav-peg-eng 계정으로 로그인합니다. Secret Manager 콘솔로 이동하여 access-uni-engineering 역할로 역할 전환을 시도하면 실패합니다. 사용자와 역할의 태그가 일치하지 않기 때문입니다.
        이제 사용자 계정의 태그와 일치하는 역할인 access-peg-engineering로 역할 전환을 시도해봅니다. 그럼 아래와 같이 역할 전환이 성공적으로 된 것을 볼 수 있습니다.


      • 태그에 아무것도 입력하지 않거나 임의의 값을 입력해서 새로운 Secret을 생성해보면 아래와 같이 권한이 없다고 하면서 실패하는 것을 볼 수 있습니다.Secret을 생성하려면 아까 IAM 정책에서 정의한 조건에 부합하는 태그가 있어야 하는데, 아래 케이스표를 참고합니다.
        위 케이스의 5번째, 6번째의 차이는 아래 IAM 정책과 연관이 있을 것으로 보이는데, StringEquals 와 ForAllValues:StringEquals 에 대해서 추가적으로 확인해볼 필요가 있습니다.
      • 다른 계정 및 역할을 이용해 위와 같은 테스트를 계속 진행해봅니다.

    • 5단계:
      • RBAC(역할 기반 액세스 제어)를 통해 ABAC(속성 기반 액세스 제어)를 사용하는 중요한 이유는 확장성입니다. 회사에서 새 프로젝트, 팀 또는 인력을 AWS에 추가할 때 ABAC 기반 정책을 업데이트할 필요가 없습니다. 예를 들어, Example Company가 코드명이 Centaur인 새로운 프로젝트에 자금을 조달하고 있다고 가정합니다. Saanvi Sarkar라는 엔지니어는 Unicorn 프로젝트에서 계속 작업하면서 Centaur의 수석 엔지니어도 겸할 예정입니다. 또한 Nikhil Jayashankar를 포함하여 Centaur 프로젝트에서만 작업하기 위해 몇 명의 엔지니어가 새로 고용되었습니다.
        새 프로젝트를 AWS에 추가하려면 어떻게 해야될까요?

 

 

실무적으로는 더욱 다양한 요청 사항들이 나올 수 있습니다. 다른 상황들은 어떻게 대처할 수 있을지 고민해보는 것이 필요합니다. (ex. 5단계에서 Saanvi가 IAM Group에 속해있었다면 어쩔티비?, 역할 전환을 꼭 사용해야 하는지?)

 

추가적으로 아래 IAM JSON 정책에 대한 고민이 필요

 

forallvalues, foranyvalues

https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_policies_multi-value-conditions.html


IfExists
https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_IfExists