

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon Verified Permissions를 사용하여 PDP 구현
<a name="avp"></a>

Amazon Verified Permissions는 정책 결정 시점(PDP)을 구현하는 데 사용할 수 있는 확장 가능하고 세분화된 권한 관리 및 권한 부여 서비스입니다. 정책 엔진은 애플리케이션이 사용자 작업을 실시간으로 확인하고 과도하게 권한이 있거나 유효하지 않은 권한을 강조 표시하는 데 도움이 될 수 있습니다. 이를 통해 권한 부여를 외부화하고 정책 관리 및 관리를 중앙 집중화하여 개발자가 더 안전한 애플리케이션을 더 빠르게 구축할 수 있습니다. Verified Permissions는 권한 부여 로직을 애플리케이션 로직과 분리하여 정책 분리를 지원합니다.

Verified Permissions를 사용하여 PDP를 구현하고 애플리케이션 내에서 최소 권한과 지속적인 확인을 구현하면 개발자는 [제로 트러스트](https://aws.amazon.com/security/zero-trust/) 원칙에 맞게 애플리케이션 액세스를 조정할 수 있습니다. 또한 보안 및 감사 팀은 애플리케이션 내의 어떤 리소스에 액세스할 수 있는 사용자를 더 잘 분석하고 감사할 수 있습니다. Verified Permissions는 특별히 구축된 보안 우선 오픈 소스 정책 언어인 [Cedar](https://www.cedarpolicy.com/en)를 사용하여 보다 세분화된 컨텍스트 인식 액세스 제어를 위해 역할 기반 액세스 제어(RBAC) 및 속성 기반 액세스 제어(ABAC)를 기반으로 정책 기반 액세스 제어를 정의합니다.

Verified Permissions는 Amazon Cognito, Google 및 Facebook과 같은 여러 자격 증명 공급자를 사용하여 다중 테넌트 권한 부여를 활성화하는 기능 등 SaaS 애플리케이션에 유용한 몇 가지 기능을 제공합니다. SaaS 애플리케이션에 특히 유용한 또 다른 Verified Permissions 기능은 테넌트별로 사용자 지정 역할을 지원하는 것입니다. 고객 관계 관리(CRM) 시스템을 설계하는 경우 한 테넌트는 특정 기준 세트를 기반으로 영업 기회별 액세스의 세분화를 정의할 수 있습니다. 다른 테넌트에 다른 정의가 있을 수 있습니다. Verified Permissions의 기본 권한 시스템은 이러한 변형을 지원할 수 있으므로 SaaS 사용 사례에 매우 적합합니다. Verified Permissions는 모든 테넌트에 적용되는 정책을 작성하는 기능도 지원하므로 SaaS 공급자로서 무단 액세스를 방지하기 위해 가드레일 정책을 쉽게 적용할 수 있습니다.

![\[Amazon Verified Permissions를 사용하여 PDP 구현\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp.png)


**Verified Permissions를 사용하는 이유는 무엇인가요?**

애플리케이션에 대한 보다 동적인 정책 기반 액세스 관리 솔루션을 위해 [Amazon Cognito](https://aws.amazon.com/cognito/)와 같은 자격 증명 공급자와 함께 Verified Permissions를 사용합니다. 사용자가 데이터의 보안, 기밀성 및 개인 정보 보호를 유지하면서 정보를 공유하고 협업하는 데 도움이 되는 애플리케이션을 구축할 수 있습니다. Verified Permissions는 자격 증명 및 리소스의 역할과 속성을 기반으로 액세스를 적용할 수 있는 세분화된 권한 부여 시스템을 제공하여 운영 비용을 줄이는 데 도움이 됩니다. 정책 모델을 정의하고, 중앙 위치에 정책을 생성 및 저장하고, 밀리초 단위로 액세스 요청을 평가할 수 있습니다.

Verified Permissions에서는 Cedar라는 간단하고 사람이 읽을 수 있는 선언적 언어를 사용하여 권한을 표현할 수 있습니다. Cedar로 작성된 정책은 각 팀의 애플리케이션에서 사용하는 프로그래밍 언어에 관계없이 팀 간에 공유할 수 있습니다.

**Verified Permissions를 사용할 때 고려해야 할 사항**

Verified Permissions에서 정책을 생성하고 프로비저닝의 일부로 자동화할 수 있습니다. 애플리케이션 로직의 일부로 런타임에 정책을 생성할 수도 있습니다. 테넌트 온보딩 및 프로비저닝의 일부로 정책을 생성할 때 지속적 통합 및 지속적 배포(CI/CD) 파이프라인을 사용하여 정책 버전을 관리, 수정 및 추적하는 것이 가장 좋습니다. 또는 애플리케이션이 정책 버전을 관리, 수정 및 추적할 수 있지만 애플리케이션 로직은 기본적으로이 기능을 수행하지 않습니다. 애플리케이션에서 이러한 기능을 지원하려면이 기능을 구현하도록 애플리케이션을 명시적으로 설계해야 합니다.

권한 부여 결정에 도달하기 위해 다른 소스의 외부 데이터를 제공해야 하는 경우이 데이터를 검색하여 권한 부여 요청의 일부로 Verified Permissions에 제공해야 합니다. 이 서비스에서는 추가 컨텍스트, 엔터티 및 속성이 기본적으로 검색되지 않습니다.

# Cedar 개요
<a name="cedar"></a>

Cedar는 개발자가 애플리케이션 권한을 정책으로 표현하는 데 도움이 되는 유연하고 확장 가능하며 확장 가능한 정책 기반 액세스 제어 언어입니다. 관리자와 개발자는 사용자가 애플리케이션 리소스를 사용하도록 허용하거나 금지하는 정책을 정의할 수 있습니다. 여러 정책을 단일 리소스에 연결할 수 있습니다. 애플리케이션 사용자가 리소스에 대한 작업을 수행하려고 하면 애플리케이션은 Cedar 정책 엔진에 권한 부여를 요청합니다. Cedar는 해당 정책을 평가하고 `ALLOW` 또는 `DENY` 결정을 반환합니다. Cedar는 모든 유형의 보안 주체 및 리소스에 대한 권한 부여 규칙을 지원하고, 역할 기반 액세스 제어(RBAC) 및 속성 기반 액세스 제어(ABAC)를 허용하며, 자동화된 추론 도구를 통한 분석을 지원합니다.

Cedar를 사용하면 비즈니스 로직을 권한 부여 로직과 분리할 수 있습니다. 애플리케이션 코드에서 요청할 때 Cedar의 권한 부여 엔진을 호출하여 요청이 승인되었는지 확인합니다. 권한이 있는 경우(결정이 임`ALLOW`) 애플리케이션은 요청된 작업을 수행할 수 있습니다. 권한이 없는 경우(결정이 임`DENY`) 애플리케이션에서 오류 메시지를 반환할 수 있습니다. Cedar의 주요 기능은 다음과 같습니다.
+ **표현식** - Cedar는 권한 부여 사용 사례를 지원하기 위해 특별히 구축되었으며 사람의 가독성을 염두에 두고 개발되었습니다.
+ **성능** - Cedar는 빠른 검색을 위한 인덱싱 정책을 지원하고 제한된 지연 시간으로 빠르고 확장 가능한 실시간 평가를 제공합니다.
+ **분석** - Cedar는 정책을 최적화하고 보안 모델을 확인할 수 있는 분석 도구를 지원합니다.

자세한 내용은 [Cedar 웹 사이트를](https://www.cedarpolicy.com/) 참조하세요.

# 예제 1: Verified Permissions 및 Cedar가 포함된 기본 ABAC
<a name="avp-basic-abac-examples"></a>

이 예제 시나리오에서는 Amazon Verified Permissions를 사용하여 가상 급여 마이크로서비스의 정보에 액세스할 수 있는 사용자를 결정합니다. 이 섹션에는 Cedar 코드 조각이 포함되어 있어 Cedar를 사용하여 액세스 제어 결정을 렌더링하는 방법을 보여줍니다. 이 예제는 Cedar 및 Verified Permissions에서 제공하는 기능에 대한 전체 탐색을 제공하기 위한 것이 아닙니다. Cedar에 대한 자세한 개요는 [Cedar 설명서를](https://docs.cedarpolicy.com/) 참조하세요.

다음 다이어그램에서는 `viewSalary` `GET` 메서드와 관련된 두 가지 일반 비즈니스 규칙을 적용하려고 합니다. *직원은 자신의 급여를 볼 수* 있고 *직원은 자신에게 보고하는 모든 사람의 급여를 볼 수 있습니다.* Verified Permissions 정책을 사용하여 이러한 비즈니스 규칙을 적용할 수 있습니다.

![\[PDP를 구현하기 위한 Amazon Verified Permissions 및 Cedar를 사용한 기본 ABAC 구현의 예\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-1.png)


*직원은 자신의 급여를 볼 수 있습니다.*

Cedar에서 기본 구문은 보안 주체, 작업 또는 리소스를 나타내는 *개체*입니다. 권한 부여 요청을 수행하고 Verified Permissions 정책으로 평가를 시작하려면 *보안 주체*, *작업*, *리소스* 및 *엔터티 목록을 제공해야 합니다.*
+ 보안 주체(`principal`)는 로그인한 사용자 또는 역할입니다.
+ 작업(`action`)은 요청에 의해 평가되는 작업입니다.
+ 리소스(`resource`)는 작업이 액세스하는 구성 요소입니다.
+ 엔터티 목록(`entityList`)에는 요청을 평가하는 데 필요한 모든 엔터티가 포함되어 있습니다.

*직원이 자신의 급여를 볼 수* 있는 비즈니스 규칙을 충족하기 위해 다음과 같은 Verified Permissions 정책을 제공할 수 있습니다.

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner
};
```

이 정책은이 `Action` 이고 요청의 리소스에 보안 주체`viewSalary`와 동일한 속성 소유자가 있는 `ALLOW` 경우 로 평가됩니다. 예를 들어 Bob이 급여 보고서를 요청한 로그인한 사용자이고 급여 보고서의 소유자이기도 한 경우 정책은 로 평가됩니다`ALLOW`.

다음 권한 부여 요청은 샘플 정책에서 평가할 수 있도록 Verified Permissions에 제출됩니다. 이 예제에서 Bob은 `viewSalary` 요청을 하는 로그인한 사용자입니다. 따라서 Bob은 엔터티 유형의 보안 주체입니다`Employee`. Bob이 수행하려고 하는 작업은 `viewSalary,` 이고 `viewSalary` 표시할 리소스는 유형 `Salary-Bob`입니다`Salary`. Bob이 `Salary-Bob` 리소스를 볼 수 있는지 평가하려면 유형을 `Bob` (보안 주체)의 값과 `Employee` 유형이 있는 리소스의 소유자 속성에 연결하는 `Salary` 엔터티 구조를 제공해야 합니다. 에서이 구조를 제공합니다. `entityList`여기서와 연결된 속성에는 유형 `Employee` 및 값이 `entityIdentifier` 포함된를 지정하는 소유자가 `Salary` 포함됩니다`Bob`. Verified Permissions는 권한 부여 요청에 `principal` 제공된를 `Salary` 리소스와 연결된 `owner` 속성과 비교하여 결정을 내립니다.

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        }
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {}
      }
    ]
  }
}
```

Verified Permissions에 대한 권한 부여 요청은 다음을 출력으로 반환합니다. 여기서 속성`decision`은 `ALLOW` 또는 입니다`DENY`.

```
{
    "determiningPolicies": 
        [ 
            {
                "determiningPolicyId": "PAYROLLAPP_POLICYSTOREID" 
            }
        ],
    "decision": "ALLOW",
    "errors": [] 
}
```

이 경우 Bob이 자신의 급여를 보려고 했기 때문에 Verified Permissions로 전송된 권한 부여 요청은 로 평가됩니다`ALLOW`. 그러나 Verified Permissions를 사용하여 두 가지 비즈니스 규칙을 적용하는 것이 목표였습니다. 다음과 같은 비즈니스 규칙도 참이어야 합니다.

*직원은 자신에게 보고하는 모든 사람의 급여를 볼 수 있습니다.*

이 비즈니스 규칙을 충족하기 위해 다른 정책을 제공할 수 있습니다. 다음 정책은 작업이 이고 요청의 리소스에 보안 주체`viewSalary`와 동일한 속성이 `owner.manager` 있는 `ALLOW` 경우 로 평가됩니다. 예를 들어 Alice가 급여 보고서를 요청한 로그인한 사용자이고 Alice가 보고서 소유자의 관리자인 경우 정책은 로 평가됩니다`ALLOW`.

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager
};
```

다음 권한 부여 요청은 샘플 정책에서 평가할 수 있도록 Verified Permissions에 제출됩니다. 이 예제에서 Alice는 `viewSalary` 요청을 하는 로그인한 사용자입니다. 따라서 Alice는 보안 주체이고 개체는 유형입니다`Employee`. Alice가 수행하려고 하는 작업은 이고 `viewSalary` 표시할 `viewSalary`리소스는 `Salary` 유형의 값입니다`Salary-Bob`. Alice가 `Salary-Bob` 리소스를 볼 수 있는지 평가하려면 유형을의 `Employee` 값과 연결하는 엔터티 구조를 `manager` 속성`Alice`에 제공해야 합니다. 그런 다음이 구조를의 값을 `Salary` 가진 유형의 `owner` 속성과 연결해야 합니다`Salary-Bob`. 에서이 구조를 제공합니다. `entityList`여기서와 연결된 속성에는 유형 `Employee` 및 값이 `entityIdentifier` 포함된를 지정하는 소유자가 `Salary` 포함됩니다`Bob`. Verified Permissions는 먼저 유형 `Employee` 및 값으로 평가되는 `owner` 속성을 확인합니다`Bob`. 그런 다음 Verified Permissions는와 연결된 `manager` 속성을 평가하고 제공된 보안 주체`Employee`와 비교하여 권한 부여 결정을 내립니다. 이 경우 `principal `및 `resource.owner.manager` 속성이 동일`ALLOW`하기 때문에 결정이 내려집니다.

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Alice"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "None"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Alice"
            }
          }
        },
       "parents": []
      }
    ]
  }
}
```

지금까지이 예제에서는 `viewSalary` 메서드와 연결된 두 가지 비즈니스 규칙을 제공했습니다. *직원은 자신의 급여를 볼 수* 있으며*, 직원은 자신에게 보고하는 모든 사람의 급여를 Verified Permissions에 독립적으로 각 비즈니스 규칙의 조건을 충족하는 정책으로 볼 수 있습니다*. 단일 Verified Permissions 정책을 사용하여 두 비즈니스 규칙의 조건을 모두 충족할 수도 있습니다.

*직원은 자신의 급여와 자신에게 보고하는 모든 사람의 급여를 볼 수 있습니다.*

이전 권한 부여 요청을 사용할 때 다음 정책은 `ALLOW` 작업이 이고 요청의 리소스에 `viewSalary`와 `owner.manager` 동일한 속성 `principal`또는와 동일한 속성이 `owner` 있는지 평가합니다`principal`.

```
permit (
    principal,
    action == PayrollApp::Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager ||
    principal == resource.owner
};
```

예를 들어 Alice가 급여 보고서를 요청하는 로그인한 사용자이고 Alice가 보고서의 소유자 또는 소유자인 경우 정책은 로 평가됩니다`ALLOW`.

Cedar 정책에서 논리 연산자를 사용하는 방법에 대한 자세한 내용은 [Cedar 설명서를](https://docs.cedarpolicy.com/policies/syntax-operators.html) 참조하세요.

# 예제 2: Verified Permissions 및 Cedar가 포함된 기본 RBAC
<a name="avp-basic-rbac-examples"></a>

이 예제에서는 Verified Permissions 및 Cedar를 사용하여 기본 RBAC를 보여줍니다. 앞서 언급했듯이 Cedar의 기본 구성은 개체입니다. 개발자는 자체 엔터티를 정의하고 선택적으로 엔터티 간에 관계를 생성할 수 있습니다. 다음 예제에는 `Users`, `Roles`,의 세 가지 유형의 엔터티가 포함됩니다`Problems`. `Students` 및는 유형의 엔터티로 간주될 `Teachers` 수 `Role,` 있으며 각는 0 또는 임의의와 연결될 `User` 수 있습니다`Roles`.

![\[PDP를 구현하기 위한 Amazon Verified Permissions 및 Cedar를 사용한 기본 RBAC 구현의 예\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-2.png)


Cedar에서 이러한 관계는를 상위`Role``Student``User``Bob`로에 연결하여 표현됩니다. 이 연결은 한 그룹의 모든 학생 사용자를 논리적으로 그룹화합니다. Cedar의 그룹화에 대한 자세한 내용은 [Cedar 설명서를](https://docs.cedarpolicy.com/overview/terminology.html#term-group) 참조하세요.

다음 정책은 유형의 논리적 그룹에 연결된 모든 보안 주체`ALLOW`에 `submitProblem,` 대한 작업 결정에 따라 평가`Students`됩니다`Role`.

```
permit (
    principal in ElearningApp::Role::"Students",
    action == ElearningApp::Action::"submitProblem",
    resource
);
```

다음 정책은 유형의 논리적 그룹에 연결된 모든 보안 주체에 `ALLOW` 대해 작업 `submitProblem` 또는 `Teachers`에 `answerProblem`대한 결정으로 평가됩니다`Role`.

```
permit (
    principal in ElearningApp::Role::"Teachers",
    action in [
        ElearningApp::Action::"submitProblem",
        ElearningApp::Action::"answerProblem"
    ],
    resource
);
```

이러한 정책을 사용하여 요청을 평가하려면 평가 엔진이 권한 부여 요청 내에서 참조되는 보안 주체가 적절한 그룹의 구성원인지 여부를 알아야 합니다. 따라서 애플리케이션은 권한 부여 요청의 일부로 평가 엔진에 관련 그룹 멤버십 정보를 전달해야 합니다. 이는 `entities` 권한 부여 호출과 관련된 보안 주체 및 리소스에 대한 속성 및 그룹 멤버십 데이터를 Cedar 평가 엔진에 제공할 수 있는 속성을 통해 수행됩니다. 다음 코드에서 그룹 멤버십은 라는 상위를 갖는 `User::"Bob"` 것으로 정의하여 표시됩니다`Role::"Students"`.

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Bob"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Students"
                } 
            ]
        },
        {
          "identifier": {
            "entityType": "ElearningApp::Problem",
            "entityId": "SomeProblem"
          },
          "attributes": {},
          "parents": []
        }
      ]
  }
}
```

이 예제에서 Bob은 `answerProblem` 요청을 하는 로그인한 사용자입니다. 따라서 Bob은 보안 주체이고 개체는 유형입니다`User`. Bob이 수행하려고 하는 작업은 입니다`answerProblem`. Bob이 `answerProblem` 작업을 수행할 수 있는지 평가하려면 상위 엔터티를 로 나열하여 엔터티`User`를 값과 연결하고 그룹 멤버십을 `Bob` 할당하는 엔터티 구조를 제공해야 합니다`Role::"Students"`. 사용자 그룹의 엔터티`Role::"Students"`는 작업 만 수행할 수 있으므로 `submitProblem`이 권한 부여 요청은 로 평가됩니다`DENY`.

반면, `User` 값이 `Alice` 이고 그룹의 일부인 유형이 `answerProblem` 작업을 수행`Role::"Teachers"` 하려고 하면 권한 부여 요청은 로 평가됩니다. 정책에 따라 그룹의 보안 주체가 `answerProblem` 모든 리소스에서 작업을 수행할 `Role::"Teachers"` 수 있다고 명시되어 있기 `ALLOW`때문입니다. 다음 코드는가 로 평가하는 이러한 유형의  권한 부여 요청을 보여줍니다`ALLOW`.

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Alice"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Teachers"
                } 
            ]
        },
        {
            "identifier": {
                "entityType": "ElearningApp::Problem",
                "entityId": "SomeProblem"
            },
            "attributes": {},
            "parents": []
        }
      ]
  }
}
```

# 예제 3: RBAC를 사용한 다중 테넌트 액세스 제어
<a name="avp-mt-abac-examples"></a>

이전 RBAC 예제를 자세히 설명하기 위해 SaaS 공급자의 일반적인 요구 사항인 SaaS 멀티테넌시를 포함하도록 요구 사항을 확장할 수 있습니다. 다중 테넌트 솔루션에서 리소스 액세스는 항상 지정된 테넌트를 대신하여 제공됩니다. 즉, 테넌트 A의 사용자는 데이터가 시스템에서 논리적으로 또는 물리적으로 공동 배치되더라도 테넌트 B의 데이터를 볼 수 없습니다. 다음 예제에서는 여러 [Verified Permissions 정책 스토어](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policy-stores.html)를 사용하여 테넌트 격리를 구현하는 방법과 사용자 역할을 사용하여 테넌트 내에서 권한을 정의하는 방법을 보여줍니다.

테넌트별 정책 스토어 설계 패턴을 사용하는 것은 Verified Permissions로 액세스 제어를 구현하면서 테넌트 격리를 유지하는 모범 사례입니다. 이 시나리오에서는 테넌트 A 및 테넌트 B 사용자 요청이 `DATAMICROSERVICE_POLICYSTORE_B`각각 별도의 정책 저장소인 `DATAMICROSERVICE_POLICYSTORE_A` 및에 대해 확인됩니다. 다중 테넌트 SaaS 애플리케이션의 Verified Permissions 설계 고려 사항에 대한 자세한 내용은 [Verified Permissions 다중 테넌트 설계 고려](avp-design-considerations.md) 사항 섹션을 참조하세요.

![\[RBAC, Amazon Verified Permissions 및 Cedar를 사용한 다중 테넌트 액세스 제어의 예\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-3.png)


다음 정책은 `DATAMICROSERVICE_POLICYSTORE_A` 정책 스토어에 있습니다. 보안 주체가 `allAccessRole` 유형의 그룹에 속할 것인지 확인합니다`Role`. 이 경우 보안 주체는 테넌트 A와 연결된 모든 리소스에서 `viewData` 및 `updateData` 작업을 수행할 수 있습니다.

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
);
```

다음 정책은 `DATAMICROSERVICE_POLICYSTORE_B` 정책 스토어에 있습니다. 첫 번째 정책은 보안 주체가 유형의 `updateDataRole` 그룹에 속해 있는지 확인합니다`Role`. 이 경우 보안 주체에게 테넌트 B와 연결된 리소스에 대해 `updateData` 작업을 수행할 수 있는 권한을 부여합니다.

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
);
```

이 두 번째 정책은 유형 `viewDataRole` 그룹의 일부인 보안 주체가 테넌트 B와 연결된 리소스에 대해 `viewData` 작업을 수행할 `Role` 수 있도록 요구합니다.

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
);
```

테넌트 A의 권한 부여 요청은 `DATAMICROSERVICE_POLICYSTORE_A` 정책 저장소로 전송되고 해당 저장소에 속한 정책에 의해 확인되어야 합니다. 이 경우이 예제의 일부로 앞서 설명한 첫 번째 정책에 의해 확인됩니다. 이 권한 부여 요청에서 값이 `User`인 유형의 보안 주체`Alice`는 `viewData` 작업 수행을 요청합니다. 보안 주체는 `allAccessRole` 유형의 그룹에 속합니다`Role`. Alice가 `SampleData` 리소스에 대한 `viewData` 작업을 수행하려고 합니다. Alice에게는 `allAccessRole` 역할이 있으므로이 평가는 `ALLOW` 결정을 내리게 됩니다.

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

대신에서 테넌트 B의 요청을 보는 경우 다음과 같은 권한 부여 요청이 `User Bob`표시됩니다. 요청은 테넌트 B에서 시작되므로 `DATAMICROSERVICE_POLICYSTORE_B` 정책 스토어로 전송됩니다.이 요청에서 보안 주체는 리소스에 `updateData` 대한 작업을 수행하려고 `Bob` 합니다`SampleData`. 그러나 `Bob`는 `updateData` 해당 리소스의 작업에 액세스할 수 있는 그룹의 일부가 아닙니다. 따라서 요청으로 인해 `DENY` 결정이 내려집니다.

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_B",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Bob"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Bob"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "viewDataRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

이 세 번째 예제에서는 리소스에서 `viewData` 작업을 수행하려고 `User Alice `시도합니다`SampleData`. 이 요청은 보안 주체가 테넌트 A에 `Alice` 속하기 때문에 `DATAMICROSERVICE_POLICYSTORE_A` 정책 스토어로 전달됩니다. `Alice`는 `allAccessRole` 유형의 그룹에 속`Role`하므로 리소스에 대한 `viewData` 작업을 수행할 수 있습니다. 따라서 요청이 `ALLOW` 결정으로 이어집니다.

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

# 예제 4: RBAC 및 ABAC를 사용한 다중 테넌트 액세스 제어
<a name="avp-mt-abac-rbac-examples"></a>

이전 섹션의 RBAC 예제를 개선하려면 사용자에게 속성을 추가하여 다중 테넌트 액세스 제어를 위한 RBAC-ABAC 하이브리드 접근 방식을 생성할 수 있습니다. 이 예제는 이전 예제와 동일한 역할을 포함하지만 사용자 속성`account_lockout_flag`과 컨텍스트 파라미터를 추가합니다`uses_mfa`. 또한이 예제에서는 RBAC와 ABAC를 모두 사용하여 다중 테넌트 액세스 제어를 구현하는 다른 접근 방식을 취하며 각 테넌트에 대해 다른 정책 저장소 대신 하나의 공유 정책 저장소를 사용합니다.

![\[RBAC, ABAC, Amazon Verified Permissions 및 Cedar를 사용한 다중 테넌트 액세스 제어의 예\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-4.png)


이 예제는 이전 예제와 마찬가지로 테넌트 A 및 테넌트 B에 대한 권한 부여 결정을 제공해야 하는 다중 테넌트 SaaS 솔루션을 나타냅니다.

사용자 잠금 기능을 구현하기 위해이 예제에서는 권한 부여 요청의 `User`엔`account_lockout_flag`터티 보안 주체에 속성을 추가합니다. 이 플래그는 시스템에 대한 사용자 액세스를 잠그고 잠긴 사용자에게 `DENY` 모든 권한을 부여합니다. `account_lockout_flag` 속성은 `User` 개체와 연결되며 플래그가 여러 세션에서 능동적으로 취소`User`될 때까지에 적용됩니다. 이 예제에서는 `when` 조건을 사용하여를 평가합니다`account_lockout_flag`.

이 예제에서는 요청 및 세션에 대한 세부 정보도 추가합니다. 컨텍스트 정보는 세션이 다중 인증을 사용하여 인증되었음을 지정합니다. 이 검증을 구현하기 위해이 예제에서는 `when` 조건을 사용하여 컨텍스트 필드의 일부로 `uses_mfa` 플래그를 평가합니다. 컨텍스트 추가 모범 사례에 대한 자세한 내용은 [Cedar 설명서를](https://docs.cedarpolicy.com/auth/entities-syntax.html) 참조하세요.

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

이 정책은 리소스가 요청 주체의 `Tenant` 속성과 동일한 그룹에 있지 않는 한 리소스에 대한 액세스를 방지합니다. 테넌트 격리를 유지하는 이러한 접근 방식을 *One Shared Multi-Tenant Policy Store* 접근 방식이라고 합니다. 다중 테넌트 SaaS 애플리케이션의 Verified Permissions 설계 고려 사항에 대한 자세한 내용은 [Verified Permissions 다중 테넌트 설계 고려](avp-design-considerations.md) 사항 섹션을 참조하세요.

또한이 정책은 보안 주체가의 멤버인지 확인하고 작업을 `viewData` 및 로 `allAccessRole` 제한합니다`updateData`. 또한이 정책은가 `false` `account_lockout_flag`이고의 컨텍스트 값이 로 `uses_mfa` 평가되는지 확인합니다`true`.

마찬가지로 다음 정책은 보안 주체와 리소스가 동일한 테넌트와 연결되도록 하여 테넌트 간 액세스를 방지합니다. 또한이 정책은 보안 주체가의 멤버가 되도록 `viewDataRole`하고 작업을 로 제한합니다`viewData`. 또한가 `account_lockout_flag` 인지`false`,의 컨텍스트 값이 로 `uses_mfa` 평가되는지 확인합니다`true`.

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

세 번째 정책은 이전 정책과 유사합니다. 이 정책은 리소스가 로 표시되는 개체에 해당하는 그룹의 구성원이어야 합니다`principal.Tenant`. 이렇게 하면 보안 주체와 리소스가 테넌트 B와 연결되어 테넌트 간 액세스를 방지할 수 있습니다. 이 정책은 보안 주체가의 멤버가 되도록 `updateDataRole`하고 작업을 로 제한합니다`updateData`. 또한이 정책은가 `account_lockout_flag` `false` 이고의 컨텍스트 값이 로 `uses_mfa` 평가되는지 확인합니다`true`.

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

다음 권한 부여 요청은이 섹션의 앞부분에서 설명한 세 가지 정책에 의해 평가됩니다. 이 권한 부여 요청에서 값이 인 `User` 및 유형의 보안 주체`Alice`는 역할를 사용하여 `updateData` 요청합니다`allAccessRole`. `Alice`에는 값이 인 속성`Tenant`이 있습니다`Tenant::"TenantA"`. 수행`Alice`하려는 작업은 `updateData,` 이고, 적용할 리소스는 `SampleData` 유형 입니다`Data`. `SampleData`는 상위 엔터티`TenantA`로 사용됩니다.

`<DATAMICROSERVICE_POLICYSTOREID>` 정책 스토어의 첫 번째 정책에 따라 `Alice`는 정책 `when` 절의 조건이 충족된다고 가정하여 리소스에 대한 `updateData` 작업을 수행할 수 있습니다. 첫 번째 조건은 `principal.Tenant` 속성을 로 평가해야 합니다`TenantA`. 두 번째 조건에서는 보안 주체의 속성이 이어야 `account_lockout_flag` 합니다`false`. 최종 조건에서는 컨텍스트가 여야 `uses_mfa` 합니다`true`. 세 가지 조건이 모두 충족되므로 요청은 `ALLOW` 결정을 반환합니다.

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "context": {
    "contextMap": {
        "uses_mfa": {
            "boolean": true
        }
    }
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {
            {
                "account_lockout_flag": {
                    "boolean": false
                },
                "Tenant": {
                   "entityIdentifier": {
                        "entityType":"MultitenantApp::Tenant",
                        "entityId":"TenantA"
                   }
                }
            }
        },
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
        },
     {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Tenant",
                "entityId": "TenantA"
            }
        ]
      }
    ]
  }
}
```

