1. 소개

이 기사에서는 다양한 액세스 제어 모델을 실제로 구현하는 방법을 살펴봅니다.

2. 액세스 제어 모델이란 무엇입니까?

애플리케이션, 특히 웹 기반 애플리케이션에 대한 일반적인 요구 사항은 정책 이라고도 하는 주어진 조건 집합이 충족되는 경우에만 일부 작업을 수행할 수 있다는 것 입니다 . 자, 이것은 매우 일반적인 요구 사항이므로 몇 가지 예를 제시해 보겠습니다.

  • 인터넷 포럼: 회원만 새 메시지를 게시하거나 기존 메시지에 회신할 수 있습니다.
  • 전자 상거래 사이트: 일반 사용자는 자신의 주문만 볼 수 있습니다.
  • 은행 백오피스: 계정 관리자는 자신의 고객 포트폴리오를 관리할 수 있습니다. 이러한 포트폴리오 외에도 일시적으로 사용할 수 없는 경우(예: 휴가) 다른 계정 관리자의 클라이언트 포트폴리오를 관리할 수 있으며 전자는 동료 역할을 합니다.
  • 디지털 지갑: 결제는 사용자 시간대 20:00~08:00에 $500로 제한됩니다.

주어진 응용 프로그램에 대해 채택할 액세스 제어 모델 은 들어오는 요청을 평가하고 요청을 진행할 수 있는지 여부를 결정합니다. 후자의 경우 결과는 일반적으로 사용자에게 다시 전송되는 오류 메시지입니다.

액세스 제어 모델 fig0

분명히 이러한 각 예제에는 주어진 요청을 승인할 때 다른 접근 방식이 필요합니다.

3. 액세스 제어 모델 유형

이전 예에서 허용/거부 결정을 내리려면 요청과 관련된 다양한 측면을 고려해야 한다는 것을 알 수 있습니다.

  • 요청과 연결된 ID입니다. 익명 액세스도 여기에는 ID 형식이 있습니다.
  • 요청 대상 객체/리소스
  • 해당 개체/자원에 대해 수행되는 작업
  • 요청에 대한 컨텍스트 정보입니다. 시간, 표준 시간대 및 사용된 인증 방법은 이러한 종류의 컨텍스트 정보의 예입니다.

액세스 제어 모델을 세 가지 유형으로 분류할 수 있습니다.

  • RBAC(역할 기반 액세스 제어)
  • 액세스 제어 List(ACL)
  • ABAC(속성 기반 액세스 제어)

유형에 관계없이 일반적으로 모델에서 다음 엔터티를 식별할 수 있습니다.

  • PEP(Policy Enforcement Point) : 요청을 가로채고  PDP 에서 반환한 결과에 따라 진행 여부를 결정합니다.
  • PDP(Policy Decision Point) : 정책을 사용하여 요청을 평가하여 액세스 결정을 내림
  • PIP(Policy Information Point) : 액세스 결정을 내리기 위해 PDP에서 사용하는 정보에 대한 액세스를 저장 및/또는 중재합니다.
  • PAP(Policy Administration Point): 액세스 의사 결정과 관련된 정책 및 기타 운영 측면을 관리합니다.

다음 다이어그램은 이러한 엔터티가 서로 논리적으로 관련되는 방식을 보여줍니다.

액세스 제어 모델 fig1

자율적인 개체로 묘사되지만 실제로는 일부 또는 모든 모델 요소가 애플리케이션 자체에 포함되어 있음을 알 수 있습니다 .

또한 이 모델은 사용자 ID를 설정하는 방법을 다루지 않습니다. 그럼에도 불구하고 이러한 측면은 요청 진행 허용 여부를 결정할 때 고려될 수 있습니다.

이제 이 일반 아키텍처를 위의 각 모델에 어떻게 적용할 수 있는지 살펴보겠습니다.

4. 역할 기반 액세스 제어

이 모델에서 PDP 결정 프로세스는 두 단계로 구성됩니다.

  • 먼저 들어오는 요청의 ID와 관련된 역할을 복구합니다.
  • 그런 다음 해당 역할을 요청 정책과 일치시키려고 시도합니다.

