2006.09.09 - 최범균(madvirus@madvirus.net)이 원문 최초 번역
이 페이지는 JSPWiki 2.4의 보안 특징에 대해서 간략하게 소개하고 있다. 새로운 시스템은 2005년 1월 이후에 개발되기 시작했고, 현재 2.4.x 버전에서 안정화되었다. 새로운 보안 시스템의 목적은 기존의 커스텀 JSPWiki 인증 방식을 웹 콘테이너 인증 및 자바 표준 보안 인증과 합치기 위해서이다. 이 페이지의 내용은 JSPWiki 2.4.25 또는 그 이상의 버전에 적용된다.
본 가이드는 JSPWiki의 보안 특징을 어떻게 사용할지에 대한 좋은 아이디어를 제공할 것이다. 이 페이지와 더불어 아래의 내용을 참고하기 바란다:
- JSPWiki:Security 2.3 Howto
, 새로운 특징을 사용하는 몇가지 예제를 제공
- JSPWiki:Security 2.3 FAQ
, 일반적인 문제에 대한 질문과 답변을 제공
- JSPWiki:PluginsAndAuthorization2.3
, 더욱 발전시킬 수 있는 몇 가지 분야 :)
- JSPWiki:Security 2.3 Wish List
, 앞으로 향상될 수 있는 몇가지 특징들의 목록
노트: 초기 2.3 빌드 이후에 보안 정책 구문이 변경되었다. 만약 커스텀 보안 정책을 사용했는데 최근에 2.4.25 또는 그 이상의 버전으로 업그레이드했다면, 아래에 있는 기본 보안 정책 수정하기 섹션을 읽어보기 바란다.
보안 트러블슈팅#
JSPWiki 2.4.7 또는 그 이상의 버전을 사용중이라면 진단 페이지admin/SecurityConfig.jsp를 체크해보기 바란다. 이 페이지는 몇가지 간단한 테스트를 수행한 뒤 보안 설정이 안전한 지 검증할 것이다.Table of Contents
- 보안 트러블슈팅
- 특징
- 보안 개요
- 시작하기
- 더 많은 정보
- 인증
- 아이덴티티 관리
- 위키 프로파일 생성하기
- 사용자 프로파일
- 사용자 데이터베이스
- 접근 제어
- 역할
- 위키 그룹
- ACL(Access Control List)
- 보안 정책
- JSPWiki 보안 커스터마이징
- 기본 보안 정책 수정하기
- 보안 정책의 동작 방식
- 보안 정책 예제
- 와일드카드
- 퍼미션 포함 관계
- 정책 블록에 당사자 정의하기
- 커스텀 정책 구현하기
- 인증 과정 커스터마이징
- 인증이 동작하는 방식
- JSPWiki의 JAAS 설정 커스터마이징
- 콘테이너 인증 방식과 통합하기
- 아이덴티티 관리 커스터마이징
- 권한 부여 과정을 커스터마이징하기
- 권한 부여가 동작하는 방식
- 외부 인가자에 의뢰하기
특징#
보안 개요#
JSPWiki 2.4는 풍부하고 유연한 보안 특징을 제공하고 있다. 이로 인해 JSPWiki는 대형 인트라넷의 부분으로서 또는 독립 단위로 동작할 수 있을 만큼 충분한 보안을 제공하고 있다. 하지만, 비록 JSPWiki의 보안 서브 시스템이 커스터마이징을 원하는 만큼 할 수 있긴 하지만, 처음 시작할 때에는 기본 설정만으로도 충분한다. 여기서는 주요 특징에 대해서 살펴볼 것이다.| 특징 | 설명 | 기본 |
|---|---|---|
| 익명성과 트러스트 | 사용자는 임의이거나, 부분적으로 인증되었거나 (즉 지속성을 지닌 쿠키를 사용한 asserted), 또는 인증될 수 있다. | Anonymous와 Asserted 사용자는 위키를 읽고 수정할 수 있다. |
| 아이덴티티 관리 | 사용자는 암호를 갖는 프로파일을 생성함으로써 위키에 등록할 수 있다. 로그인 한 뒤, 사용자는 자신의 프로파일을 관리할 수 있다. 프로파일은 로그인 ID, 전체 이름, 위키 이름, 이메일 주소 그리고 (선택적으로) 암호를 포함한다. JSPWiki API는 LDAP이나 RDBMS와 같은 모든 호환가능한 사용자 데이터베이스를 아이덴티티 스토리지로 플러그인 할 수 있다. | JSPWiki는 사용자 프로파일을 저장하는 사용자 데이터베이스로 XML 파일을 사용한다. 암호는 SAH-1을 사용하여 해시된다. 또한 JDBC DataSource를 제공하는 모든 데이터베이스에 프로파일을 저장할 수도 있다. |
| 인증 | 위키는 사용자 데이터베이스에 저장된 사용자 ID와 암호를 사용하여 사용자를 인증할 수 있고 또는 J2EE 콘테이너로부터 인증 자격을 허용할 수도 있다. | JSPWiki는 자신 만의 데이터베이스를 사용하여 사용자를 인증한다. ("커스텀 인증") |
| 보안 정책 | 위키의 보안 정책은 사용자가 어떤 기능을 수행할 수 있는지를 결정한다. 예를 들어, 정책을 통해 anonymouse, asserted 그리고 authenticated 사용자가 페이지를 읽고, 편집하고, 이름을 바꾸고 그리고 삭제할 수 있는지 또는 사용자 프로파일을 만들고 수정할 수 있는지, 또는 새로운 페이지와 위키 그룹을 만들 수 있는지를 지정할 수 있다. ACL(Access Control list)을 사용하여 페이지 단위로 권한을 설정할 수도 있다. | JSPWiki는 기본적으로 거의 모든 사용자에게 폭넓은 권한을 부여한다. |
| ACL(Access Controls Lists) | 작성자는 문서를 누가 보고, 수정하고, 편집할 수 있는 지에 대한 ACL을 추가할 수 있다. ACL은 사용자 이름, 위키 이름, 위키 그룹 또는 외부의 인증된 역할을 포함할 수 있다. 만약 ACL이 위키 그룹이나 역할을 포함하고 있다면, 사용자는 반드시 그룹의 멤버이거나 그 역할을 소유하고 있어야 한다. 페이지 내용과 독립된 방법으로, 관리자는 외부에 ACL을 저장할 수 있다. | ACL은 특별한 위키 마크업을 사용하여 위키 페이지 자체에 저장된다. |
| 그룹 | 사용자는 간단한 마법사를 사용하여 사용자의 그룹을 즉각적으로 생성할 수 있다. 이렇게 생성한 그룹은 특정 페이지에 대한 접근을 제약하기 위해 ACL에 추가될 수 있다. 관리자가 그룹 멤버 정보를 어디에 (파일 또는 데이터베이스 등) 저장할지를 설정할 수 있다. | JSPWiki는 기본적으로 그룹 데이터베이스로 XML 파일을 사용한다. |
| 역할 | 사용자는 'Authenticated'나 'Admin'과 같이 자신의 정체에 알맞은 역할을 소유할 수 있다. 이 역할은 특정한 페이지에 대한 접근을 제어하기 위해 ACL에 추가될 수 있다. JSPWiki 관리자는 사용자가 특정 역할을 소유하고 있는 지의 여부를 데이터베이스나 웹 콘테이너와 같은 외부의 인가자(authorizer)에게 의뢰할 수 있다. | JSPWiki는 사용자의 역할 소유를 판단하기 위해 isInRole을 사용하여 J2EE 웹 콘테이너에 문의한다. |
| 엔터프라이즈 통합 | J2SE 표준 보안 정책 파일의 구문을 사용하여 보안 정책을 표현한다. 보안 정책 파일의 위치는 관리자에 의해 변경될 수 있다. JAAS(Java Authentication and Authorization Service)를 사용하여 인증을 관리하며, 로그인 설정 위치 역시 설정할 수 있다. 위키는 인증 자격을 제공하고 권한 검사를 수행하기 위해 추가적으로 J2EE 웹 콘테이너의 제약 조건을 사용할 수 있다. 콘테이너가 관리하는 인증 및 권한 서비스는 관리자가 LDAP, SSO, PAM, Kerberos 그리고 액티브 디렉토리와 같은 엔터프라이즈 보안 인스트럭쳐에 연결할 수 있도록 해 준다. | 미리 정의된 자바 보안 설정 파일과 JAAS 설정 파일이 제공되며, 관리자가 설정을 변경하지 않은 경우 미리 제공된 보안 설정이 로딩된다. JSPWiki는 기본적으로 J2EE 콘테이너가 관리하는 인증 및 권한 서비스를 사용하지 않는다. |
시작하기#
JSPWiki 보안을 시작하기 위해 특별히 필요한 것은 없다. 단순히 JSPWiki WAR를 배포하고 여러분이 사용하고 있는 서블릿 콘테이너에 로딩하면 된다. 기본적으로:- 기본 로그인 설정과 보안 정책이 자동으로 로딩된다
- 임의 사용자도 페이지를 수정하고 사용자 프로파일을 생성할 수 있다
- 사용자는 로그인 이름과 암호를 사용하여 로그인한다
- 사용자 정보는 WEB-INF 폴더에 있는 XML 파일에 저장된다
- 위키 그룹은 WEB-INF 폴더에 있는 XML 파일에 저장된다
- 콘테이너가 관리하는 인증 및 권한 서비스를 사용하지 않는다. (물론, 기본적으로는 실제로 사용하는 것 같다 - 아래의 노트를 보자 - Karsten)
기본 설정을 사용하면, 사용자는 프로파일을 생성하고, 페이지와 그룹을 만들고 페이지 ACL을 생성할 수 있다.
만약 이 특징을 직접 테스트해보고 싶다면, 위키 웹 어플리케이션을 시작해보자. 그리고 "My Prefs"를 클릭하여 프로파일을 작성해보자. 그러면 WEB-INF/userdatabase.xml 파일에 새로운 사용자 정보가 추가된 것을 확인할 수 있을 것이다. 그런 뒤, 로그인을 하여 화면의 왼쪽편에 "G'Day" 메시지가 출력되는 지 확인해보자.
| 노트: "Create User Profile"을 실행할 때 Could not save profile: You must log in before creating a profile. Login name cannot be null. 에러와 함께 문제가 생길 수 있다. (리눅스 아파치 톰캣 5.5.17에서 JSPWiki-2.4.15 베타 버전을 설치한 경우) BugSecurity에서, Alex Reid는 문제를 수정하기 위해 다음과 같이 지적했다. WEB-INF 폴더에 위치한 jspwiki.properties 파일에 기본값인 "jspwiki.security = container" 라고 설정되어 있지 않고 "jspwiki.security = jaas" 라고 설정되어 있는 확인해보시오 - Karsten Breivik |
모든 사람은 페이지에 접근할 수 없고 오직 특정 사람만 볼 수 있도록 하려면 새 페이지를 만들고 ACL 마크업을 추가하면 된다:
[{ALLOW view AndyJ}]
로그아웃하고 그 페이지를 보려고 시도해보자. 위키는 요청을 거절하고 로그인 페이지로 리다이렉트 할 것이다.
다음에, 로그인 하고 새로운 위크 그룹을 만들어보자. 그 그룹에 내 계정이 포함된 것을 확인할 수 있다. (기본적으로 자신의 계정이 새로 만든 그룹에 추가된다.) 그런 뒤, 새로운 위키 페이지를 만들고 새로 만든 그룹이 페이지를 읽을 수 있도록 ACL을 추가하자. 로그아웃 하고 방금 만든 페이지에 접근하면 역시 로그인 페이지로 이동할 것이다.
WEB-INF/jspwiki.policy 파일의 내용을 살펴보면, 그것의 구문이 비교적 직관적인 것을 알 수 있다. 직접 이 파일을 조작할 수도 있다 예를 들어, anonymous 사용자에 대한 "editor" 권한을 없앤 뒤 웹 어플리케이션을 시작해보자. 그럼, 임의 사용자가 페이지를 수정할 수 없게 된다.
더 많은 정보#
이 문서의 나머지 부분은 JSPWiki의 보안 시스템에 대한 보다 자세한 정보를 담고 있다. 관심이 있다면 계속해서 읽어볼 것을 궈한다.인증#
JSP는 다양한 단계의 인증과 트러스트를 지원한다. 사용자는 임의 사용자일 수 있고, 쿠키를 통한 "asserted" 사용자일 수도 있고, 인증되거나 또는 관리자일 수 있다.| 상태 | 설명 | 왼쪽 메뉴에 보여지는 것.. |
|---|---|---|
| Anonymous | 로그인 하지 않고 제공된 쿠키가 없는 사용자 | (아무것도 업음) |
| Asserted | 사용자의 브라우저가 JSPWikiAssertedName라고 불리는 쿠키를 포함 | "G'Day, username (not logged in)" |
| Authenticated | 아이디와 암호를 사용하여 로그인한 사용자 | "G'Day, username (authenticated)" |
기본 보안 정채과 페이지 ACL에 따라, 사용자는 인증이 필요하거나 필요하지 않을 수 있다.
사용자가 로그인 하고자 할 때 --- 또는 보안 정책 또는 페이지 ACL에 의해 로그인이 필요할 때 --- username 필드와 password 필드를 갖는 웹 폼이 출력된다. 웹 폼에 아이디와 암호를 입력한 뒤 정보를 전송하면, JSPWiki는 아래의 방법 중 하나를 사용하여 로그인을 시도한다.
- 커스텀 인증, JSPWiki의 사용자 데이터베이스에 저장된 아이와 암호를 찾고 검증
- 콘테이너 인증, 인증을 수행하고 자격을 제공하는 서블릿 콘테이너에 의존
JSPWiki는 어떤 인증 방식이 유효한지 스스로 찾아낸다. 만약 web.xml 파일에 특정 <security-contraint> 요소가 주석처리되어 있지 않다면, 콘테이너 인증이 사용된다. 그렇지 않다면 JSPWiki는 커스텀 인증을 사용한다. 어떤 방식을 사용하더라도 사용자는 동일하게 느끼게 된다.
아이덴티티 관리#
위키 프로파일 생성하기#
비록 몇몇 위키가 임의 사용자로 구성되지만, 많은 경우 그렇지 않다. 종종, 위키는 사용자에게 웹 사이트에서 자신을 표현할 수 있는 아이덴티티를 만들 수 있도록 하고 있다. JSPWiki는 기본적으로 사용자가 자신만의 위키 프로파일을 설정하고 관리할 수 있는 기본 화면을 포함하고 있다.위키 프로파일을 설정하려면 프론트 페이지에 있는 링크를 클릭하여 UserPreferences.jsp 페이지를 연다. 즉, "My Prefs" 링크를 클릭한 뒤 "Profile" 탭을 연다. 기본적으로 폼은 아래의 정보를 입력받는다:
- 사용자 ID
- 사용자가 원하는 "위키 이름" (예, JanneJalkanen)
- 사용자의 전체 이름 (first and last name)
- 암호
- 이메일 주소
사용자가 프로파일을 저장하면, JSPWiki는 새로운 사용자 ID, 위키 이름, 전체 이름을 이미 다른 사용자가 사용하고 있는 지 검사한다. 만약 사용중이라면 다른 값을 입력할 수 있도록 입력폼이 다시 출력된다
사용자 프로파일#
위키 프로파일을 생성한 다음에, 사용자는 프론트 페이지에 잇는 My Prefs} 링크를 통해서 최근에 입력한 프로파일을 수정할 수 있다. 기본적으로 사용자는 자신의 프로파일을 수정하기 위해서는 인증을 거쳐야 한다.사용자 데이터베이스#
사용자 프로파일을 저장할 때, 그 정보는 UserDatabase라고 불리는 저장소에 저장된다. 기본적으로, 프로파일을 WEB-INF 디렉토리에 있는 userdatabase.xml 파일에 저장된다. 각 사용자 프로파일을 각각의 <user> 요소에 저장되며, 암호는 SHA-1을 사용하여 해시처리된다.2.3.3 버전부터 JSPWiki는 JDBC와 호환되는 데이터베이스 프로파일을 저장할 수 있게 되었다. XML 사용자 데이터베이스와 마찬가지로, JDBC 호환 DB 역시 인증 서브시스템에 플러그인된다. 이것은 데이터베이스를 사용하여 프로파일을 저장하고 사용자를 인증할 수 있다는 것을 의미한다. 또한, 웹 콘테이너와 사용자 데이터베이스를 공유할 수도 있다.
접근 제어#
JSPWiki는 위키이다. 위키는 공개와 참여를 표방한다. 기본적으로, JSPWiki도 모든 사용자가 모든 위키 페이지를 보고, 작성하고 수정할 수 있도록 하고 있다. 하지만, 많은 경우에 사용자는 특정 페이지에 대한 접근을 제약하길 원할 것이다. Access control lists, 또는 ACL을 사용하면 사용자는 특정 페이지에 대한 접근 권한을 제어할 수 있게 된다. ACL은 사용자, 역할 그리고 위키 그룹이 특정 기능을 수행할 수 있도록 명시할 수 있다.역할#
JSPWiki는 역할(Role)이라고 불리는 사용자 클래스를 통해서 역할 기반의 보안을 구현하고 있다. 특별히, JSPWiki는 사용자 인증 상태를 표시하는 네 개의 역할을 정의하고 있다:- Anonymous
- Asserted
- Authenticated
- All
기본으로 제공되는 역할 뿐만 아니라 JSPWiki는 서블릿 콘테이너와 같은 외부의 인가자가 제공하는 역할을 인식할 수 있다.
위키 그룹#
역할 기반의 보안은 훌륭하다. 하지만, 그것이 때로는 위키에서 문제가 될 수도 있다. 그것은 전통적인 역할 기반의 접근 제어는 종종 모든 것이 관리자에 의해 설정된다고 가정하기 때문이다. 이는 지원 작업의 병목을 유발하고 채택하는 데 장애물이 된다.역할 기반의 접근 제어를 좀더 유연하게 만들기 위해 JSPWiki는 사용자 위키 그룹을 만들 수 있도록 하였다. 이는 특별한 역할로서 사용자가 그들 스스로 생성할 수 있다. 사용자는 프론트 페이지에 있는 Create a new group. 링크를 클릭하면 NewGroup.jsp 페이지가 열리면서 위키 그룹을 생성할 수 있게 된다. 사용자는 그룹의 이름과 그룹에 속한 멤버 목록을 입력한 뒤 "save" 버튼을 클릭하면 입력한 멤버를 포함한 위키 그룹이 생성된다. 기본적으로 그룹에 속한 누구든지 멤버 목록을 수정할 수 있다.
페이지 ACL과 함께 역할과 위키 그룹은 위키를 잠그는 데 사용된다. 접근 제어에 대해서는 바로 다음에 설명하고 있다.
ACL(Access Control List)#
ACL(Access control lists)은 사용자가 특정 페이지에 대한 권한을 제어할 수 있도록 한다. ACL은 간단하고 특별한 위키 마크업으로서, 특정 페이지에 대해 누가 어떤 기능을 수행할 수 있는지를 정의한다.- 누가: 사용자의 위키이름 또는 전체 이름을 사용한다. 둘다 모두 잘 동작한다. 빌트인 역할이나 위키 그룹 또한 가능하다.
- 무엇을: 유요한 권한은 "view", "edit", "comment", "rename" 그리고 "delete"이다.
예를 들어, Janne와 Mike Morris 만 볼 수 있는 비밀 페이지를 작성했다고 해 보자. 이 경우 위키 페이지의 상단에 다음의 마크업을 추가해주기만 하면 된다:
[{ALLOW view Janne,Mike Morris}]
위 설정은 Janne과 Mike는 페이지를 볼 수 있지만, 그 밖에 나머지는 볼 수 없다는 것을 뜻한다. 위 ACL은 "edit" 권한을 포함하고 있지 않다. 만약 Janne가 이 문서를 수정할 수 있도록 하려면 다음을 추가해주면 된다:
[{ALLOW edit Janne}]
ACL은 역할과 위키 그룹을 포함할 수 있다. 모든 인증된 사용자는 페이지를 볼 수 있고 위키 그룹 "Managers"의 멤버는 수정도 할 수 있도록 설정하려면 다음과 같이 설정 하면 된다:
[{ALLOW view Janne,Mike Morris,Authenticated}]
[{ALLOW edit Janne,Managers}]
역할, 위키 그룹, 그리고 사용자/위키 이름이 때로는 중복될 수도 있다. 보안상의 이유로, 빌트인 역할과 콘테이너가 정의한 역할을 항상 같은 으림을 가진 위키 그룹보다 높은 우선순위를 갖는다. 마찬가지로 위키 그룹은 사용자의 이름 또는 위키 이름보다 높은 우선순위를 갖는다. 따라서, 비록 "Authenticated"라는 이름을 가진 사용자를 등록하는 것이 가능할지는 몰라도, 그 사용자가 "Authenticated" 역할에 부여된 모든 접근 권한을 갖지는 못한다.
노트: 접근 거부 ACL을 지원하지 않는다. 이는 신중하고 철학적인 디자인 선택이다. --- 허용과 거부의 우선순위에 대해 걱정하는 것보다 기본적으로 거부하는 것이 훨씬 쉽다.
기본적으로, 위키 페이지는 ACL을 갖지 않는다. 페이지가 ACL을 갖지 않는다면, 기본 보안 정책이 페이지에 적용된다. 보안 정책에 대해서는 다음 절에서 살펴볼 것이다.
보안 정책#
JSPWiki는 아래의 두가지 정보를 사용하여 기능을 허용할지의 여부를 결정한다:- 페이지 ACL - 페이지 마다 접근 제약을 정의한 마크업 (앞에서 살펴보았다)
- 보안 정책 - 각 타입의 사용자를 위한 미리 정의한 허용 집합
| 승인 | Anonymous 사용자 | Asserted 사용자(쿠키를 가짐) | Authenticated 사용자 | Admin 그룹 |
|---|---|---|---|---|
| 모든 페이지 보기 | x | x | x | x |
| 모든 페이지 수정하기 | x | x | x | x |
| 모든 페이지에 첨부 파일 업로드하기 | x | x | ||
| 모든 페이지를 수정(편집+업로드)하기 | x | x | ||
| 모든 존재하는 페이지에 주석달기 | x | x | x | x |
| 새 페이지 작성하기 | x | x | x | x |
| 모든 페이지의 이름 변경하기 | x | x | ||
| 모든 페이지를 삭제하기 | x | |||
| 모든 그룹을 보기 | x | x | x | |
| 모든 그룹을 수정하기 | x | x | ||
| 모든 그룹의 이름을 변경하기 | x | x | ||
| 모든 그룹을 삭제하기 | x | |||
| 새 그룹을 생성하기 | x | x | ||
| 프로파일을 생성하기 | x | x | x | x |
| 사용자 기호 정보를 수정하기 | x | x | ||
| 사용자 프로파일을 수정하기 | x | x |
이들 권한은 기본값이다. 보고, 수정하고, 주석을 다는 등의 페이지 기능의 경우 특정 페이지에 ACL을 추가함으로써 추가적인 제약을 가할 수 있다. 주의할 점은 ACL을 사용한다 하더라도 이미 정책에 의해 허용된 것 이상의 권한을 부여하지는 못한다는 것이다. 예를 들어, 정책에서 Anonymous 사용자가 모든 페이지를 읽을 수 있지만 수정할수는 없다고 정의한 경우, Main 페이지의 ACL에서 Anonymous 사용자에게 Edit 권한을 부여한다 하더라도 동작하지 않을 것이다.
JSPWiki는 표준 자바 보안 정책 API를 사용한다. 기본 퍼미션은 표준 보안 정책 파일 구문을 사용해서 승인된다. JSPWiki는 처음 시작될 때 기본 보안 파일인 WEB-INF/jspwiki.policy 로딩한다.
JSPWiki의 기본 보안 정책은 소규모 팀에는 적당하다. 하지만, 기업의 인트라넷이나 공개 위키에서 사용하기에는 다소 느슨한 편이다. 다음의 기본 보안 정책 수정하기 섹션에서 정책을 보다 강력하게 만드는 상세한 내용과 기존의 보안 정책을 사용하여 JSPWiki를 실행하는 방법을 살펴볼 것이다.
JSPWiki 보안 커스터마이징#
기본 보안 정책 수정하기#
보안 정책의 동작 방식#
JSPWiki의 보안 정책 시스템은 자바의 보안 API에 기반하고 있다. WEB-INF/jspwiki.policy에 저장된 기본 보안 파일은 페이지 ACL이 제공되지 않을 때 위키 페이지에 대한 권한 정보를 정의한다. 정책은 또한 사용자 프로파일이나 그룹 생성과 같이 페이지 이외의 것과 관련된 기능에 대한 것도 제어한다.jspwiki.policy 파일은 표준 자바 정책 파일이기 때문에, 그 구문에 친숙하다면 쉽게 이해할 수 있을 것이다. 기본 정책은 표준 "workgroup wiki" 사용자 경우를 목표로 하고 있다. 정책 블럭은 전형적으로 네 개의 주요 퍼미션 타입인 PagePermission, GroupPermission, WikiPermission 그리고 AllPermission를 특정한 역할을 가진 사용자에게 허용한다:
- PagePermission은 특정한 페이지 또는 페이지 집합에 대해 허용된 기능이다: view, edit, modify, comment, rename, upload, delete. PagePermission은 와일드카드를 지원한다.
- GroupPermission은 누가 그룹에 접근하고 관리할 수 있는지를 제어한다: view, edit, delete
- WikiPermission은 특정한 대상 위키에 대해 허용된 기능이다: createPages, createGroups, registerUser, editPreferences
- AllPermission은 주어진 위키의 모든 권한을 허용한다. 개략적으로 유닉스 시스템에서 root 권한과 비슷하다.
WikiPermission, GroupPermission 그리고 PagePermission을 위한 문법은 기능 다음에 대상을 명시한다. WikiPermission의 경우 대상은 위키의 이름이다. (위키 이름은 jspwiki.properties 파일의 jspwiki.applicationName 프로퍼티에 정의되어 있다.) PagePermission의 경우, 대상은 위키 이름과 콜론, 그리고 페이지 이름 또는 페이지 모음으로 구성된다. GroupPermission도 동일한 방식으로 동작한다. 앞서 언급했듯이 기능 문자열은 퍼미션마다 다르다.
네 번째 타입의 퍼미션 AllPermission은 이 퍼미션을 소유한 사용자에게 관리자 권한을 부여한다. 해당 위키에서 AllPermission를 승인받은 사용자는 무엇이든지 할 수 있고, 페이지가 ACL을 소유하고 있는지의 여부에 상관없이 퍼미션 검사를 받지 않는다. AllPermission 퍼미션은 한 개의 대상만 허용하며, 그 한개의 대상은 위키의 이름이 적용된다.
보안 정책 예제#
다음은 기본 보안 파일에서 발췌한 "grant" 블럭 예제 코드이다.grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.authorize.Role "Anonymous" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:*", "view";
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:*", "modify";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "createPages";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editPreferences";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editProfile";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "login";
};
이 보안 블럭은 anonymous 사용자에게 다소 폭넓은 권한을 허용하고 있다. 사용자는 모든 위키에 대해 ACL을 갖지 않는 모든 페이지를 보고 편집할 수 있고 새로운 페이지를 만들고, 프레퍼런스를 수정하고, 프로파일을 만들고 수정할 수 있다. modify 페이지 퍼미션을 갖고 있기 때문에, 페이지를 편집할 수 있고 그리고 파일을 춤버할 수 있다. 필요에 따라 이 보안 정책을 알맞게 변경할 수 있다. 예를 들어, anonymous 사용자가 새로운 페이지를 만들거나 기존의 페이지를 편집할 수 없도록 만들어 보자. (즉, 페이지 관련 작업을 하기 전에 프로파일을 먼저 만들고 인증을 받도록 해 보자.) 다음은 이런 요구에 맞춰 수정한 정책 블록 부분의 코드이다:
grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.authorize.Role "Anonymous" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:*", "view";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editPreferences";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editProfile";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "login";
};
하지만, 이것만으로 충분하지 않다고 해보자. 사용자가 다른 어떤 페이지에 앞서 반드시 프론트 페이지를 먼저 읽어야 한다고 해 보자. 이 경우 다음과 같이 정책 블록을 변경해서 원하는 바를 이룰 수 있다:
grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.authorize.Role "Anonymous" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:Main", "view";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editPreferences";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editProfile";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "login";
};
anonymous 사용자가 모든 위키 그룹에 있는 멤버 목록을 볼 수 있길 원한다고 해 보자. 이는 일반적인 경우가 아니기 때문에 기본 설정 값이 아니다. 아마도 이런 경우는 그룹 멤버 정보가 보안에 민감한 정보가 아니라고 추측할 수 있다. 이 경우 GroupPermission "*:*", "view"을 추가할 필요가 있다. 다음은 필요한 내용이 추가된 정책 블럭 코드이다:
grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.authorize.Role "Anonymous" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:Main", "view";
permission com.ecyrd.jspwiki.auth.permissions.GroupPermission "*:*", "view";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editPreferences";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "editProfile";
permission com.ecyrd.jspwiki.auth.permissions.WikiPermission "*", "login";
};
마지막으로 "Admin"이라는 위키 그룹을 만들고 이 그룹에 관리자 권한을 부여해보자:
grant
principal com.ecyrd.jspwiki.auth.GroupPrincipal "Admin" {
permission com.ecyrd.jspwiki.auth.permissions.AllPermission "JSPWiki";
};
Admin 위키 그룹에 속한 모든 사용자는 다음에 JSPWiki를 시작할 때 관리자로서 인식될 것이다. 따라서, Admin 위키 그룹에 있는 모든 사용자는 관리자가 된다. Admin 그룹의 회원 목록은 초기에 비어있다. 여러분은 직접 수동으로 (Install.jsp}를 실행하여) Admin} 위키 그룹을 만들어야 한다.
노트: "grant" 블럭의 signedBy "jspwiki" 섹션은 호출하는 코드가 인증되고 트러스트되었다는 것을 확신한다. 만약 기본 정책을 커스터마이징한다면, 모든 "grant" 블럭에 이 문장을 포함시킬것을 권한다.
와일드카드#
PagePermission을 위한 정책 구문은 페이지 대상에 대한 접두사 또는 접미사로 와일드카드를 허용한다. 이는 정책 블럭을 간결하고 보기 좋게 만들어준다. 예를 들어, "Main*"의 페이지 대상은 "MainPage", "MainStreet" 그리고 "MainWelcome" 등이다. 와일드카드 "*"는 위키에 있는 모든 페이지를 의미한다. GroupPermissions도 같은 구문을 사용하며, 와일드카드는 "모든 그룹"을 의미한다. 아래는 두 개의 와일드카드 예제이다:permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:Main*", "edit"; permission com.ecyrd.jspwiki.auth.permissions.GroupPermission "*:*Test", "edit";PagePermission은 모든 위키의 "Main"으로 시작하는 모든 페이지에 적용된다. GroupPermission은 모든 위키의 "Test"로 끝나는 모든 그룹에 적용된다.
와일드카드 (*)는 대상의 첫번째 글자 또는 마지막 글자여야 한다. 다중 와일드카드 또는 대상 문자열의 중간에 위치하는 와일드카드는 현재 지원하지 않는다. 따라서, 페이지 대상 *UserPages* 그리고 Andy*Page는 잘못된 것이다.
WikiPermission과 AllPermisson은 또한 대상으로 와일드카드 캐릭터를 허용한다. 그것은 곧 "모든 위키"를 의미한다.
퍼미션 포함 관계#
몇몇 퍼미션은 다른 퍼미션을 포함한다:- "modify" 퍼미션은 "edit"와 "upload"
- "edit" PagePermission은 "view"와 "comment"
- "upload" PagePermission은 "view"
- "delete" PagePermission은 "edit"
- "createGroups" WikiPermission은 "createPages"
- "edit" GroupPermission은 "view"
- "delete" GroupPermission"은 "edit"와 "view"
- 특정한 위키를 위한 "AllPermission"은 그 위키에 대한 모든 PagePermissions과 WikiPermissions
정책 블록에 당사자 정의하기#
앞서 언급했듯이, 정책 파일에 있는 각각의 "grant" 블럭은 특정한 역할에 대한 권한을 부여한다. grant 문장에 principal type "principalName" 부분에서 역할을 명시한다. type은 java.security.Principal 인터페이스를 구현한 모든 클래스가 될 수 있다. 표준 JSPWiki 역할에서 이 Principal 타입은 com.ecyrd.jspwiki.auth.authorize.Role이다. 이 principalName은 principal 타입의 getName() 메소드가 리턴하는 임의의 값이 될 수 있다. JSPWiki는 역할과 관련해서 다음의 표준 이름을 포함하고 있다:- "Anonymous"
- "Asserted"
- "Authenticated"
- "All"
JSPWiki의 보안 정책은 권한을 위키 그룹에 부여할 수 있다. GroupPrincipal 타입을 사용하여 정책 파일에서 특정한 위키 그룹을 구분할 수 있다. 따라서, "SocialCommittee" 위키 그룹은 GroupPrincipal "SocialCommittee"과 관련하여 아래와 같이 정의된다:
grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.GroupPrincipal "SocialCommittee" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:Group*", "edit";
};
JSPWiki의 보안 정채은 또한 웹 콘테이너와 같은 외부 인가자가 리턴한 역할에 권한을 부여할 수 있다. 이 정책 파일에서 외부 역할은 빌트인 역할인 com.ecyrd.jspwiki.auth.authorize.Role과 동일한 Principal 타입을 사용하여 구분된다. 따라서, "ContainerAdmin"라 불리는 콘테이너 역할과 Role "ContainerAdmin"를 일치시키려면 다음과 같이 한다:
grant signedBy "jspwiki",
principal com.ecyrd.jspwiki.auth.authorize.Role "ContainerAdmin" {
permission com.ecyrd.jspwiki.auth.permissions.AllPermission "JSPWiki";
};
물론, 권한을 특정한 사용자에게 허용할 수 있다. 블럭에서 이름을 붙인 principal은 사용자 위키 이름, 전체 이름 또는 로그인 이름과 대응해야 한다. 예를 들어, 이름이 "Janne"인 사용자에게 기본 수정 권한을 부여하는 정책 블럭의 예제는 아래와 같다:
grant signedBy "jspwiki",
principal "Janne" {
permission com.ecyrd.jspwiki.auth.permissions.PagePermission "*:*", "edit";
};
정책 파일의 개별 사용자를 명시하는 것은 피하라. 대신 특정한 역할(위키 그룹, 빌트인 역할 또는 외부 역할)을 명시하는 것이 더 좋다.
커스텀 정책 구현하기#
시작할 때에, JSPWiki는 시스템 프로퍼티 java.security.policy가 설정되었는 여부를 검사해서 사용자가 미리 정의한 보안 정책을 가졌는지를 확인한다. 대부분의 경우, 커스텀 보안 정책은 로딩되지 않으며, JSPWiki는 WEB-INF/jspwiki.policy로부터 기본 정책을 로딩할 것이다.하지만, 경우에 따라서 관리자는 자신의 자바 보안 정책을 사용하거나 또는 JSPWiki의 기본 보안 정책을 커스터마이징 하길 원할 수도 있다. 이런 경우에, 웹 콘테이너를 시작할 때 명령행 인자에 java.security.policy 시스템 프로퍼티를 설정해주어야 한다. 파일 위치는 jspwiki.policy 파일에 대한 절대 경로이거나 그것을 호출하기 위해 정의한 것이어야 한다. 예를 들면 아래와 같다:
java -jar myservletcontainer.jar -Djava.security.policy=/etc/jspwiki.policy
몇몇 서블릿 콘테이너는 환경 변수를 찾아서 java 명령어에 내용을 추가하는 것이 쉽다. 예를 들어, 톰캣 사용하자는 단순히 CATALINA_OPTS 변수에 추가해주기만 하면 된다:
export CATALINA_OPTS="-Djava.security.policy=/path-to/jspwiki.policy"
보안이 중요한 환경에서 $CATALINA_HOME/conf와 같은 JSPWiki와는 별도 디렉토리에 {jspwiki.policy}를 저장해야 한다.
노트: JSPWiki는 커스텀 보안 Permission 클래스를 정의하고 있다. JVM이 보안 정책 결정 때 이클래스를 사용하도록 하려면, jspwiki.jar 파일을 jspwiki라는 alias를 가진 디지털 인증을 이용하여 사인해야 한다. 이 인증을 포함하고 있는 키스토어 jspwiki.jks 파일은 보안 파일과 같은 디렉토리에 위치해야 하며, 기본 위치는 /WEB-INF 이다. 만약 JSPWiki를 소스 코드로부터 빌드 한다면, Ant 빌드 스크립트를 사용해서 인증서와 키스토어를 생성할 수 있다. 만약 JSPWiki 보안 정책 파일이 관련 키스토어를 어디서 찾을 수 있는 지 알아내지 못한다면, JSPWiki는 작동을 멈출 것이다. 따라서, jspwiki.jks 키스토어를 보안 정책 파일과 같은 디렉토리에 위치시키는 것에 유의해야 한다._
인증 과정 커스터마이징#
인증이 동작하는 방식#
JSPWiki는 위키 사용자의 로그인/로그아웃 처리를 위해 JAAS(Java Authentication and Authorization Service)를 사용한다. JAAS는 개념적으로는 PAM과 유사한다. (PAM은 리눅스, 솔라리스 그리고 기타 다른 OS를 위한 "쌓아나갈 수 있는(stackable)" 인증 프레임워크이다.)JSPWiki는 WikiSession을 사용하여 각 사용자를 추적한다. WikiSession은 HttpSession과 유사하며 관련되어 있다. 사용자가 임의 사용자에서 asserted 상태로 변할 때, 그리고 authenticated 상태로 변할 때, WikiSession 객체는 지속적으로 유지된다. 하지만, 사용자의 로그인 상태에 따라 관련 사용자의 자격은 변경된다.
특히, 각 사용자의 WikiSession은 자격 목록을 갖고 있는 표준 J2SE Subject를 포함하고 있다. Principal은 다음의 네 가지 중 하나가 될 수 있다:
- User Principals, 커스텀 또는 콘테이너 JAAS LoginModule이 제공되며 한 개 이상의 사용자 Principal을 표현
- Built-in Role Principals, "authenticated","anonymous", "asserted", "all"의 논리 Role 객체를 표현
- External Role Principals, 웹 콘테이너와 같은 외부의 인가자로부터 생성된 논리적 Role 객체를 표현
- Group Principals, 사용자가 속한 위키 그룹을 표현
그렇다면 어떻게 Principal을 구하게 될까? 쉽다 --- JAAS. JSPWiki는 콘테이너 방식 인증이나 위키 자신의 커스텀 인증 방식을 사용할 수 있다는 것을 기억할 것이다. 기본 인증 "스택"은 각 경우에 따라 약간 다르게 동작한다:
- 콘테이너 인증. WebContainerLoginModule이 먼저 HTTP 요청의 Principal을 검사함으로써 "로그인" 시도를 한다. 만약 로그인 되었다면 그 Principal을 사용하고 그 Principal과 두 개의 역할인 "All"과 "Authenticated"를 추가한다. 만약 그렇지 않다면, RemoteUser 프로퍼티를 시도하고 종합적인 사용자 Principal과 "All" 및 "Authenticated" 역할을 지정한다. 이 두가지 방식 모두 성공하지 못했다면(아마도 아직 로그인을 하지 않았기 때문일 것이다), (CookieAssertionLoginModule를 사용하여 쿠키가 발견되면) asserted 사용자로 지정하거나 또는 (쿠키가 없다면) anonymous 사용자로 지정할 것이다. 이 경우 사용자의 역할 자격은 "All" 그리고 "Asserted" 또는 "Anonymous"가 된다. 만약 다른 모듈이 실패하면, 마지막으로 AnonymousLoginModule이 항상 성공하게 된다.
- 커스텀 인증. 이 경우, UserDatabaseLoginModule은 로그인 폼((Login.jsp))에서 전송한 데이터를 사용하여 설정된 UserDatabase를 통해 인증을 수행한다. 기본적으로 사용자 데이터베이스는 XML 파일에 저장된다. 만약 로그인에 성공한다면, 사용자는 사용자의 로그인 이름, 전체 이름 그리고 위키 이름을 표현하는 세 개의 사용자 자격을 갖게 된다. (유연함을 위해, ACL에 높은 정확성을 요규하지 않는다.) 또한, 빌트인 역할인 "All"과 "Authenticated"를 추가한다.
위에서 설명한 과정은 사용자에게는 보여지지 않으며 내부적으로 발생한다. 중요한 점은 WikiSession은 항상 허가 목적으로 사용될 수 있는 몇 개의 빌트인 역할을 포함하는 주체를 갖는다는 것이다. 특히, WikiSession의 주체는 항상 사용자의 아이덴티티를 표현할 수 있는 최소한 한 개의 사용자 자격(Principal)을 포함하고 있으며, 적어도 두개의 빌트인 역할 자격("All" 그리고 "Anonymous", "Asserted" 또는 "Authenticated" 중 하나)을 포함한다는 것이다. 주체는 또한 사용자가 속한 위키 그룹에 해당하는 GroupPrincipal 객체를 포함할 수 있고, 외부 인가자로부터 발생한 각각의 역할을 위한 Role 객체를 포함할 수 있다.
JSPWiki의 JAAS 설정 커스터마이징#
일반적으로는 기본 로그인 과정만으로도 충분하다. 하지만, JSPWiki는 JAAS를 사용하기 때문에, 원하는 대로 로그인 과정을 설정할 수 있다. 아래는 jspwiki.jaas 파일의 기본 설정이다. 이 파일은 기본적으로 WEB-INF 디렉토리에서 로딩한다:JSPWiki-container {
com.ecyrd.jspwiki.auth.login.WebContainerLoginModule SUFFICIENT;
com.ecyrd.jspwiki.auth.login.CookieAssertionLoginModule SUFFICIENT;
com.ecyrd.jspwiki.auth.login.AnonymousLoginModule SUFFICIENT;
};
JSPWiki-custom {
com.ecyrd.jspwiki.auth.login.UserDatabaseLoginModule REQUIRED;
};
첫번째 블록(JSPWiki-Container)은 WikiContext가 생성되는 동안 인증 과정이 어떻게 호출되는 지를 보여준다. 만약 사용자가 아직 인증되지 않았다면, JSPWiki는 WebContainerLoginModule, CookieAssertionLoginModule, 그리고 AnonymousLoginModule을 차례대로 사용하여 사용자의 로그인을 시도한다. 첫번째 모듈이 성공하면 WikiSession의 Principal 자격을 갖는 Subject를 생성시킨다. 이 블럭을 변경하면 기본 로그인 과정을 수정할 수 있다. 예를 들어, CookieAssertionLoginModule을 제거하면 웹 브라우저 쿠키를 사용하여 사용자가 asserted 역할을 갖는 것을 금지할 수 있다. AnonymousLoginModule 부분은 없애지 않는 것이 좋다. AnonymousLoginModule은 인증되지 않은 세션이 적어도 "Anonymous" 자격을 갖는 것을 보장한다. 만약 콘테이너 인증을 사용한다면, WebContainerLoginModule 부분을 포함해야 한다. (그렇게 하지 않더라도 단지 동작하지 않는 것이기 때문에 문제는 되지 않는다.)
두번째 블록(JSP-custom)은 커스텀 인증을 위해 JSPWiki가 UserDatabase를 사용할지의 여부를 지정한다. 쉽게 이것을 다른 JAAS LoginModule로 교체할 수 있다. 예를 들어, Sun JDK는 Kerberos LoginModule과 네이티브 OS LoginModule을 포함하고 있다 (유닉스 배포판은 PAM을 사용하고 윈도우즈 배포판은 로컬 SAM을 사용한다.)
JAAS 설정을 커스터마이징하려면 별도 파일에 새로운 설정을 저장해야 한다. JSPWiki에 JVM 시스템 프로퍼티인 java.security.auth.login.config를 사용하여 이 설정 파일이 어디에 위치하는 지를 설정해주어야 한다:
java -jar myservletcontainer.jar -Djava.security.auth.login.config==/etc/jspwiki.jaas
커스텀 보안 정책 설정과 마찬가지로, 웹 콘테이너는 구동시에 JAAS 프로퍼티를 설정하는 것이 좋다. 톰캣의 경우 단지 CATALINA_OPTS 시스템 프로퍼티에 추가해주기만 하면 쉽게 설정할 수 있다:
export CATALINA_OPTS="-Djava.security.auth.login.config==/etc/jspwiki.jaas"
보안이 중요한 환경인 경우 jspwiki.jaas 파일을 $CATALINA_HOME/conf와 같이 JSPWiki와 상관없는 디렉토리에 저장해야 한다.
노트: 웹 콘테이너가 JAAS를 사용하는 또 다른 어플리케이션을 실행중이라면, 기존에 존재하는 JAAS 설정 파일에 jspwiki.jaas의 내용을 추가해주어야 한다.
JBoss 사용자를 위한 노트: JBoss는 특별한 JAAS 설정 파일 포맷을 사용한다. 서버의 login-config.xml 파일(기본적으로 server/default/conf/login-config.xml 디렉토리에 위치)에 다음과 같이 추가하면 된다:
<application-policy name="JSPWiki-container">
<authentication>
<login-module code="com.ecyrd.jspwiki.auth.login.WebContainerLoginModule"
flag="sufficient"/>
<login-module code="com.ecyrd.jspwiki.auth.login.CookieAssertionLoginModule"
flag="sufficient"/>
<login-module code="com.ecyrd.jspwiki.auth.login.AnonymousLoginModule"
flag="sufficient"/>
</authentication>
</application-policy>
<application-policy name="JSPWiki-custom">
<authentication>
<login-module code="com.ecyrd.jspwiki.auth.login.UserDatabaseLoginModule"
flag="required"/>
</authentication>
</application-policy>
콘테이너 인증 방식과 통합하기#
기본적으로 JSPWiki는 커스텀 인증을 사용하여 사용자 로그인을 처리한다. 즉, 설정된 UserDatabase에 저장된 사용자 아이디와 암호를 사용하는 것이다. 하지만, 많은 기업은 콘테이너 관리 인증을 사용하는 것을 선호한다. 이것은 JSPWiki가 웹 콘테이너 realm로부터 구한 자격을 사용할 수 있도록 한다. 콘테이너의 realm 설정에 따라, JSPWiki가 사용가능한 인증 방법을 폭넓게 해줄 수 있다. 많은 콘테이너는 LDAP, 데이터베이스, Kerberos, SecurID, Shibboleth, SAML 그리고 NT 도메인 컨트롤러 인증 등을 지원하고 있다.매우 간단한 설정으로 JSPWiki는 콘테이너 인증을 사용할 수 있다. 먼저, 웹 콘테이너가 JSPWiki 웹 어플리케이션을 위한 보안 realm을 사용하도록 설정한다. 예를 들어, 톰캣의 경우 <realm> 요소를 사용하여 특정한 웹 어플리케이션(또는 콘테이너 전체)에 콘테이너 인증을 설정할 수 있다. 아래 코드는 MySQL relam 설정의 예제이다:
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost/authority"
connectionName="test" connectionPassword="test"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name" />
WebSphere, WebLogic, JBoss 등의 다른 콘테이너는 다른 방식으로 realm을 설정하지만 방법은 비슷하다.
JSPWiki 웹 어플리케이션을 위한 보안 realm을 설정한 다음에, WEB-INF/web.xml 파일에 있는 <security-constraint> 요소의 주석 처리를 제거한다:
<!-- REMOVE ME TO ENABLE CONTAINER-MANAGED AUTH
<security-constraint>
<web-resource-collection>
<web-resource-name>Administrative Area</web-resource-name>
<url-pattern>/Delete.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Authenticated area</web-resource-name>
<url-pattern>/Edit.jsp</url-pattern>
<url-pattern>/Comment.jsp</url-pattern>
<url-pattern>/Login.jsp</url-pattern>
<url-pattern>/NewGroup.jsp</url-pattern>
<url-pattern>/Rename.jsp</url-pattern>
<url-pattern>/Upload.jsp</url-pattern>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>HEAD</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
...
<security-role>
<description>
This logical role includes all authenticated users
</description>
<role-name>Authenticated</role-name>
</security-role>
<security-role>
<description>
This logical role includes all administrative users
</description>
<role-name>Admin</role-name>
</security-role>
REMOVE ME TO ENABLE CONTAINER-MANAGED AUTH -->
노트: 2.3.74 이전 버전의 경우 이 파일의 내용이 약간 다르다.
JSPWiki가 시작할 때, JSPWiki의 웹 어플리케이션 배치 파일(WEB-INF/web.xml)을 파싱하고 특정한 제약 조건이 존재하는 지 판별한다. 특히, /Delete.jsp와 Login.jsp에 접근할 때 논리적인 역할이 필요한지 여부를 확인한다. 만약 <security-constraint> 블럭의 주석 처리를 제거했다면, 논리적 역할이 필요할 것이고 jspwIKI는 커스텀 인증 대신에 콘테이너 인증을 사용하게 될 것이다.
web.xml에 기술되어 있는 기본 콘테이너 방식의 보안 제약 조건은 사용자가 페이지를 수정하고, 파일을 업로드 하고, 페이지에 커멘트를 달고, 새로운 그룹을 만들고 또는 프로파일을 수정할 때 사용자가 로그인 하도록 한다. 이것은 충분히 제한적이고, 기본 보안 정책보다 다시 엄격하다. 대부분의 인트라넷 환경과 위키에서는 충분한 설정이다. 필요하다면 제약 조건을 강화할 수 있다.
콘테이너 인증을 사용할 때, <role-name>의 값은 중요하며, 웹 콘테이너의 보안 realm으로부터 구한 역할 이름과 일치해야 한다. 기본 설정이 올바르게 동작하려면, "Admin" 그리고/또는 "Authenticated" 역할을 추가하여 로그인할 때 웹 콘테이너가 알맞게 역할을 할당할 수 있도록 해야 한다.
예를 들어, 톰캣에 빌트인 되어 있는 "Memory Realm"을 사용하는 경우, $CATALINA_HOME/conf/tomcat-users.xml 파일을 수정해서 원하는 실제 사용자 계정을 추가해주어야 한다. 각각의 사용자는 Admin 또는 Authenticated의 역할 중 하나 또는 두가지를 소유해야만 한다. 다른 realm 타입에 대한 내용은 웹 콘테이너 문서를 참고하기 바란다.
다른 방법으로, "Authenticated"와 "Admin"에 대한 모든 참조를 웹 콘테이너의 보안 realm이 리턴한 역할과 일치하는 역할 이름으로 교체할 수도 있다. JSPWiki는 역할 이름이 일치하는 한 어떤 방식을 사용해도 문제되지 않는다.
또한, 보호될 자원에 접근할 경우 웹 세션을 보호하기 위해 SSL을 사용할 수도 있다. 물론, 웹 콘테이너(또는 웹 서버)가 SSL을 지원하도록 설정한 경우에 해당한다. 만약 SSL을 사용하길 원하지 않는다면 <user-data-constraint> 요소를 제거하면 된다.
- 경고: 콘테이너 인증을 사용할 때, 2.3.x 버전은 사용자가 브라우저가 쿠키를 허용하도록 설정할 것을 필요로 한다. 이렇게 함으로써 웹 콘테이너가 주로 JSESSIONID 쿠키를 사용해서 세션 식별자를 설정할 수 있게 된다.
아이덴티티 관리 커스터마이징#
JSPWiki는 "사용자 데이터베이스"라고 불리는 저장소를 사용하여 위키 멤버와 관련된 식별 정보를 저장한다. 사용자의 아이덴티티는 사용자 프로파일에 저장된다. 사용자 프로파일은 사용자의 로그인 이름, 전체 이름, 위키 이름, 이메일 주소 등의 정보를 포함한다. 만약 (콘테이너 인증 방식 대신에) JSPWiki의 커스텀 인증 방식을 사용한다면, 사용자 프로파일은 사용자 암호를 포함한다. 로그인 이름은 유일한 식별자로서 JSPWiki 식별자와 콘테이너가 관리하는 식별자에 연결한다.특별히, JSPWiki는 사용자 프로파일을 저장하기 위해 표준 UserDatabase 구현체인 com.ecyrd.jspwiki.auth.user.XMLUserDatabase를 사용한다. 이는 워크 그룹이나 작은 규모의 공개 위키에는 충분하다. 기본으로, JSPWiki는 WEB-INF/에 위치한 userdatabase.xml 파일을 사용자 프로파일 저장소로 사용한다. jspwiki.properties 파일의 jspwiki.xmlUserDatabaseFile 수정해서 사용자 프로파일을 저장할 파일의 경로를 수정할 수 있다. 파일의 경로는 /etc와 같이 웹 어플리케이션 밖에 위치할 수도 있다.
기본 XML 구현체 뿐만 아니라, 2.3.33 또는 그 이상의 버전은 RDBMS에 사용자 프로파일을 저장할 수 있다. 구현 클래스는 JDBCUserDatabase 이다. JDBC 사용자 데이터베이스의 특징은 다음과 같다:
- JNDI 기반의 DataSource 탐색 (콘테이너가 제공하는 커넥션 풀이 적당하다; 이렇게 하면 JSPWiki는 데이터베이스 암호를 알 필요가 없다)
- 모든 JDBC 데이터베이스를 지원
- 커스터마이징이 가능한 테이블과 컬럼 이름
- PreparedStatement의 사용 (예를 들어., SQL 인젝션 공격에 안전하다)
- JDBC 사용자 테이블을 생성하는 스크립트 예제 포함(현재는 McKoi와 PostgreSQL, MySQL은 예정...)
JDBCUserDatabase를 사용하기 위해서, jspwiki.properties에 구현 클래스를 명시해주어야 한다:
jspwiki.userdatabase = com.ecyrd.jspwiki.auth.user.JDBCUserDatabase또한, DataSource를 찾기 위한 정보와 사용자 정보를 찾고 저장할 때 사용할 테이블 이름과 컬럼 이름을 jspwiki.properties에 추가해주어야 한다. 또한, JDBC 드라이버를 서블릿 콘테이너의 클래스패스에 설치해야 한다. 예를 들어, 톰캣 4/톰캣 5 버전에서 MySQL을 사용한다면 MySQL JDBC 드라이버 jar 파일을 CATALINA_HOME/common/lib directory에 복사해주어야 한다.
보다 자세한 내용은 jspwiki.properties 파일과 com.ecyrd.jspwiki.auth.user.JDBCUserDatabase의 API 문서를 참고하기 바란다.
이 두가지 방법으로 원하는 것을 할 수 없다면, 여러분 스스로 직접 구현체를 구현할 수 있다. com.ecyrd.jspwiki.user.UserDatabase 인터페이스는 사용자 프로파일을 로딩하고 저장하고, 검색하는 메소드를 정의하고 있다. 만약 여러분 자신의 사용자 데이터베이스를 갖고 있다면, jspwiki.properties 클래스에 구현체를 직접 명시해주면 된다:
jspwiki.userdatabase = com.example.wiki.MyLDAPUserDatabase
권한 부여 과정을 커스터마이징하기#
권한 부여가 동작하는 방식#
내부적으로, JSP 권한 부여 알고리즘은 1) 사용자가 소유한 Principal을 검사, 2) 사용자가 외부 역할이나 위키 그룹에 속했는 지의 여부를 바탕으로 접근을 허용한다. anonymous 사용자도 "Anonymous" 역할을 소유하기 때문에 이들 사용자도 권한 부여 체크에 대상이 된다.접근을 위한 요청은 무엇으로 구성되어 있는가? 퍼미션을 요구하는 모든 기능을 수행하기 전에 호출된 JSP나 자바 코드는 AuthorizationManager의 checkPermission 메소드를 호출하여 권한 검사를 수행한다. 이 메소드에 파라미터로 Permission 객체가 전달되는데, Permission 객체는 PagePermission (페이지 레벨의 기능) 이거나 WikiPermission (프로파일 생성, 그룹 생성, 페이지 작성 등 위키 레빌의 기능) 이다.
권한 부여 과정은 Permission이 WikiSession과 관련된 주체에 허용되었는지를 검사하는 것이다. Permission 검사 알고리즘은 다음과 같다:
- 주체의 Principal 집합이 AllPermission이 허용된 GroupPrincipal, 역할 또는 사용자 Principal을 포함하고 있다면, 해당 Permission은 항상 허용된다. 따라서 administrator는 모든 것을 할 수 있다.
- 모든 퍼미션에 대해, Permission이 기본 보안 정책에 따라 허용되는 지 검사한다. 그렇지 않다면 퍼미션을 거부하고 진행을 멈춘다.
- ACL을 가진 페이지의 경우, ACL에 이 퍼미션이 할당된 Principal 목록(역할, 위키 그룹, 또는 사용자)을 구한다. 그런 뒤, 주체가 이들 역할이나 Principal 중 한가지를 가졌는 지 검사한다. 이 과정은 다음과 같다:
- 만약 ACL에 있는 Principal이 빌트인 역할이라면, 알고리즘은 단순히 주체가 해당 역할을 소유하고 있는 지 검사한다.
- 만약 ACL에 있는 Principal이 역할이지만 빌트인 역할이 아닌 경우라면, 외부 인가자의 isInRole 메소드를 호출한다.
- 만약 ACL에 있는 Principal이 위키 그룹이라면, 알고리즘은 주체가 해당하는 GroupPrincipal을 소유하고 있는 지 검사한다.
- 만약 ACL에 있는 Principal이 사용자라면, 주체가 해당 사용자인지 검사한다.
- 그렇지 않을 경우 퍼미션을 거부한다.
정리하면, 이 알고리즘은 "Authenticated"와 "All" 등 빌트인 역할, 또한 외부 인가자의 (웹 콘테이너가 제공하는 것 같은) 그룹과 임의 사용자, 그리고 임의의 위키 그룹을 사용하는 방법을 제공한다. 따라서, 인증 및 권한 부여를 위해 웹 콘테이너를 외부의 LDAP 서버와 연동하고 싶다면, 그렇게 할 수 있다. 그리고 여러분 자신만의 위키 그룹을 만드록 싶다면 역시 그렇게 할 수 있다.
앞에서 업근했듯이, ACL은 정책에서 이미 허용한 것 이상의 권한을 부여하지 못한다. 예를 들어, anonymous 사용자가 모든 페이지를 읽을 수 있지만 수정할 수 없다고 보안 정책에서 정의했다면, Main 페이지의 ACL에서 anonymous 사용자에게 Edit 권한을 부여하더라도 동작하지 않는다.
외부 인가자에 의뢰하기#
권한 부여 알고리즘은 빌트인 역할 Pricipal과 사용자 Principal에 특정한 Principal이 존재하는지의 여부를 검사한다. 권한 부여 알고리즘은 또한 외부 인가자에 의해 결정된 역할에 있는 멤버십이나 위키 그룹 멤버에 기반하여 결정할 수도 있다.인가자 인터페이스(com.ecyrd.jspwiki.auth.Authorizer)는 외부 인가자에 의뢰하는 메소드를 정의하고 있다. RDBMS 인가자나 LDAP과 같은 것을 사용하고 싶은 손쉽게 자신만의 구현체를 작성할 수 있다. 커스텀 인가자를 구현했다면, jspwiki.properties 파일에 다음과 같이 구현 클래스를 설정해주어야 한다:
jspwiki.authorizer = com.example.wiki.MyRDBMSAuthorizer
JSPWiki의 기본 인가자는 com.ecyrd.jspwiki.auth.authorize.WebContainerAuthorizer이며, 이 인가자는 HttpRequest의 isUserInRole(String) 메소드를 사용하여 웹 콘테이너에게 인가 요청을 전달한다.
(com.ecyrd.jspwiki.auth.authorize.GroupManager) 인터페이스는 Authorizer를 상속받고 있으며, 그룹 멤버 목록을 조회하고 저장하는데 필요한 메소드를 추가로 정의하고 있다. GroupManager는 백엔드 GroupDatabase 클래스와 동작한다. GroupDatabase의 기본 구현체(com.ecyrd.jspwiki.auth.authorize.XMLGroupDatabase)는 WEB-INF 디렉토리에 저장되어 있는 groupdatabase.xml 파일로부터 멤버 목록을 읽어오고 저장한다. 커스텀 GroupDatabase를 구현할 수 있으며, jspwiki.properties 파일에 구현 클래스를 명시해주면 된다:
jspwiki.groupdatabase = com.example.wiki.MyRDBMSGroupDatabase
Authorizer와 GroupManager/GroupDatabase의 차이점은 무엇일까? 이들은 사용자가 특정한 역할을 소유했는지의 여부에 따라 기능에 대한 권한을 부여한다는 점에서 비슷한 기능을 제공한다. 차이점은 GroupManager는 위키 그룹 저장소를 위해 설계되었다는 점이다. GroupDatabase과 함께 동작하여 사용자가 스스로 생성할 수 있는 임의의 역할을 관리하고 저장하고 로딩한다. 반면에 Authorizer는 일반적으로 IT 관리자가 제어하는 인프라를 통해 제공되는 백엔드 서비스이다. 외부 Authorizer는 새로운 역할을 생성하는 기능을 제공하지 않는다. 단지 사용자가 이미 정의되어 있는 역할에 포함되어 있는 지를 검사하는 기능을 제공할 뿐이다. 이 두 가비 방법의 경계를 명확하게 구분해야 한다.
이런 접근 방식의 장점은 매우 유연하게 권한 부여를 제공할 수 있다는 점이다. 이는 GroupManager/GroupDatabase와 더불어 웹 콘테이너의 인증 API의 장점을 갖는 외부 Authorizer를 함께 사용할 수 있다는 것을 의미한다.
CategoryDocumentation, CategoryKoreanDocumentation
이 페이지에 질문을 등록하지 말고, Security 2.3 FAQ 페이지를 사용하기 바란다.