# 예제 5: Verified Permissions 및 Cedar를 사용한 UI 필터링
<a name="avp-ui-filtering-examples"></a>

Verified Permissions를 사용하여 승인된 작업을 기반으로 UI 요소의 RBAC 필터링을 구현할 수도 있습니다. 이는 다중 테넌트 SaaS 애플리케이션의 경우 특정 사용자 또는 테넌트와 연결될 수 있는 컨텍스트에 민감한 UI 요소가 있는 애플리케이션에 매우 유용합니다.

다음 예제에서는 `Users`의 `Role``viewer`가 업데이트를 수행할 수 없습니다. 이러한 사용자의 경우 UI는 업데이트 버튼을 렌더링해서는 안 됩니다.

![\[Amazon Verified Permissions 및 Cedar를 사용한 UI 필터링 예제\]](http://docs.aws.amazon.com/ko_kr/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-5.png)


이 예제에서는 단일 페이지 웹 애플리케이션에 4개의 버튼이 있습니다. 표시되는 버튼은 현재 애플리케이션에 로그인한 `Role` 사용자의에 따라 다릅니다. 단일 페이지 웹 애플리케이션은 UI를 렌더링할 때 Verified Permissions를 쿼리하여 사용자에게 수행할 권한이 있는 작업을 결정한 다음 권한 부여 결정에 따라 버튼을 생성합니다.

다음 정책은 값이 `Role` 인 유형이 사용자와 데이터를 모두 볼 `viewer` 수 있도록 지정합니다. 이 정책에 대한 `ALLOW` 권한 부여 결정에는 `viewData` 또는 `viewUsers` 작업이 필요하며 리소스가 `Data` 또는 유형과 연결되어야 합니다`Users`. `ALLOW` 결정을 통해 UI는 `viewDataButton` 및 라는 두 개의 버튼을 렌더링할 수 있습니다`viewUsersButton`.

```
permit (
    principal in GuiAPP::Role::"viewer",
    action in [GuiAPP::Action::"viewData", GuiAPP::Action::"viewUsers"],
    resource 
)
when {
   resource in [GuiAPP::Type::"Data", GuiAPP::Type::"Users"]
};
```

다음 정책은 값이 `Role` 인 유형이 데이터만 볼 `viewerDataOnly` 수 있도록 지정합니다. 이 정책에 대한 `ALLOW` 권한 부여 결정에는 `viewData` 작업이 필요하며 리소스가 유형과 연결되어야 합니다`Data`. `ALLOW` 결정을 통해 UI가 버튼을 렌더링할 수 있습니다`viewDataButton`.

```
permit (
    principal in GuiApp::Role::"viewerDataOnly",
    action in [GuiApp::Action::"viewData"],
    resource in [GuiApp::Type::"Data"] 
);
```

다음 정책은 값이 `Role`인 유형이 데이터 및 사용자를 편집하고 볼 `admin` 수 있도록 지정합니다. 이 정책에 대한 `ALLOW` 권한 부여를 결정하려면 `updateData`, `updateUsers` `viewData,` 또는의 작업이 필요하며 `viewUsers`리소스가 유형 `Data` 또는와 연결되어야 합니다`Users`. `ALLOW` 결정을 통해 UI는 `updateDataButton`, `updateUsersButton`, 및 버튼 4개를 모두 렌더링할 `viewDataButton`수 있습니다`viewUsersButton`.

```
permit (
    principal in GuiApp::Role::"admin",
    action in [
        GuiApp::Action::"updateData",
        GuiApp::Action::"updateUsers",
        GuiApp::Action::"viewData", 
        GuiApp::Action::"viewUsers"
       ],
    resource 
)
when {
   resource in [GuiApp::Type::"Data", GuiApp::Type::"Users"]
};
```