이 모델의 구체적인 구현은 Java EE 사양에 @HttpConstraint 어노테이션 및 이에 상응하는 XML 형식으로 제공 됩니다. 이것은 서블릿에 적용될 때 어노테이션의 일반적인 사용입니다.

@WebServlet(name="rbac", urlPatterns = {"/protected"})
@DeclareRoles("USER")
@ServletSecurity(
  @HttpConstraint(rolesAllowed = "USER")
)
public class RBACController  extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("Hello, USER");
    }
}

Tomcat 서버의 경우 앞에서 설명한 액세스 제어 모델 엔터티를 다음과 같이 식별할 수 있습니다.

  • PEP: 대상 서블릿에서 이 어노테이션의 존재를 확인 하고 현재 요청과 관련된 ID를 복구하기 위해 관련 Realm 을 호출하는 Security 밸브
  • PDP: 주어진 요청에 적용할 제한을 결정하는 Realm 구현
  • PIP: Security 관련 정보를 저장하는 특정 Realm 구현에서 사용하는 모든 백엔드. RBAC 모델의 경우 핵심 정보는 일반적으로 LDAP 저장소에서 검색되는 사용자의 역할 집합입니다.
  • 정책 저장소: 이 경우 어노테이션은 저장소 자체입니다.
  • PAP: Tomcat은 동적 정책 변경을 지원하지 않으므로 실제로 필요하지 않습니다. 그러나 약간의 상상을 통해 어노테이션을 추가하거나 응용 프로그램의 WEB-INF/web.xml 파일을 편집하는 데 사용되는 모든 도구로 이를 식별할 수 있습니다.

다른 Security 프레임워크(예: Spring Security)도 비슷한 방식으로 작동합니다. 여기서 핵심은 특정 프레임워크가 우리의 일반 모델을 정확히 준수하지 않더라도 다소 위장된 경우에도 해당 엔터티가 여전히 존재한다는 것입니다.

4.1. 역할 정의

정확히 역할을 구성하는 것은 무엇입니까? 실제로 역할은 사용자가 특정 애플리케이션에서 수행할 수 있는 명명된 관련 작업 집합입니다 . 응용 프로그램의 요구 사항에 따라 필요에 따라 거칠게 또는 미세하게 정의할 수 있습니다.

세분성 수준에 관계없이 정의하는 것이 좋으므로 각각은 분리된 기능 집합에 매핑됩니다. 이렇게 하면 부작용을 두려워하지 않고 역할을 추가/제거하여 사용자 프로필을 쉽게 관리할 수 있습니다.

사용자와 역할 간의 연결에 관해서는 직접 또는 간접 접근 방식을 사용할 수 있습니다. 전자에서는 사용자에게 직접 역할을 할당합니다. 후자에는 역할을 할당하는 중간 엔터티(일반적으로 사용자 그룹)가 있습니다.

액세스 제어 모델 fig2

이 연결에서 그룹을 중개 엔터티로 사용하는 이점은 한 번에 많은 사용자에게 역할을 쉽게 재할당할 수 있다는 것입니다. 이 측면은 사람들이 한 영역에서 다른 영역으로 끊임없이 이동하는 대규모 조직의 맥락에서 상당히 관련이 있습니다.

마찬가지로 간접 모델을 사용하면 일반적으로 애플리케이션을 리팩토링한 후 기존 역할 정의를 쉽게 변경할 수도 있습니다.

5. 액세스 제어 List

ACL 기반 Security 제어를 통해 개별 도메인 개체에 대한 액세스 제한을 정의할 수 있습니다. 이것은 일반적으로 개체의 전체 범주에 제한이 적용되는 RBAC와 대조됩니다. 위의 포럼 예에서 RBAC 전용 접근 방식을 사용하여 새 게시물을 읽고 만들 수 있음을 정의할 수 있습니다.

그러나 사용자가 자신의 게시물을 편집할 수 있는 새로운 기능을 만들기로 결정했다면 RBAC만으로는 충분하지 않을 것입니다. 이 경우 결정 엔진은 편집 작업의 대상이 누구인지뿐만 아니라 어떤 게시물이 대상인Map 고려해야 합니다.

