Java의 동적 코드 평가-영리합니까?


30

내 응용 프로그램을 위해 Java에서 유연한 ACL 프레임 워크를 만들려고합니다.

많은 ACL 프레임 워크가 규칙의 허용 목록에 작성되며 규칙은 owner : action : resource 형식입니다 . 예를 들어

  • "요한은 리소스 FOOBAR-1을 볼 수 있습니다"
  • "메리가 리소스 FOOBAR-1을 볼 수 있음"
  • "메리 리소스 FOOBAR-1을 편집 할 수 있습니다"

규칙은 데이터베이스에 쉽게 직렬화 / 지속될 수 있기 때문에 매력적입니다. 그러나 내 응용 프로그램에는 복잡한 비즈니스 논리가 있습니다. 예를 들어

  • "5 년 이상 경력이있는 부서 1의 모든 사용자는 FOOBAR-1 자원을 볼 수 있으며 그렇지 않은 경우 권한이 없습니다."
  • "날짜가 2016 년 3 월 15 일 이후 인 경우 부서 2의 모든 사용자는 FOOBAR-2 자원을 볼 수 있으며 그렇지 않은 경우 권한이 없습니다."

처음 생각했을 때, 이것과 같이 매우 복잡한 규칙을 처리 할 수있는 데이터베이스 스키마를 고안하는 것은 악몽 일 것입니다. 따라서 컴파일 된 응용 프로그램에 "굽기"하고 각 사용자에 대해 평가 한 다음 평가 결과로 owner : action : resource 규칙 을 생성해야하는 것처럼 보입니다 . 논리를 컴파일 된 응용 프로그램에 굽는 것을 피하고 싶습니다.

그래서 술어 : action : resource 형식으로 규칙을 표현하려고 생각했습니다 . 여기에서 술어는 사용자의 허용 여부를 결정하는 부울 식입니다. 이 술어는 Java의 Rhino 엔진에 의해 평가 될 수있는 JavaScript 표현식의 문자열입니다. 예를 들어

  • return user.getDept() == 1 && user.seniority > 5;

그렇게하면 술어를 데이터베이스에 쉽게 유지할 수 있습니다.

영리한 가요? 이 엉성한 가요? 이 특수 효과 입니까? 이다 과다 설계 ? 이것이 안전 합니까 (Java는 Rhino 엔진을 샌드 박스 할 수 있습니다).


8
논리를 컴파일 된 응용 프로그램에 넣는 것보다 이러한 비즈니스 규칙을 데이터베이스에 적용하려고하면 어떤 이점이 있습니까?
Winston Ewert

6
@WinstonEWert 규칙을 외부화하면 규칙을 변경, 추가 또는 제거 할 경우 응용 프로그램을 다시 컴파일하고 재배포 할 필요가 없습니다.
Twittopher


2
재미있는 질문! 보안에 중점을 두지 않고 그러한 솔루션의 유지 관리, 안정성 및 사용 용이성 측면에 중점을 둔 답변을보고 싶습니다.
oliver

6
이것은 본질적으로 사용자가 구성 할 수있는 규칙 엔진 인 Outlook 전자 메일 규칙 과 비슷하게 들립니다 .

답변:


37

동적 데이터를 구현 언어의 인터프리터로 파이핑하는 것은 데이터 손상 가능성을 악의적 인 응용 프로그램 인수 가능성으로 확대하기 때문에 일반적으로 나쁜 생각입니다. 즉, 당신은 당신의 방법을 외출 만들 코드 주입 취약점을.

규칙 엔진 또는 DSL (Domain-Specific Language)로 문제를 더 잘 해결할 수 있습니다 . 이러한 개념을 살펴보면 휠을 재발 명할 필요가 없습니다.


16
그러나 JavaScript가 DSL과 같은 스크립팅 언어로 사용되지 않습니까? 필요한 데이터를 설정하고 (읽기 전용) 스 니펫을 함수로 감싸서 안전하게 평가합니다. 코드는 부울을 반환하는 것 외에는 아무것도 할 수 없으므로 악의적 인 기회는 없습니다.
amon

6
@Twittopher 전체 술어를 평가하기 위해 전체 JavaScript 엔진을 드래그하는 것은 여전히 ​​1) 완전한 오버 킬, 2) 위험하고 3) 오류가 발생하기 쉬운 것처럼 보입니다. 예를 들어 , ==대신에 사용 했습니다 ===. 모든 규칙이 항상 끝날터링 완성도 를 제공하고 싶 습니까? 자바와 자바 스크립트 사이의 모든 상호 작용이 정교 해 지도록 후프를 뛰어 넘는 대신 Kilian이 제안한 것처럼 간단한 파서와 인터프리터를 작성하는 것이 어떻습니까? 귀하의 요구에 맞게 조정하고보다 쉽게 ​​확보 할 수 있습니다. ANTLR 등을 사용하십시오.
Doval