이 간단한 예에서는 데이터베이스에 단일 작성자 열을 추가하고 이를 사용하여 편집 작업에 대한 액세스를 허용하거나 거부할 수 있습니다. 하지만 협업 편집을 지원하고 싶다면 어떻게 해야 할까요? 이 경우 게시물을 편집할 수 있는 모든 사람의 List(ACL)을 저장해야 합니다.

ACL을 처리하는 데는 몇 가지 실질적인 문제가 있습니다.

  • ACL은 어디에 저장합니까?
  • 대형 개체 컬렉션을 검색할 때 ACL 제한을 효율적으로 적용하는 방법은 무엇입니까?

Spring Security ACL 라이브러리 는 ACL 라이브러리의 좋은 예입니다 . 전용 데이터베이스 스키마와 캐시를 사용하여 ACL을 구현하고 Spring Security와 긴밀하게 통합됩니다. 다음은 개체 수준에서 액세스 제어를 구현하는 방법을 보여주는 이 라이브러리의 기사에서 채택한 간단한 예 입니다.

@PreAuthorize("hasPermission(#postMessage, 'WRITE')")
PostMessage save(@Param("noticeMessage")PostMessage postMessage);

ACL의 또 다른 좋은 예는 개체를 보호하기 위해 Windows에서 사용하는 권한 시스템입니다. 모든 Security 개체 (예: 파일, 디렉터리, 프로세스)에는 개별 사용자/그룹 및 관련 권한 List이 포함된 Security 설명 자가 첨부되어 있습니다.

액세스 제어 모델 fig3

Windows ACL은 관리자가 개별 사용자 및/또는 그룹에 권한을 할당할 수 있도록 매우 강력합니다(요청하는 사람에 따라 복잡함). 또한 개별 항목은 가능한 각 작업에 대한 허용/거부 권한을 정의합니다.

6. 속성 기반 액세스 제어

속성 기반 제어 모델을 사용하면 ID, 작업 및 대상 개체뿐만 아니라 요청과 관련된 컨텍스트 정보를 기반으로 액세스 결정을 내릴 수 있습니다 .

XACML 표준은 아마도 XML 문서를 사용하여 액세스 정책을 설명하는 이 모델 의 가장 잘 알려진 예일 것입니다. 디지털 지갑 출금 규칙을 설명하기 위해 이 표준을 사용하는 방법은 다음과 같습니다.

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" 
  PolicyId="urn:baeldung:atm:WithdrawalPolicy"
  Version="1.0" 
  RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">
    <Target/>
    <Rule RuleId="urn:oasis:names:tc:baeldung:WithDrawalPolicy:Rule1" Effect="Deny">
        <Target>
            <AnyOf>
                <AllOf>
... match rule for the withdrawal action omitted
                </AllOf>
            </AnyOf>
        </Target>
        <Condition>
... time-of-day and amount conditions definitions omitted
        </Condition>
    </Rule>
</Policy>

전체 규칙 정의는 온라인 에서 사용할 수 있습니다 .

장황함에도 불구하고 일반적인 구조를 파악하는 것은 어렵지 않습니다. 정책에는 평가 시 결과가 Effect : Permit 또는 Deny 인 하나 이상의 규칙이 포함됩니다 .

각 규칙에는 요청 속성을 사용하여 논리적 표현식을 정의하는 대상이 포함됩니다. 선택적으로 규칙은 적용 가능성을 정의하는 하나 이상의 Condition 요소를 포함할 수도 있습니다.

런타임 시 XACML 기반 액세스 제어 PEP는 RequestContext 인스턴스를 생성하고 평가를 위해 PDP에 제출합니다. 그런 다음 엔진은 적용 가능한 모든 규칙을 평가하고 액세스 결정을 반환합니다.

RequestContext 에 있는 정보의 종류는 이 모델을 이전 모델과 구별하는 주요 측면입니다. 예를 들어 디지털 지갑 애플리케이션에서 인출을 승인하기 위해 구축된 요청 컨텍스트의 XML 표현을 살펴보겠습니다.

<Request 
    xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
    CombinedDecision="true"
    ReturnPolicyIdList="false">
    
    <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
... action attributes omitted
    </Attributes>
    <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment">
... environment attributes (e.g., current time) omitted
    </Attributes>
    <Attributes Category="urn:baeldung:atm:withdrawal">
... withdrawal attributes omitted 
    </Attributes>
</Request>

21:00에 이 요청 을 XAML 규칙 평가 엔진에 제출 하면 야간 거래에 허용되는 최대 금액을 초과하므로 예상되는 결과는 이 인출을 거부하는 것입니다.

ABAC 모델의 주요 이점은 유연성입니다. 정책을 변경하기만 하면 복잡한 규칙을 정의하고 수정할 수 있습니다. 구현에 따라 실시간으로 수행할 수도 있습니다.

6.1. XACML4J

XACML4J 는 Java용 XACML 3.0 표준의 오픈 소스 구현입니다. ABAC 모델에서 요구하는 평가 엔진 및 관련 엔터티의 구현을 제공합니다. 핵심 API는 당연히 PDP 로직을 구현하는 PolicyDecisionPoint 인터페이스입니다.

PDP를 구축했으면 이를 사용하려면 두 단계가 필요합니다. 먼저 평가하려는 요청에 대한 정보 로 RequestContext 를 생성하고 채웁니다.

... attribute categories creation omitted
RequestContext request = RequestContext.builder()
  .attributes(actionCategory,environmentCategory,atmTxCategory)
  .build();

여기에서 각 xxxCategory 매개변수에는 연관된  Category 에 대한 속성 세트가 포함되어 있습니다 . 전체 코드사용 가능한 빌더를 사용하여 21:00에 발생하는 $1,200.00 인출에 대한 테스트 요청을 생성합니다. 또는 JAXB 호환 소스 에서 직접 RequestContext 객체 를 생성할 수도 있습니다 .

다음으로 평가를 위해 이 개체를 PolicyDecisionPoint 서비스 의 결정() 메서드에  전달합니다.

ResponseContext response = pdp.decide(request);
assertTrue(response.getDecision() == Decision.DENY); 

반환된 ResponseContext 에는 정책 평가 결과 가 포함된 Decision 개체가 포함되어 있습니다. 또한 진단 정보와 추가 의무 및/또는 조언을 PEP에 반환할 수도 있습니다. 의무와 조언은 그 자체에 대한 주제이므로 여기서는 다루지 않겠습니다. Axiomatic의 이 예제은 이 기능을 사용하여 일반적인 기록 시스템 애플리케이션에서 규제 제어를 구현하는 방법을 보여줍니다.

6.2. XACML이 없는 ABAC

XACML의 복잡성은 일반적으로 대부분의 응용 프로그램에 과도하게 사용됩니다. 그러나 애플리케이션에서 기본 모델을 계속 사용할 수 있습니다. 결국 우리는 항상 특정 사용 사례에 맞게 조정된 더 간단한 버전을 구현할 수 있으며 몇 가지 매개변수만 외부화할 수 있습니다. 맞습니까?

노련한 개발자라면 누구나 이것이 어떻게 끝나는지 알고 있습니다…

ABAC 구현의 까다로운 측면은 요청의 페이로드에서 속성을 추출하는 방법 입니다. 서블릿 필터 또는 JAX-RS 인터셉터와 같이 요청을 처리하기 전에 사용자 정의 로직을 삽입하는 표준 메소드는 원시 페이로드 데이터에만 액세스할 수 있습니다.

최신 애플리케이션은 JSON 또는 유사한 표현을 사용하는 경향이 있으므로 PEP는 페이로드 속성을 추출하기 전에 이를 디코딩해야 합니다. 이는 특히 대용량 페이로드의 경우 CPU 및 메모리 사용량에 대한 잠재적 적중을 의미합니다.

이 경우 더 나은 접근 방식은 AOP를 사용하여 PEP를 구현하는 것입니다. 이 경우 측면 처리기 코드는 페이로드의 디코딩된 버전에 액세스할 수 있습니다.

7. 결론

이 기사에서는 다양한 액세스 제어 모델과 애플리케이션이 이를 사용하여 액세스 규칙을 적용하는 방법에 대해 설명했습니다.

늘 그렇듯이 예제의 전체 소스 코드는  GitHub 에서 찾을 수 있습니다 .

Security footer banner