6
@Doval 작은 DSL을 쓰는 것은 로켓 과학이 아니며, 3 시간에서 5 일 안에 간단한 언어를 쓸 수 있습니다. 그러나 이것은 1) 완전한 오버 킬, 2) 위험하고 3) 오류가 발생하기 쉬운 것 같습니다. 당신은 정말로 전체 미니 언어를 쓰고 싶습니까? 일부 비즈니스 규칙이 예상보다 복잡하고 모든 기능을 갖춘 언어가 필요한 경우 어떻게해야합니까? Not Invented Here 증후군으로 고통 받고 있습니까? 바퀴를 재창조하는 대신 기존 언어를 사용하지 않는 이유는 무엇입니까? 이미 전투 테스트를 거친 언어를 사용하는 것이 훨씬 쉽습니다.
amon

14
@amon 이런 상황이 발생하면 Killian과 같은 실제 규칙 엔진 (JavaScript가 아님)을 찾을 수 있습니다. 두 가지 접근 방식의 위험을 동일시하는 것은 잘못된 것입니다. 완전한 언어를 위해 통역사를 확보하려는 모든 노력을 버리기 위해서는 한 번의 생략 만하면됩니다. 빼기 과정입니다. 실수로 작은 DSL을 위험하게 만드는 것은 훨씬 어렵습니다. 그것은 부가적인 과정입니다. 실수 할 가능성이있는 구문은 구문 트리를 잘못 해석하는 것이며 단위 테스트가 가능합니다. 우연히 인터프리터에게 하드 드라이브 포맷 기능을 제공하지 않을 것입니다.
Doval

4
@amon : js 스 니펫에 부작용이 while (true) ;
없더라도

44

나는 이것을했고, 당신은하지 않는 것이 좋습니다.

내가 한 것은 Lua에서 모든 비즈니스 로직을 작성하고 해당 Lua 스크립트를 데이터베이스에 저장하는 것입니다. 내 응용 프로그램이 시작되면 스크립트를로드하고 실행합니다. 그렇게하면 새로운 바이너리를 배포하지 않고도 애플리케이션의 비즈니스 로직을 업데이트 할 수 있습니다.

나는 변경을 할 때 항상 바이너리를 업데이트해야한다는 것을 항상 발견했다. 일부 변경 사항은 Lua 스크립트에 있었지만 변경해야 할 변경 목록이 항상 있었으므로 거의 항상 바이너리에서 일부 변경을 수행하고 Lua 스크립트에서 일부 변경을 수행해야했습니다. 바이너리 배포를 항상 피할 수 있다는 상상은 단순히 사라지지 않았습니다.

내가 더 도움이 된 것은 바이너리 배포를 쉽게하는 것이 었습니다. 내 응용 프로그램은 시작시 업데이트를 자동으로 확인하고 업데이트를 다운로드하여 설치합니다. 따라서 사용자는 항상 내가 푸시 한 최신 바이너리에 있습니다. 바이너리 변경과 스크립트 변경 간에는 거의 차이가 없습니다. 다시 한 번하면 업데이트를 원활하게하기 위해 더 많은 노력을 기울일 것입니다.


3

데이터베이스에 코드가 없습니다. 그러나 데이터베이스에 함수 이름이 포함 된 후 리플렉션을 사용하여 호출하면 비슷한 작업을 수행 할 수 있습니다. 새 조건을 추가 할 때 코드와 데이터베이스에 조건을 추가해야하지만 조건과 매개 변수를 전달하여 조건을 복잡하게 평가할 수 있습니다.

즉, 부서 번호가 매겨진 경우 UserDepartmentIs 검사 및 TodayIsAfter 검사를 수행 한 다음 부서 = 2 및 오늘> 03/15/2016이되도록하기가 쉽습니다. 그런 다음 권한을 종료 할 수 있도록 TodayIsBefore 검사를 받으려면 TodayIsBefore 함수를 작성해야합니다.

사용자 권한 으로이 작업을 수행하지 않았지만 데이터 유효성 검사를 위해이 작업을 수행했지만 작동해야합니다.


2

XACML은 실제로 찾고있는 솔루션입니다. 액세스 제어에만 중점을 둔 규칙 엔진 유형입니다. OASIS에서 정의한 표준 인 XACML은 세 부분으로 정의됩니다.

  • 건축
  • 정책 언어 (실제로 원하는 것)
  • 요청 / 응답 체계 (승인 결정을 요청하는 방법).

아키텍처는 다음과 같습니다.

  • PDP (Policy Decision Point)는 아키텍처의 핵심 부분입니다. 알려진 정책 세트에 대해 수신 권한 부여 요청을 평가하는 구성 요소입니다.
  • PEP (Policy Enforcement Point)는 애플리케이션 / API / 서비스를 보호하는 코드입니다. PEP는 비즈니스 요청을 가로 채고 XACML 권한 부여 요청을 작성하여 PDP로 전송하고 응답을 다시 수신하며 응답 내부의 결정을 시행합니다.
  • PIP (Policy Information Point)는 PDP를 LDAP, 데이터베이스 또는 웹 서비스와 같은 외부 데이터 소스에 연결할 수있는 구성 요소입니다. PIP는 PEP가 "앨리스 doc # 12를 볼 수 있습니까?"와 같은 요청을 보낼 때 편리합니다. PDP에는 사용자의 연령을 요구하는 정책이 있습니다. PDP는 PIP에 "앨리스의 나이를 줘"라고 요청한 다음 정책을 처리 할 수 ​​있습니다.
  • PAP (정책 관리 지점)는 전체 XACML 솔루션 (속성 정의, 정책 작성 및 PDP 구성)을 관리하는 장소입니다.

확장 가능한 액세스 제어 마크 업 언어-XACML 아키텍처

첫 사용 사례는 다음과 같습니다.

/*
 * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
 * 
 */
 policy departmentOne{
    target clause department == 1
    apply firstApplicable
    /**
     * All users in department 1 with over 5 years of seniority can VIEW resource FOOBAR-1, else not authorized
     */
    rule allowFooBar1{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }

 }

두 번째 사용 사례는 다음과 같습니다.

 /*
  * "All users in department 2, if the date is after 03/15/2016, can VIEW resource FOOBAR-2, else not authorized"
  *  
  */
  policy departmentTwo{
    target clause department == 1
    apply firstApplicable
    rule allowFooBar2{
        target clause resourceId=="FOOBAR-1" and seniority>=5 and currentDate>"2016/03/15":date and actionId=="VIEW"
        permit
    }
    rule denyOtherAccess{
        deny
    }
  }

참조를 사용하여 두 가지 사용 사례를 단일 정책으로 결합 할 수 있습니다.

  policyset global{
    apply firstApplicable
    departmentOne
    departmentTwo
  }

그리고 당신은 끝났습니다!

XACML 및 ALFA에 대한 자세한 내용은 다음을 참조하십시오.


0

여기서 정말로 원하는 것은 XACML 입니다. 그것은 당신이 원하는 것을 정확하게 제공합니다. 모든 역할이 완전히 분리 된 상태에서 전체 아키텍처를 구현할 필요는 없습니다. 단일 응용 프로그램 만있는 경우 PDP와 PEP를 balana 를 사용하여 앱에 통합 하면 PIP가 무엇이든됩니다. 기존 사용자 데이터베이스입니다.

이제 앱의 어느 곳에서든 무언가를 승인해야하며, 사용자, 동작 및 컨텍스트가있는 XACML 요청을 작성하면 XACML 엔진이 작성한 XACML 정책 파일을 기반으로 결정을 내립니다. 이러한 정책 파일은 데이터베이스 나 파일 시스템 또는 구성을 유지하려는 모든 위치에 보관할 수 있습니다. Axiomatics는 원시 XML보다 조금 더 읽기 쉬운 ALFA라는 XACML XML 표현과 ALFA 정책에서 XACML XML을 생성하는 Eclipse 플러그인을 대체합니다.


1
이것은 질문에 어떻게 대답합니까?
gnat

그는 특히 외부 적으로 구성된 권한 부여 시스템을 구현하려고합니다. XACML은 특정 사용 사례를 매우 잘 다루는 외부에서 구성된 인증 시스템입니다. 동적 코드 실행에 대한 일반적인 질문에 대한 훌륭한 답변은 아니지만 그의 구체적인 질문에 대한 좋은 해결책이라고 인정합니다.
gregsymons

0

우리는 현재 회사에서이 작업을 수행했으며 결과에 매우 만족합니다.

표현식은 js로 작성되었으며, ElasticSearch 쿼리에서 얻을 수있는 결과를 제한하기 위해 사용합니다.

비결은 결정을 내리는 데 충분한 정보를 사용할 수있게하여 코드를 변경하지 않고도 원하는 파마를 실제로 작성할 수 있지만 동시에 빠르게 유지할 수 있다는 것입니다.

시스템을 공격 할 필요가없는 사용자가 권한을 작성하므로 코드 삽입 공격에 대해 걱정하지 않아도됩니다. while(true)예제 와 같은 DOS 공격에도 동일하게 적용됩니다 . 시스템 관리자는 그렇게 할 필요가 없으며 모든 사람의 권한을 제거 할 수 있습니다 ...

최신 정보:

XACML과 같은 것이 조직의 중앙 인증 관리 지점으로 더 나은 것 같습니다. 우리의 유스 케이스는 고객이 팁을 내릴 IT 부서가 전혀 없다는 점에서 약간 다릅니다. 우리는 독립적 인 무언가가 필요했지만 가능한 한 많은 유연성을 유지하려고 노력했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.