보안 시스템 설정

본 장에서는 JEUS에서 핵심적인 보안 시스템을 실제로 어떻게 설치하고 설정하는지를 설명한다. 설명한 서비스 이외의 서비스를 도메인에 설정하는 방법은 참고 자료를 참고한다.

1. 개요

본 절에서는 보안 시스템 설정과 관련된 기본적인 사항들을 간단하게 설명한다.

JEUS의 보안 시스템은 Security Installer를 통해 서버를 실행할 때 시작된다. Security Installer는 domain.xml에 정의된 정보를 바탕으로 보안 도메인을 만들고 보안 서비스를 시작하여 JEUS를 안전하게 보호한다. 디폴트 보안 시스템에서는 accounts.xml과 policies.xml에 정의된 사용자 계정과 보안 정책이 적용된다.

보안 도메인에 대해 다음의 2가지를 설정할 수 있다.

  • 보안 도메인과 보안 서비스에 대한 정의

  • 해당 도메인에 대한 계정 및 정책 설정

디폴트 보안 시스템의 설정 과정은 다음과 같다.

  1. 보안 도메인들을 설정한다.

  2. 각 보안 도메인별로 구성요소와 보안 서비스를 설정한다.

  3. 각 도메인에 대한 Subjects(인증 데이터)의 사용자 정보를 설정한다.

  4. 각 도메인에 대한 Policies(보안 정책 데이터)를 설정한다.

  5. Subject와 Policy 이외의 추가 사항을 설정한다.

  6. Java SE SecurityManager를 설정한다(선택적).

  7. JACC Provider를 설정한다(선택적).

디폴트 보안 시스템 디렉터리

다음은 디폴트 보안 시스템의 디렉터리 구조이다. 각 디렉터리에는 보안 시스템에서 사용하는 설정 파일들이 나열되어 있다.

JEUS_HOME/domains/<domain name>
   |--config
        |--security
            |--security.key
            |--policy
            |--security-domains.xml
            |--SYSTEM_DOMAIN
                  |--accounts.xml
                  |--policies.xml
security

다음은 각 디렉터리 및 파일에 대한 설명이다.

구분 설명

security.key

대칭키 암호화 알고리듬의 Key를 저장하는 파일이다. 최초로 암호화를 수행하면 파일이 생성된다.

policy

Java Permission 설정 파일이다. JEUS의 보안 시스템과는 별도로 Java SE Security Manager에서 사용된다.

security-domains.xml

JEUS의 보안 도메인에 대한 설정을 저장하는 파일이다.

SYSTEM_DOMAIN

JEUS 서버가 사용자 인증과 권한 체크를 위해 사용하는 도메인이다. 이 도메인은 JEUS를 기동하고, 종료하는 등의 Permission들과 JEUS 시스템 administrator 계정을 포함하고 있다.

  • accounts.xml : 사용자 정보가 저장된다.

  • policies.xml : 보안 정책 정보(권한 부여 데이터)가 저장된다.

애플리케이션에 JEUS 시스템과 다른 보안정책을 적용하려면 별도의 보안 도메인 디렉터리를 생성하고 관련 설정을 적용한 뒤 사용해야 한다.

2. 보안 도메인 설정

보안 도메인을 설정하기 위해서는 domain.xml 및 security-domains.xml을 직접 편집해야 한다. 사용자 계정 설정과 보안 정책 설정을 제외한 나머지 사항은 동적 변경이 불가능하다. 따라서 보안 도메인을 추가하거나, 보안 서비스 설정 등을 수정했을 경우 서버를 재부팅해야 수정된 사항이 적용됨에 유의한다.

보안과 관련된 모든 설정은 JEUS 도메인에 속한 모든 서버에 동일하게 적용된다. 따라서 사용자 계정 설정과 보안 정책 설정을 제외하고는 동작하고 있는 모든 서버를 재부팅해야 보안 설정 적용이 가능하다.

본 절에서는 XML 편집을 통해 보안 도메인을 정의하는 방법에 대해 설명한다.

2.1. XML 편집 설정

XML을 직접 편집하려면 JEUS_HOME/domains/<domain name>/config/domain.xml 및 JEUS_HOME/domains/<domain name>/config/security/security-domains.xml 내의 다음 태그를 이용하여 설정한다.

도메인에 대한 XML 파일 설정 방법은 JEUS_HOME/lib/schemas/jeus/supportLocale/ko 디렉터리 내의 jeus-domain.xsd와 jeus-security.xsd, security-domains.xsd 의 XML 스키마에 정의되어 있다. 상위 태그는 <security-manager>이며, 이 태그는 도메인 설정과 관련된 다음 하위 태그를 가진다. 하위 태그는 0개 이상씩 설정 가능하다.

보안 도메인 설정 : <domain.xml>
<security-manager>
   <default-application-domain>SYSTEM_DOMAIN</default-application-domain>
   <security-domain-names>
     <security-domain-name>SYSTEM_DOMAIN</security-domain-name>
     ...
   </security-domain-names>
</security-manager>

다음은 설정 태그에 대한 설명이다.

  • <security-manager>

    JEUS에 등록할 보안 도메인들을 설정한다. <security-manager>에 대한 보안 설정 파일의 예제는 보안 도메인 구성요소 설정을 참고한다.

    태그 설명

    <connect-retries>

    JEUS Security NetworkService에서 connection retry count 값을 정의한다.

    (기본값: 10)

    <password-validator>

    JEUS 계정의 암호를 지정할 때, 암호의 보안성을 높이기 위하여 암호 적합성 검사를 설정한다.

    <default-application-domain>

    Jakarta EE 애플리케이션에서 사용할 기본 보안 도메인의 이름을 정의한다.

    (기본값: SYSTEM_DOMAIN)

  • <security-domain-names>

    JEUS에서 사용할 보안 도메인들의 이름을 지정한다.

    태그 설명

    <security-domain-name>

    Security 도메인 이름을 설정한다. Security 도메인 설정에서 name 값을 참조한 값이다.

보안 도메인 설정 : <security-domains.xml>
<security-domains>
   <security-domain>
      <name>SYSTEM_DOMAIN</name>
      <authentication />
      <authorization />
      ...
   </security-domain>
</security-domains>

다음은 설정 태그에 대한 설명이다.

  • <security-domain>

    JEUS에 등록할 보안 도메인들을 설정한다. <security-domain>에 대한 보안 설정 파일의 예제는 보안 도메인 구성요소 설정을 참고한다.

    태그 설명

    <name>

    Security 도메인 이름을 설정한다.

    <authentication>

    Authentication 서비스를 정의한다.

    <authorization>

    Authorization 서비스를 정의한다.

    <identity-assertion>

    Identity Assertion 서비스를 정의한다.

    <credential-mapping>

    Credential Mapping 서비스를 정의한다.

    <credential-verification>

    Credential Verification 서비스를 정의한다.

    <audit>

    Audit 서비스를 정의한다.

    <subject-validation>

    Subject Validation 서비스를 정의한다.

2.2. 사용자 계정 및 보안 정책 설정

본 절에서 설명은 디폴트로 제공되는 XML을 이용한 설정에 대해 설명한다.

사용자 계정 및 보안 정책 설정은 XML뿐만 아니라 데이터베이스에 사용자 계정 정보와 보안 정책 정보를 저장하여 사용하는 것도 가능하며, 이에 대한 자세한 내용은 사용자 정보 설정에 대한 데이터베이스 사용 설정과 보안 정책 설정에 대한 데이터베이스 사용 설정을 참고한다.

다음은 사용자 계정 및 보안 정책을 설정하는 과정에 대한 설명이다.

  1. 새로운 보안 도메인을 설정하려면 JEUS_HOME/domains/<domain name>/config/security 아래에 새로운 디렉터리를 생성해야 한다. 디렉터리 이름은 생성하려는 보안 도메인 이름과 일치해야 한다. 일반적으로 보안 도메인 이름은 모두 대문자로 쓰고 "_DOMAIN"으로 끝맺는다. 예를 들면 "DEFAULT_APPLICATION_DOMAIN"으로 명명할 수 있다.

    DEFAULT_APPLICATION_DOMAIN 도메인을 생성하기 위해 명령 프롬프트에서 다음 명령어를 실행한다.

    $ mkdir ${JEUS_HOME}/domains/domain1/config/security/DEFAULT_APPLICATION_DOMAIN

    domain1은 실제 JEUS 도메인 이름으로 대체되어야 한다.

  2. 새로운 도메인 디렉터리를 생성한 후에 디렉터리 내에 몇 가지 설정 파일들을 생성한다.

    가장 좋은 방법은 기존 도메인 디렉터리의 설정 파일들을 그대로 복사해서 필요에 따라 설정 파일을 변경하는 것이다(다음의 명령어는 모두 한 라인에 쓴다). 복사된 설정 파일에 대한 설명은 다음 절에서 설명한다.

    $ cp ${JEUS_HOME}/domains/domain1/config/security/SYSTEM_DOMAIN/*.*
         ${JEUS_HOME}/domains/domain1/config/security/DEFAULT_APPLICATION_DOMAIN

    JEUS_HOME/domains/<domain name>/security 아래에 SYSTEM_DOMAIN이 이미 디폴트로 존재한다. SYSTEM_DOMAIN은 JEUS 서버가 사용자 인증과 권한 체크를 위해 사용하는 도메인이다. 이 도메인은 JEUS를 기동하고, 종료하는 등의 Permission들과 JEUS 시스템 "administrator" 계정을 포함하고 있다.

  3. 새로운 보안 도메인 이름을 JEUS_HOME/domains/<domain name>/config/domain.xml 및 JEUS_HOME/domains/<domain name>/config/security/security-domains.xml에 각각 추가한다. domain.xml의 경우는 <security-manager><security-domain-names>에 추가해야 하고, security-domains.xml의 경우는 <security-domains><security-domain>에 추가한다.

  4. 새로 생성된 도메인은 JEUS를 다시 시작해야 적용된다.

    보안 도메인 SYSTEM_DOMAIN은 domain.xml의 설정과는 관계없이 항상 포함된다. 기본적으로 JEUS_HOME/domains/<domain name>/config/security 경로 아래에 도메인과 같은 이름의 디렉터리를 생성하여 각 도메인별로 정의할 Repository에 대한 계정 정보(account.xsd)와 보안 정책 정보(policies.xsd)를 정의한다. 기타 도메인별 Security Service 등록은 domain.xml에 한다.

3. 보안 도메인 구성요소 설정

본 절에서는 보안 서비스를 제외한 보안 도메인의 구성요소들을 설정하는 방법에 대해 설명한다.

3.1. XML 편집 설정

각 보안 도메인에서 로딩되는 보안 서비스는 domain.xmlsecurity-domains.xml에 설정되어 있다.

서비스에 대한 XML 파일 설정 방법은 JEUS_HOME/lib/schemas/jeus/supportLocale/ko 디렉터리 내의 jeus-security.xsd 및 security-domains.xsd의 XML 스키마에 정의되어 있다. <security-domains> 태그의 하위에는 서비스 설정과 관련된 <security-domain>을 설정한다. <security-domain>은 1개 이상 설정이 가능하고 각 태그는 JEUS에서 사용하는 보안 도메인을 정의한다.

보안 도메인 설정 : <domain.xml>
<?xml version="1.0" encoding="UTF-8"?>
<domain version="9.0" xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
   . . .
   <security-manager>
     <default-application-domain>DEFAULT_APPLICATION_DOMAIN</default-application-domain>
     <security-domain-names>
        <security-domain-name>SYSTEM_DOMAIN</security-domain-name>
        <security-domain-name>DEFAULT_APPLICATION_DOMAIN</security-domain-name>
           .....
     </security-domain-names>
  </security-manager>
   . . .
</domain>
보안 시스템 서비스 설정 : <security-domains.xml>
<?xml version="1.0" encoding="UTF-8"?>
<security-domains xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9.0">
   <security-domain>
      <name>SYSTEM_DOMAIN</name>
      .....
   </security-domain>
   <security-domain>
      <name>DEFAULT_APPLICATION_DOMAIN</name>
   </security-domain>
</security-domains>

<security-domain>에서 기타 다른 Service Provider에 대한 정보를 설정하지 않고 <name>에 대한 정보만 설정하면 해당 도메인에 기본으로 제공되는 보안 서비스들이 동작하게 된다.

다음은 <security-domain>의 하위 태그에 대한 설명이다.

  • <name> (필수)

    보안 도메인에 대한 이름이다.

  • <cache-config> (0개 이상, 선택)

    해당 도메인에 적용된 보안 Repository Service에서 적용할 Cache 정책값을 정의한다.

    태그 설명

    <min>

    Repository Service에 적용할 Cache entry 최소 size 값을 설정한다.

    <max>

    Repository Service에 적용할 Cache entry 최대 size 값을 설정한다.

    <timeout>

    Repository Service에 적용할 Cache entry의 timeout 값을 설정한다.

  • <keystore-config> (0개 이상, 선택)

    해당 도메인의 보안 서비스에 적용할 Keystore 파일에 정보값을 정의한다.

    하위의 설정값이 없는 경우 –Djeus.ssl.* 또는 –Djavax.net.ssl.* 설정이 되어 있는지 확인해 보고 해당 값이 없을 경우에는 기본값이 적용된다.

    태그 설명

    <keystore-path>

    Keystore 파일 경로를 설정한다.

    (예: JEUS_HOME/domains/<domain name>/config/security/keystore)

    <keystore-alias>

    Keystore 파일의 KeyEntry 타입의 인증서가 여러 개인 경우 명시적으로 alias 값으로 해당 서버 인증에 필요한 인증서를 가리키도록 한다.

    <keystore-password>

    Keystore 파일에 대한 패스워드를 설정한다. (기본값: changeit)

    <keystore-keypassword>

    Keystore 파일에 대한 Keypassword를 설정한다.

    (기본값: <keystore-password> 값과 동일)

    <truststore-path>

    Truststore 파일 경로를 설정한다.

    (예: JEUS_HOME/domains/<domain name>/config/security/truststore)

    <truststore-password>

    Truststore 파일에 대한 패스워드를 설정한다. (기본값: changeit)

4. 보안 서비스 설정

JEUS 보안 시스템은 플러그(plug) 형태의 인증(Authentication) 서비스와 권한 확인(Authorization) 서비스를 지원한다. 본 절에서는 보안 서비스를 포함하여 보안 도메인의 구성요소들을 XML 편집을 통해 설정하는 방법에 대해 설명한다.

4.1. XML 편집 설정

각 보안 도메인에서 로딩되는 보안 서비스는 security-domains.xml 내에 다음과 같이 설정되어 있다.

다음은 보안 설정 파일의 예제이다.

보안 시스템 서비스 설정 : <security-domains.xml>
<?xml version="1.0" encoding="UTF-8"?>
<security-domains xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9.0">
   <security-domain>
      <name>SYSTEM_DOMAIN</name>
      <authentication>
         <repository-service>
            <xml-file-repository>
               <config-file>
                  <filename>accounts.xml</filename>
                  <filepath>
                      ${JEUS_HOME}/domains/domain1/config/security/
                  </filepath>
               </config-file>
            </xml-file-repository>
         </repository-service>
      </authentication>
   </security-domain>
   <security-domain>
      <name>DEFAULT_APPLICATION_DOMAIN</name>
   </security-domain>
</security-domains>

다음은 <security-domain>의 하위 태그에 대한 설명이다.

  • <name> (필수)

    보안 도메인에 대한 이름이다.

  • <authentication> (0개 이상, 선택)

    해당 도메인에 적용할 인증 서비스를 정의한다.

    • <repository-service>

      인증을 위한 사용자 정보 저장소 타입에 따른 서비스를 정의한다.

      태그 설명

      <xml-file-repository>

      사용자 정보가 xml 파일에 정의된 경우 설정한다.

      <database-repository>

      사용자 정보가 데이터베이스에 정의된 경우 설정한다.

      <custom-repository>

      jeus.security.spi.AuthenticationRepositoryService SPI를 상속하여 사용자 정보를 로딩하는 방식을 확장 Repository Service를 구현하여 적용하는 경우 설정한다.

    • <jaas-login-config>

      해당 도메인에 적용할 JAAS 서비스를 등록한다.

      • <callback-handler-class> : JAAS Callback Handler Factory 클래스 이름을 정의한다.

      • <login-module> : LoginModule 관련 내용을 설정한다.

        태그 설명

        <login-module-classname>

        LoginModule을 implements한 패키지를 포함한 클래스 이름을 정의한다.

        <control-flag>

        다음 4가지 속성들 중 하나를 정의하여 전반적으로 Authentication Stack에 대하여 조정하는 속성을 정의한다.

        • required

        • requisite

        • sufficient

        • optional

        <option> (0개 이상)

        LoginModule 초기화하는 경우 적용할 속성값을 정의한다.

    • <custom-authentication-service>

      jeus.security.spi.AuthenticationService SPI를 상속하여 기본으로 제공되는 인증 서비스를 확장해서 적용하고 싶은 경우 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

  • <authorization> (0개 이상, 선택)

    해당 도메인에 적용할 권한 부여 서비스를 정의한다.

    • <repository-service>

      권한 부여를 위한 정책 정보 저장소 타입에 따른 서비스를 정의한다.

      태그 설명

      <xml-file-repository>

      정책 정보가 XML 파일에 정의된 경우 설정한다.

      <database-repository>

      정책 정보가 데이터베이스에 정의된 경우 설정한다.

      <custom-repository>

      jeus.security.spi.AuthorizationRepositoryService SPI를 상속하여 정책 정보를 로딩하는 방식을 확장 Repository Service를 구현하여 적용하는 경우 설정한다.

    • <custom-authorization-service>

      jeus.security.spi.AuthorizationService SPI를 상속하여 기본으로 제공되는 인증 서비스를 확장 적용하고 싶은 경우 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

    • <jacc-service>

      JACC 2.0 기반의 권한 부여 서비스를 적용하는 경우 설정한다.

  • <identity-assertion> (0개 이상, 선택)

    해당 도메인에 적용할 IdentityAssertion 서비스를 정의한다.

    • <default-identity-assertion-service>

      JEUS Security Framework에서 제공하는 기본 Identity Assertion Service를 정의한다.

      • <x509-identity-assertion> : X509Certificate Token에 대한 Identity Assertion Service를 지원한다.

        태그 설명

        <config-file>

        X509Certificate Token에 대한 사용자 매핑을 하기 위해서 정보를 정의한 파일의 위치를 지정한다.

        (기본값: DOMAIN 폴더 하위에 위치한 user-cert-map.xml)

        <default-user-mapper>

        X509Certificate Token 값에 attribute type(cert-attr-type) 값 또는 attribute type(attribute-type), attribute value에 대한 delimiter 값(attribute-value-delimiter)을 정의한다.

    • <custom-identity-assertion-service>

      jeus.security.spi.IdentityAssertionService SPI를 상속한 Identity Assertion Service를 확장 구현하여 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

  • <credential-mapping> (0개 이상, 선택)

    해당 도메인에 적용할 CredentailMapping Service를 정의한다.

    • <default-credential-mapping-service>

      JEUS Security Framework에서 제공하는 기본 Credential Mapping Service를 지원한다.

      • <x509-credential-mapping> : X509Certificate에 대한 Credential Mapping Service를 지원한다.

        태그 설명

        <truststore-path>

        현 도메인에 적용할 Truststore 파일에 대한 경로를 정의한다.

        <truststore-password>

        현 도메인에 적용된 Truststore파일 대한 패스워드를 정의한다.

    • <custom-credential-mapping-service>

      jeus.security.spi.CredentialMappingService SPI를 상속한 Credential Mapping Service를 확장 구현하여 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

  • <credential-verification> (0개 이상, 선택)

    해당 도메인에 적용할 Credential Verification Service를 정의한다.

    • <default-credential-verification-service>

      JEUS Security Framework에서 제공하는 기본 Credential Verification Service 지원한다.

      태그 설명

      <password-verification>

      PasswordFactory 클래스에 대한 검증 서비스를 정의한다.

      <jeus-certificate-verification>

      X509Certificate에 대한 검증 서비스를 정의한다.

    • <custom-credential-verification-service>

      jeus.security.spi.CredentialVerificationService SPI를 상속한 Credential Verification Service를 확장 구현하여 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

  • <audit> (0 개 이상, 선택)

    JEUS Security Framework에서 발생하는 이벤트에 대한 정보를 수집할 수 있도록 해당 도메인에 적용할 EventHandlingService를 정의한다.

    태그 설명

    <default-audit-service>

    해당 이벤트 정보를 기록하는 파일 경로와 이벤트 로그 레벨을 정의한다.

    • config-file: 로그 파일 경로

    • audit-level: 로그 레벨

    <custom-audit-service>

    jeus.security.spi.EventHandlingServiceService SPI를 상속한 Audit Service를 확장 구현하여 정의한다. 설정은 "Custom 보안 서비스" 설명을 참고한다.

Custom 보안 서비스

다음은 Custom 보안 서비스를 설정하는 방법이다. JEUS에서 제공하는 보안 서비스 종류와 Custom 보안 서비스의 개발과 관련된 사항은 Custom 보안 서비스 개발을 참고한다.

  • <classname> (필수)

    Custom 보안 서비스를 구현한 Java 클래스명이다. 이 클래스는 파라미터가 없는 디폴트 public 생성자를 가지고 있어야 하며, jeus.security.spi 패키지의 SPI 클래스를 상속받거나, jeus.security.base.Service 클래스를 직접 상속해야 한다.

  • <property> (0개 이상)

    jeus.security.base.PropertyHolder 인터페이스(jeus.security.base.Service 클래스가 구현한다)를 통해 보안 서비스에 name-value 쌍으로 속성을 설정할 수 있다. 속성은 각 보안 서비스를 초기화하는 데 사용된다.

    다음 2개의 하위 태그를 가진다.

    태그 설명

    <name>

    속성명을 설정한다.

    <value> (선택)

    속성명에 해당하는 String 속성값을 설정한다.

5. 보안 시스템 사용자 정보 설정

디폴트 보안 설정에서 사용자 데이터는 accounts.xml 파일에서 읽어 들인다.

다음은 파일 저장 경로이다.

JEUS_HOME/domains/<domain name>/config/security/<security domain name>/accounts.xml

여기서 <domain name>은 도메인의 이름이고, <security domain name>은 사용자가 관리될 보안 도메인의 이름을 나타낸다.

5.1. XML 편집 설정

accounts.xml의 XML 스키마는 accounts.xsd이며, JEUS_HOME/lib/schemas/jeus/supportLocale/ko 경로에 있다. accounts.xml 파일에는 최상위 태그 <accounts> 하위에 <users> 및 <groups> 태그가 있으며 0개 이상의 <user> 및 <group> 태그가 포함되어 있다. 각각은 사용자와 그룹을 나타낸다.

보안 시스템 사용자 정보 설정 : <accounts.xml>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<accounts xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
   <users>
      <user>
         <name>user1</name>
         <password>{AES}mnG6ItxFO/WQlE2YzIZ7sA==</password>
         <group>group1</group>
      </user>
      <user>
         <name>user2</name>
         <password>{DES}7dJ0KDTGQNpSnQAPYBNnmA==</password>
      </user>
      <user>
         <name>user3</name>
         <password>{DES}7dJ0KDTGQNpSnQAPYBNnmA==</password>
         <group>nested_group</group>
      </user>
      <user>
         <name>user4</name>
         <password>{SEED}dl2EePMAcnxPYbIyknuZkA==</password>
         <group>nested_group</group>
      </user>
   </users>
   <groups>
      <group>
         <description>Group1</description>
         <name>group1</name>
         <subgroup>nested_group</subgroup>
      </group>
      <group>
         <description>For NestedGroup</description>
         <name>nested_group</name>
      </group>
   </groups>
</accounts>

다음은 설정 태그에 대한 설명이다.

  • <user>

    각 <user> 태그는 다음과 같은 하위 태그를 가지고 있다.

    태그 설명

    <description> (선택)

    <user>에 대한 설명이다. (문자열)

    <name> (필수)

    <user>에 대한 이름을 나타낸다. (예: 사용자명, 사용자 ID)

    <password> (0개 이상, 선택)

    <user>에 대한 패스워드를 나타낸다.

    <password>는 어떤 특정 알고리듬을 사용하여 인코딩된 값을 정의한다. <password> 태그에 적용된 알고리듬 또는 인코딩 방식을 ’{}’ 블록 사이에 기입하도록 한다. 인코딩 방식에 대한 자세한 내용은 패스워드 보안 설정을 참고한다.

    <group> (0개 이상, 선택)

    <user>가 포함된 그룹을 나타낸다. 한 사용자는 여러 그룹에 포함될 수 있으며, 다음의 <group> 태그에서 정의된 그룹을 지정해야 한다.

  • <group>

    각 <group> 태그는 다음과 같은 하위 태그를 가지고 있으며 그룹을 정의한다.

    태그 설명

    <description> (선택)

    <group>에 대한 설명이다. (문자열)

    <name> (필수)

    <group>에 대한 이름을 나타낸다.

    <subgroup> (0개 이상, 선택)

    해당 group role을 동일하게 부여할 수 있도록 nested하게 속한 그룹 이름들을 정의한다.

5.2. 데이터베이스 사용 설정

본 절에서는 JEUS가 정의한 데이터베이스 테이블을 이용한 Authentication을 설정하는 방법에 대해서 설명한다.

다음 예제는 JEUS에 정의한 데이터소스를 이용할 때 설정하는 방법이다.

데이터베이스를 이용한 사용자 설정 : <security-domains.xml>
<?xml version="1.0" encoding="UTF-8"?>
<security-domains xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9.0">
   . . .
   <security-domain>
      <name>MY_DOMAIN</name>
      <authentication>
         <repository-service>
            <database-repository>
               <datasource-id>auth</datasource-id>
            </database-repository>
         </repository-service>
      </authentication>
      . . .
   </security-domain>
   . . .
</security-domains>

위의 예제에서 <datasource-id>에는 Authentication에 사용할 security-domains.xml에 등록한 데이터소스의 ID를 명시해야 한다. 또 다른 방법으로 DriverManager를 이용해 JEUS에서 제공하는 JDBC를 이용하지 않고 직접 DB와 통신하면서 Authentication을 이용할 수 있는데, 위의 예제에서 <datasource-id> 태그 부분을 다음과 같이 변경한다.

다음 예제는 JEUS JDBC를 이용하지 않을 때 데이터베이스 Repository를 설정하는 방법이다.

JEUS JDBC를 사용하지 않는 경우 설정 : <security-domains.xml>
   <security-domain>
      ...
      <repository-service>
         <dbdriver-config>
            <vendor>oracle</vendor>
            <driver>oracle.jdbc.OracleDriver</driver>
            <url>jdbc:oracle:thin:@127.0.0.1:1521:ORA9I</url>
            <username>scott</username>
            <password>{base64}dGlnZXI=</password>
         </dbdriver-config>
      </repository-service>
      ...
   </security-domain>

이 방식을 이용할 경우 커넥션을 맺고 끊는 것이 매우 잦기 때문에 성능상 문제가 있을 가능성이 크므로 JEUS JDBC(<datasource-id>)를 이용하는 방법을 권장한다.

데이터베이스에서 사용되는 테이블은 다음과 같이 구성된다.

figure usertable
Subject에 대한 사용자 정보를 저장하기 위한 데이터베이스 테이블 구조

데이터베이스에 테이블이 존재하지 않을 경우 JEUS_HOME/templates/security/dbrealm.sql.template 파일을 이용해서 DB에 테이블을 생성하면 사용자명이 "jeus", 패스워드가 "jeus"인 사용자가 최초로 생성된다.

5.3. 패스워드 보안 설정

본 절에서는 패스워드 보안 설정에 대한 사항 중 패스워드의 적합성 검사와 암호화 알고리듬, 그리고 SecretKey 파일 관리방법에 대해서 설명한다.

패스워드의 적합성 검사

사용자가 신규 계정을 생성하기 위해 패스워드를 입력하거나 기존 패스워드를 변경할 경우 패스워드의 적합성을 검사하여 제약을 줄 수 있다. 일반적으로 사용되는 제약 사항(알파벳과 숫자, 특수문자의 사용 여부나 아이디와 패스워드를 같게 하면 안되는 규칙 등등)과 같은 방식을 이용하여 패스워드의 보안을 강화할 수 있다.

Domain administrator는 기본적으로 제공되는 Default Password Validator나 사용자가 직접 구현하는 Custom Password Validator 중에 하나를 선택하여 도메인 전체에 적용할 수 있다. 각각의 기능을 사용하기 위해 사용자는 jeusadmin의 명령어를 통해 설정을 추가, 변경 및 삭제 할 수 있다. 사용자의 설정 정보는 domain.xml에 저장된다.

  • Default Password Validator 설정

    jeusadmin에서 modify-default-password-validator, show-default-password-validator 명령어를 통해 설정할 수 있으며, 명령어에 대한 정보는 JEUS Reference 안내서의 "Part II. 콘솔 명령어와 툴"을 참고한다.

    [MASTER]domain1.adminServer>modify-default-password-validator -min 4 -max 10
    Default password validator is updated successfully.
    Check the results using "show-default-password-validator or modify-default-password-validator".
    [MASTER]domain1.adminServer>show-default-password-validator
    ================================================================================
    +----------------------------------------------------------------------+-------+
    |                               property                               | value |
    +----------------------------------------------------------------------+-------+
    | min length                                                           |     4 |
    | max length                                                           |    10 |
    | include special characters                                           | false |
    | include digit characters                                             | false |
    | include capital characters                                           | false |
    | include small characters                                             | false |
    | exclude user id                                                      | false |
    +----------------------------------------------------------------------+-------+
    ================================================================================

    다음은 Default Password Validator을 사용할 경우 설정 항목에 대한 설명이다.

    항목 설명

    min

    패스워드의 최소 글자 수를 설정한다. (범위: 1 ~ 255, 기본값: 1)

    max

    패스워드의 최대 글자 수를 설정한다. (범위: 1 ~ 255, 기본값: 255)

    special

    패스워드에 특수문자가 반드시 들어가게 설정한다.

    digit

    패스워드에 숫자가 반드시 들어가게 설정한다.

    capital

    패스워드에 대문자가 반드시 들어가게 설정한다.

    small

    패스워드에 소문자가 반드시 들어가게 설정한다.

    excludeId

    패스워드에 아이디가 포함되지 못하게 설정한다.

    이렇게 설정한 Default Password Validator 값은 domain.xml에 아래와 같은 형식으로 저장된다.

    Default Password Validator로 패스워드 적합성 검사 설정 : <domain.xml>
    <domain>
        . . .
        <security-manager>
            . . .
            <password-validator>
                <default-password-validator>
                    <minLength>4</minLength>
                    <maxLength>10</maxLength>
                    <force-special-character>true</force-special-character>
                    <force-digit>true</force-digit>
                    <force-capital-letter>true</force-capital-letter>
                    <force-small-letter>true</force-small-letter>
                    <deny-username>true</deny-username>
                </default-password-validator>
            </password-validator>
            . . .
        </security-manager>
        . . .
    </domain>

    Default Password Validator의 설정을 마치면 변경 사항은 모두 동적으로 반영된다. 이후부터 새 사용자의 패스워드를 입력하거나 기존 패스워드를 변경하려고 할 때 설정된 Default Password Validator의 Password Validation이 적용된다.

  • Custom Password Validator 설정

    Custom Password Validator를 사용하면 사용자 맞춤형 Password Validation을 할 수 있다. JEUS는 jeus.util.PasswordValidator 인터페이스를 제공하며, 사용자는 해당 인터페이스를 직접 implement하여 원하는 기능을 담은 클래스를 구현한 뒤, jar 파일로 패키징하여 "DOMAIN_HOME/lib/application"에 넣어야 한다.

    사용자가 implement하여 구현해야 하는 jeus.util.PasswordValidator 인터페이스는 다음과 같다.

    public interface PasswordValidator {
           boolean validatePassword(String id, String password);
    }

    PasswordValidator 인터페이스를 구현한 클래스의 validatePassword(String id, String password) 메소드는 계정의 생성이나 비밀번호 변경을 시도하는 사용자의 id와 password를 인자로 받아 비밀번호 적합성 검사를 수행하고 기준에 적합하면 true를, 아니면 false를 리턴해야 한다.

    인터페이스를 구현한 클래스를 jar 파일 형태로 "DOMAIN_HOME/lib/application" 경로에 넣었으면 사용자는 jeusadmin의 명령어를 통해 Custom Password Validator 설정을 할 수 있다.

    jeusadmin에서는 Custom Password Validator에 관련한 명령어로 add-custom-password-validator, remove-custom-password-validator, show-custom-password-validator를 제공한다. 명령어에 대한 정보는 JEUS Reference 안내서의 "Part II. 콘솔 명령어와 툴"을 참고한다.

    [MASTER]domain1.adminServer>add-custom-password-validator -class MyValidator
    Custom password validator [MyValidator] is added successfully.
    Check the results using "show-custom-password-validator".
    [MASTER]domain1.adminServer>show-custom-password-validator
    ================================================================================
    +------------------------------------------------------------------------------+
    |                     custom password validator class names                    |
    +------------------------------------------------------------------------------+
    | MyValidator                                                                  |
    +------------------------------------------------------------------------------+
    ================================================================================

    이렇게 설정한 Custom Password Validator 값은 domain.xml에 아래와 같은 형식으로 저장된다.

    Custom Password Validator로 패스워드 적합성 검사 설정 : <domain.xml>
    <domain>
        . . .
        <security-manager>
            . . .
            <password-validator>
                <custom-password-validator>
                    <class-name>MyValidator</class-name>
                    <class-name>MyValidator2</class-name>
                </custom-password-validator>
            </password-validator>
            . . .
        </security-manager>
        . . .
    </domain>

    Custom Password Validator의 설정 변경사항을 적용하기 위해서는 서버를 재시작해야 한다. 서버 재시작 이후부터 새 사용자의 패스워드를 입력하거나 기존 패스워드를 변경하려고 할 때 설정된 Custom Password Validator의 Password Validation이 적용된다. 만약 사용자가 여러 개의 클래스를 구현하여 Custom Password Validator에 등록하였다면 모든 클래스의 Password Validation을 통과해야만 비밀번호 설정을 끝마칠 수 있다.

    서버를 재시작하는 과정에서 "DOMAIN_HOME/lib/application"에 사용자가 설정을 끝마친 Custom Password Validator에 등록된 클래스의 jar 파일이 없으면 서버는 부팅에 실패한다. 이 경우 사용자가 직접 domain.xml을 올바르게 수정해 주어야 서버를 다시 시작할 수 있다.

암호화 알고리듬

사용자 설정을 할 때는 사용자의 패스워드를 지정해야 한다. 패스워드를 plain-text 형식으로 저장하는 것이 가능하나 암호화 알고리듬을 통해 암호화하여 타인이 알아볼 수 없도록 한다.

안정성이 입증된 대칭키 알고리듬인 AES를 사용하는 것을 권장한다.

jeusadmin의 set-password 명령어를 통해 사용자별로 패스워드의 암호화가 가능하며, JEUS_HOME/bin/encryption을 이용하여 직접 암호화할 수도 있다.

직접 암호화한 경우는 패스워드를 설정할 때 다음의 형식으로 설정한다.

{알고리듬}암호화된문자열

대칭키 암호화 알고리듬의 키 값은 JEUS_HOME/domains/<domain name>/config/security/security.key 파일에 저장된다.

다음은 패스워드 암호화에서 지원하는 알고리듬에 대한 설명이다.

항목 설명

AES/DES/DESede/SEED/Blowfish

대칭키 암호화 알고리듬이다.

base64

인코딩 알고리듬이다. Base64로 인코딩된 정보는 누구나 손쉽게 디코딩할 수 있어 보안상 안전하지 않다.

SHA

Hash 알고리듬이다. 복호화가 불가능하다.

암호화 알고리듬을 사용할 때 key의 크기를 지정할 수 있다. Key 크기는 관리자가 시스템 프로퍼티로 관리하며 시스템 전체에 통일된 key 크기가 적용된다.

Key 크기의 기본값은 256bit 이며, 시스템 프로퍼티로 jeus.security.keylength 옵션을 주어 key 크기를 변경할 수 있다. 예를 들어 "-Djeus.security.keylength=256" 옵션을 주어 256bit의 key 크기를 갖는 암호화 알고리듬을 사용할 수 있다.

시스템 프로퍼티로 설정한 key 크기가 암호화 알고리듬이 지원하는 최대 key 크기 값보다 큰 경우, 암호화 알고리듬이 지원하는 최대값으로 key 크기가 설정된다. 예를 들어 AES는 key 크기로 128, 192, 256bit만 지원하기 때문에 AES512와 같은 설정은 AES256으로 적용된다.

만약 지정한 key 크기가 암호화 알고리듬이 지원하는 최대 key 크기 값보다 작으면서 지원하지 않는 key 크기인 경우에는 EncryptionException이 발생한다. 예를 들어 AES는 key 크기로 128, 192, 256bit만 지원하기 때문에 AES200과 같은 설정은 EncryptionException이 발생한다.

새롭게 시스템 프로퍼티를 설정한 이후에는 반드시 새롭게 password 초기화 과정을 거쳐야 한다.

마스터 패스워드를 통한 SecretKey 파일 관리

암호화 툴(JEUS_HOME/bin에 위치)을 사용해서 패스워드를 암호화하는 경우 해당 암호화 파일에 적용되는 SecretKey 정보를 security.key 파일에 암호화 알고리듬별로 저장하여 관리한다. 마스터 패스워드를 입력받아 이 패스워드로 security.key 파일을 암호화하여 저장할 수 있다.

security.key 파일은 다음 경로에 위치한다. 도메인 환경을 구성하는 경우 해당 security.key 파일을 함께 다른 노드에 옮겨놓아야 한다.

JEUS_HOME/domains/<domain name>/config/security/security.key

JEUS에 등록하는 데이터베이스 패스워드를 암호화하였을 경우 클라이언트에서는 이를 decrypt하기 위해 Key가 필요하다. 이때 SecretKey 파일 경로를 시스템 프로퍼티를 이용해 설정할 수 있다.

또한, security.key 파일에 마스터 패스워드가 설정된 경우 마스터 패스워드도 시스템 프로퍼티를 이용해서 설정할 수 있다. key path를 지정하는 프로퍼티 이름은 jeus.security.keypath이며, 마스터 패스워드를 설정하려면 jeus.security.master를 이용하면 된다. 이 프로퍼티들은 JEUS를 기동할 때도 이용할 수 있다. 다만, 보안의 이유로 마스터 패스워드는 프롬프트(standard input)로 입력하는 것을 권장한다.

5.4. 로그인 정보 캐시 기능

JEUS 스크립트를 통한 서버 부트나 jeusadmin으로 서버에 접속할 때는 사용자 정보가 필수로 입력되어야 한다. 이때 사용자 정보를 매번 입력하지 않고 로그인 정보를 캐시하여 사용할 수 있는 기능을 제공한다.

해당 정보는 USER_HOME/.jeusadmin/.jeuspasswd 파일에 AES로 인코딩되어 저장된다. 캐시 로그인 기능은 JEUS_HOME/bin/security.key 파일을 통해 인코딩/디코딩을 수행한다. 파일에 사용자의 중요한 정보인 id/password가 저장되기 때문에 본 기능의 사용은 권장하지 않는다.

로그인 정보의 Cache는 한 번이라도 인증이 이루어진 다음 파일에 기록된다.

JEUS 스크립트를 통한 서버 부트나 jeusadmin의 connect 명령어를 수행할 때 사용자 정보와 함께 -cachelogin 옵션을 추가하면 해당 로그인 정보가 파일에 저장된다. 이때 캐시 파일에 <domain name>:<user name>을 Key로 로그인 정보가 저장된다.

추후 JEUS 스크립트가 실행될 때 사용자 패스워드를 입력하지 않아도 도메인 이름과 사용자 이름에 대한 로그인 정보가 존재하면 자동으로 사용자 정보를 채워준다. 캐시된 로그인 정보가 존재한다 하더라도 사용자가 직접 사용자 정보를 입력한 경우에는 캐시된 로그인 정보는 무시된다.

다음 예제는 저장된 로그인 정보를 보여준다.

#Warning: We don't recommend to use this on Production Environment.
domain1:user1 gEPaqBz6BaAxWxdSXf8wZNPLsWkysgcov/KJnHvDeduKRvTAOb7F6zRaPHc2zLBUIUi46FQFWnl4mQiEIUbG9UEe4yZrsRri7yS9qi+7EwA=

저장된 로그인 정보는 jeusadmin의 off-line 명령어인 remove-login-cache를 통해 삭제할 수 있다.

6. 보안 시스템 정책 설정

디폴트 보안을 설정하는 경우 정책 데이터(권한 부여 데이터)는 policies.xml 파일에서 읽어온다.

이 파일은 다음 경로에 위치한다.

JEUS_HOME/domains/<domain name>/config/security/<security domain name>/policies.xml

<domain name>은 도메인의 이름이고, <security domain name>은 정책이 적용될 보안 도메인의 이름을 나타낸다.

6.1. XML 편집 설정

policies.xml의 XML 스키마는 policies.xsd로 JEUS_HOME/lib/schemas/jeus/supportLocale/ko 디렉터리 내에 있다. policies.xml은 0개 이상의 <policy> 태그로 구성되어 있으며, 각 태그는 개별 정책(권한 부여 데이터)을 나타낸다.

보안 시스템 Policy 설정 : <policies.xml>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<policies xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
   <policy>
      <role-permissions>
         <role-permission>
            <principal>user1</principal>
            <role>administrator</role>
         </role-permission>
         <role-permission>
            <principal>user1</principal>
            <role>teller</role>
            <actions>9:00-17:00</actions>
            <classname>
               jeus.security.resource.TimeConstrainedRolePermission
            </classname>
         </role-permission>
      </role-permissions>
      <resource-permissions>
         <context-id>default</context-id>
         <resource-permission>
            <role>teller</role>
            <resource>bankdb</resource>
            <actions>select, update</actions>
         </resource-permission>
         <resource-permission>
            <role>administrator</role>
            <resource>jndi</resource>
            <actions>modify, delete</actions>
         </resource-permission>
         <resource-permission>
            <resource>jndi</resource>
            <actions>lookup</actions>
            <unchecked/>
         </resource-permission>
         <resource-permission>
            <role>administrator</role>
            <resource>jeus.*</resource>
            <actions>*</actions>
         </resource-permission>
      </resource-permissions>
   </policy>
</policies>

다음은 설정 태그에 대한 설명이다.

  • <role-permissions> (0 또는 1)

    Principal-to-Role 매핑들에 대한 정보를 제공한다. 하위 태그로 0개 이상의 <role-permission> 태그를 가지고 있다.

    <role-permission> 태그는 다음의 태그로 구성되어 있다.

    태그 설명

    <principal> (0개 이상)

    현재 <role-permission>을 소유하고 있는 Principal 이름이다.

    <role> (1개, 필수)

    Role 이름을 나타낸다.

    <actions> (선택)

    Role에 대한 액션을 나타낸다.

    <classname> (선택)

    Role Permission으로 사용될 java.security.Permission을 구현한 Java 클래스명이다. 생략되면 jeus.security.resource.RolePermission이 디폴트로 사용된다. Custom Permission을 설정하고 구현하는 방법은 "Custom Permission 구현 및 설정"을 참고한다.

    <excluded> (선택)

    값이 없는 empty 태그( <xxx/> )이다. 설정되어 있으면 해당 Role Permission이 배제된다. 즉, Permission이 암시하는 Role에 아무도 접근할 수가 없다.

    <unchecked> (선택)

    값이 없는 empty 태그이다. 설정되어 있으면 Role Permission이 체크되지 않는다. 즉, Permission이 암시하는 Role에 누구나 접근할 수 있다.

  • <resource-permissions> (0개 이상)

    Role-to-Resource에 대한 정보는 다음의 태그로 구성되어 있다.

    • <context-id> (선택)

      문자열로 Context ID를 나타낸다. Context는 권한 부여 체크가 일어나는 범위를 나타낸다. JEUS 시스템이 JEUS 리소스에 대해 사용하는 기본 Context ID는 "default"이다.

    • <resource-permission> (0개 이상)

      다음의 항목으로 구성되어 있다.

      태그 설명

      <role> (0개 이상)

      현재 Resource Permission을 소유하고 있는 Role 이름이다.

      <resource> (1개, 필수)

      리소스 이름을 나타낸다.

      <actions> (선택)

      리소스에 대한 액션을 나타낸다.

      <classname> (선택)

      Resource Permission으로 나타내는 java.security.Permission을 구현한 클래스명이다. 생략하면 jeus.security.resource.ResourcePermission이 디폴트로 사용된다. Custom Permission을 생성하고 설정하는 방법은 "Custom Permission 구현 및 설정"을 참고한다.

      <excluded> (선택)

      값이 없는 empty 태그이다. 설정하면 해당 Resource Permission이 배제된다. 즉, Permission이 암시하는 리소스는 누구도 접근할 수 없다.

      <unchecked> (선택)

      값이 없는 empty 태그이다. 설정하면 해당 Resource Permission을 체크하지 않는다. 즉, Permission이 암시하는 리소스는 누구나 접근할 수 있다.

보통 policies.xml은 JEUS 서버 리소스에 대한 Permission( JNDI, JMS, Security 서버 등)을 설정하는 데 사용되고, Jakarta EE 애플리케이션과 Jakarta EE 모듈에 대한 Permission을 설정하는 데는 사용하지 않는다. 대신 Jakarta EE 애플리케이션과 모듈에 Permission을 설정하기 위해 다양한 DD 파일을 사용한다. 자세한 사항은 애플리케이션과 모듈에서 보안 설정을 참고한다.

Custom Permission 구현 및 설정

Permission(Role Permission 또는 Resource Permission)을 policies.xml 파일에 추가할 때마다 Permission을 나타내는 Java 클래스명을 설정해야 한다. 해당 클래스는 java.security.Permission 추상 클래스를 확장한 것이다. 자신만의 java.security.Permission 구현 클래스를 생성하여, policies.xml에 <classname> 태그로 설정하면 Custom Permission을 직접 생성할 수 있다.

다음 요구사항을 가진 새로운 Custom Permission을 구현하는 방법을 설명한다. 새로운 Role Permission은 원래의 Role 외에 다음과 같은 2가지 조건이 충족되는 상황에서 또 다른 Role을 암시할 수 있다.

  • 또 다른 Role도 원래의 Role과 동일한 이름을 가지고 있다.

  • 현재 시간이 특정 시간 범위(오전 9시부터 오후 5시까지) 내에 있을 때만 또 다른 Role을 암시할 수 있다.

예를 들어 이러한 Role Permission은 뱅킹 애플리케이션에서 "user2"라는 Principal이 오전 9시부터 오후 5시까지 업무시간 동안만 "teller"라는 Role을 가질 수 있도록 만들 수 있다. 이를 위해 다음의 2가지 작업이 필요하다.

  1. Custom Permission 클래스를 구현한다. 클래스 구현이 완료되면 "javac"로 컴파일하고 JEUS 서버의 클래스 패스에 해당 클래스 경로를 설정한다. 다음은 위의 요구사항을 만족하는 Custom Permission 클래스를 구현한 것이다. 자세한 코드는 생략한다.

    Custom Permission 클래스 : <TimeConstrainedRolePermission.java>
    package jeus.security.resource;
    
    import java.security.Permission;
    import java.util.Calendar;
    import java.util.StringTokenizer;
    
    /**
     * A time-constrained Role permission.
     * <p>
     * With this permission implementation you can express
     * things such as "X can only be in the role Y between
     * 09:00 AM to 05:00 PM".
     */
    public class TimeConstrainedRolePermission extends RolePermission {
        private String timeConstraint = "*";
        private int startTime = Integer.MIN_VALUE;
        private int endTime = Integer.MAX_VALUE;
    
        public TimeConstrainedRolePermission(String roleName) {
            this(roleName, "*");
        }
    
        public TimeConstrainedRolePermission(String roleName, String timeConstraint)
        {
            super(roleName);
            if (timeConstraint != null) {
                this.timeConstraint = timeConstraint;
                parseTimeConstraint();
            }
        }
    
        private void parseTimeConstraint() {
            . . .
        }
    
        public boolean equals(Object anotherObject) {
            . . .
        }
    
        public int hashCode() {
            . . .
        }
    
        public String getActions() {
            return timeConstraint;
        }
    
        public boolean implies(Permission anotherPermission) {
            if (this.timeConstraint.equals("*")) {
                return super.implies(anotherPermission);
            } else {
                Calendar cal = Calendar.getInstance();
                int curHour = cal.get(Calendar.HOUR_OF_DAY);
                int curMinute = cal.get(Calendar.MINUTE);
                int now = curHour * 60 + curMinute;
                if (now >= this.startTime && now <= this.endTime) {
                    return super.implies(anotherPermission);
                } else {
                    return false;
                }
            }
        }
    }

    해당 클래스는 jeus.security.resource.RolePermission을 상속하고, jeus.security.resource.RolePermission은 다시 java.security.Permission을 상속한다. 이는 코드 재사용성을 높이기 위한 구조이다.

    TimeConstrainedRolePermission을 상속해 또 다른 java.security.Permission을 만드는 것도 가능하다.

    위의 소스 일부에서 보면 2가지 타입의 생성자가 있다.

    • 첫 번째는(role name) 하나의 파라미터만 받는다.

    • 두 번째는(role name, time constraint) 2개의 파라미터를 받는다.

      java.security.Permission에서 첫 번째 파라미터는 "name"을 뜻하고 두 번째 파라미터는 "actions"를 뜻한다. 몇몇 Permission 구현 클래스는 "actions" 파라미터를 받는 두 번째 타입의 생성자가 생략되기도 한다.

      • "actions" 파라미터는 Permission에 대한 유효 시간을 나타내며, “09:00-17:00”라는 값을 가진다.

      • "name" 파라미터는 "administrator" 또는 "teller"와 같은 Role명을 나타낸다.

      소스의 핵심은 "implies(Permission anotherPermission)" 메소드로 현재 시스템 시간이 주어진 유효 시간 내에 있는지 체크한 다음, 만약 그렇다면 super.implies() 메소드를 호출하고, 그렇지 않으면 false를 리턴한다. 모든 implies() 메소드는 Boolean 값을 리턴하게 되어 있는데, 해당 Permission이 파라미터로 넘어온 Permission을 암시하는지를 나타낸다.

      1. implies() 메소드와 java.security.Permission 추상 클래스에 대한 자세한 정보는 Java SE JavaDoc 문서를 참고한다.

      2. jeus.security.resource.RolePermission, jeus.security.resource.TimeConstrainedRolePermission, jeus.security.resource.ResourcePermission에 대한 자세한 정보는 참고 자료와 JEUS Security JavaDoc에서 jeus.security.resource 패키지를 참고한다.

  2. policies.xml에 해당 Permission을 사용하도록 설정한다.

    Custom Permission 클래스 : <policies.xml>
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <policies xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
       <policy>
          <role-permissions>
             <role-permission>
                <principal>user2</principal>
                <role>administrator</role>
                <actions>9:00-17:00</actions>
                <classname>
                   jeus.security.resource.TimeConstrainedRolePermission
                </classname>
             </role-permission>
          </role-permissions>
          <resource-permissions>
             <context-id>default</context-id>
             <resource-permission>
                <role>administrator</role>
                <resource>jeus.*</resource>
                <actions>*</actions>
             </resource-permission>
          </resource-permissions>
       </policy>
       . . .
    </policies>

    "user2"라는 사용자는 "administrator" Role을 오전 9시부터 오후 5시까지 업무시간 동안만 부여받는다. "administrator" Role은 모든 JEUS 리소스(jeus.*)에 대해 모든 액션(*)을 실행할 수 있는 권한을 가지고 있다. 따라서, user2는 업무시간 동안만 모든 JEUS 리소스에 대한 모든 권한을 행사할 수 있다.

    위의 스키마는 Jakarta EE 애플리케이션과 모듈에서 JEUS DD 파일을 설정할 때도 그대로 적용되고 예제에서 보여준 Principal-to-Role Permission에 적용되고, Role-to-Resource Permission에도 동일하게 적용된다. JEUS DD에서 Custom Permission을 사용하는 방법은 애플리케이션과 모듈에서 보안 설정을 참고한다.

6.2. 데이터베이스 사용 설정

데이터베이스를 이용하여 Policy를 설정하려면 다음과 같이 security-domains.xml에서 보안 도메인 서비스를 지정해야 한다. Authentication과 마찬가지로 Driver Manager를 직접 이용하고 싶은 경우 <datasource-id> 대신에 <dbdriver-config> 태그를 추가한다. 그러나 일반적으로 JEUS JDBC 데이터소스를 사용할 것을 권장한다.

데이터베이스를 이용한 Policy 설정 : <security-domains.xml>
<?xml version="1.0" encoding="UTF-8"?>
<security-domains xmlns="http://www.tmaxsoft.com/xml/ns/jeus" version="9.0">
   ...
   <security-domain>
      <name>MY_DOMAIN</name>
      <authorization>
         <repository-service>
            <database-repository>
               <datasource-id>auth</datasource-id>
            </database-repository>
         </repository-service>
      </authorization>
      . . .
   </security-domain>
   . . .
</security-domains>

데이터베이스를 사용하는 AuthenticationRepositoryService를 사용하려면 데이터베이스에 접근하는 JDBC 드라이버와 접근을 하기위한 정보인 URL, 사용자 이름 그리고 패스워드가 필요하다.

본 예제에서는 Oracle에 접근하기 위한 정보로 패스워드는 base64로 인코딩된 문자가 입력된다. 특정 암호화 알고리듬 또는 인코딩 방식이 적용된 패스워드 값을 기입하는 경우 accounts.xml의 사용자 패스워드와 동일한 방식으로 기입하면 된다.

데이터베이스에서 사용되는 테이블은 다음과 같이 구성된다.

figure policytable
Policy를 저장하기 위한 데이터베이스 테이블 구조

데이터베이스에 테이블이 존재하지 않는다면 JEUS_HOME/templates/security/dbrealm.sql.template 파일을 이용해서 DB에 테이블을 생성하여 기본적인 Policy는 “SYSTEM_DOMAIN”에 “administrator”라는 Role을 가지게 되고, “jeus.*”에 대한 Resource 권한을 가진다. “administrator” Role 포함된 principal은 데이터베이스 사용 설정에서 설명한 jeus이다.

7. 추가 항목 설정

본 절에서는 Subject와 Policy 이외의 추가 항목을 설정하는 방법을 설명한다.

7.1. Java SE SecurityManager 설정

JEUS에서 Java SE SecurityManger를 사용하면, 플랫폼에 대한 부수적인 견고성을 얻을 수 있으나 성능이 저하된다. 일반적으로 Java SE SecurityManger에서는 모든 핵심 JEUS 코드뿐 아니라 JEUS에 deploy되어 있는 Jakarta EE 애플리케이션 및 모듈이 완벽하게 신뢰받은 코드로 간주되므로, 굳이 보안 관리자를 사용하여 부하를 초래할 필요는 없다. 보안 관리자를 사용하지 않는 모드가 JEUS에서 디폴트 모드이다.

그러나 때때로 Java SE SecurityManger를 사용하여 코드 수준의 보안을 강화시켜 추가적인 견고성을 높이는 문제가 성능 저하보다 중요하게 다루어지는 경우가 있다.

예를 들어 시스템 관리자가 불안정한 코드를 포함하고 있을지도 모르는 Jakarta EE 애플리케이션을 JEUS에 deploy해야 한다. 이 경우에 성능 저하라는 비용을 감수하고서라도 코드 레벨의 보안을 강화시켜 호스트를 보호하는 것이 더 중요하다고 판단되면 Java SE SecurityManger를 작동시켜야 한다.

Java SE SecurityManger를 JEUS와 함께 동작시키기 위해 domain.xml에 특정 서버에 대해 jvm-option을 다음과 같이 정의한다.

-Djava.security.manager
-Djava.security.policy=${JEUS_HOME}/domains/domain1/config/security/policy(UNIX기준)

정책 파일은 JEUS_HOME/domains/<domain name>/config/security/policy이며 내용은 다음과 같다.

Java SE SecurityManager 설정 : <policy>
grant codeBase "file:${jeus.home}/lib/system/*" {
   permission java.security.AllPermission;
};

grant {
   permission java.net.SocketPermission "127.0.0.1:1024-",
   "connect, accept, connect, listen, resolve";
   permission java.security.SecurityPermission "runTrustedLogin", "read";
   permission java.security.SecurityPermission "loginCodeSubject", "read";
   permission java.security.SecurityPermission "putProviderProperty.*";
   permission java.security.SecurityPermission "insertProvider.*";
   permission javax.management.MBeanPermission "*", "*";
};

Java SE SecurityManger는 JEUS의 보안 시스템과는 완전히 별개의 것이다. JEUS 보안 시스템은 코드 수준의 보호(코드를 호출할 수 있는 Permission 설정)가 아니라, 사용자 수준의 보호(누가 로그인했고, 해당 자원에 대한 Permission이 있는가)를 다루고 있다.

둘 사이 유일한 접점은 JEUS가 특별한 경우 Java SE SecurityManger를 사용하여 코드 수준의 Permission을 체크함으로써 악의적인 Servlet이나 EJB 코드로부터 JEUS를 보호하기도 한다는 점이다.

7.2. JACC Provider 설정

JEUS에서 JACC 2.0 설정에 대한 이슈는 JACC Provider 사용에서 설명할 것이다. 더 자세한 내용은 해당 절을 참고한다.

7.3. Identity 부여를 위한 정보 설정

IdentityAssertionService 지원하는 경우 추가적으로 인증서와 사용자 간의 매핑 정보가 있는 cert-user-map.xml 파일에서 읽어 들인다. 이 파일은 다음의 경로에 위치한다.

JEUS_HOME/domains/<domain name>/config/security/<security domain name>/

<domain name>은 도메인의 이름이고, <security domain name>은 사용자가 속한 보안 도메인의 이름을 나타낸다.

cert-user-map.xml의 XML 스키마는 cert-user-map.xsd이며, JEUS_HOME/lib/schemas/jeus/supportLocale/ko 경로에 있다.

이 파일에는 최상위 태그 <cert-user> 하위에 <user> 및 <cert> 태그가 있으며 하위 0개 이상의 <cert-user> 태그가 포함되어 있다. 각각은 사용자에 대한 인증서 매핑을 위한 속성 정보를 나타내고 있다.

Identity 부여를 위한 정보 설정 : <cert-user-map.xml>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cert-user-map xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
   <cert-user>
      <username>user1</username>
      <cert>
         <subjectDN>user1DN</subjectDN>
      </cert>
   </cert-user>
</cert-user-map>

각 <cert-user> 태그는 다음과 같은 하위 태그를 가지고 있다.

  • <username> (필수)

    인증서 attribute 값에 매핑되는 사용자에 대한 이름을 나타낸다. (예: 사용자명, 사용자 ID)

  • <cert>

    각 <cert> 태그는 다음과 같은 하위 태그를 가지고 있으며 사용자에 대한 인증서 매핑 정보을 정의한다. 이는 Truststore 파일에 포함된 인증서에 대해서 하위 attribute 값들이 유일한 ID를 보장해서 idenity를 부여할 수 있도록 사용자 이름과 매핑되는 값들을 정의한다.

    태그 설명

    <alias> (선택)

    Keystore 내의 Certificate에 대한 Alias를 정의한다. (문자열)

    <subjectDN> (선택)

    Keystore 내의 Certificate에 대한 subjectDN를 정의한다. (문자열)

    <SKI> (선택)

    Keystore 내의 Certificate에 대한 SKI를 정의한다. (문자열)

    <issuer> (선택)

    Keystore 내의 Certificate에 대한 issuer를 정의한다. (문자열)

    <serialNo> (선택)

    Keystore 내의 Certificate에 대한 serial number를 정의한다. (문자열)

7.4. Identity에 대한 인증서 정보 설정

JEUS 보안 시스템에서는 인증서로 인증된 Identity 사용자 정보에 대한 인증서 정보를 얻을 수 있는 API를 제공하는 UserCertMappingService를 제공한다. UserCertMappingService 지원하는 경우 추가적으로 사용자별 인증서 파일을 얻기 위한 매핑 정보가 있는 user-cert-map.xml 파일에서 읽어 들인다. 이 파일은 다음의 경로에 위치한다.

JEUS_HOME/domains/<domain name>/config/security/<security domain name>/

<domain name>은 도메인의 이름이고, <security domain name>은 사용자가 속한 보안 도메인의 이름을 나타낸다.

user-cert-map.xml의 XML 스키마는 user-cert-map.xsd이며, JEUS_HOME/lib/schmas/jeus/supportLocale/ko 경로에 있다.

이 파일에는 최상위 태그 <user-cert-map> 태그 하위에 0개 이상의 <user-cert> 태그가 포함되어 있다. 각각은 Keystore 파일에서 사용자에 대한 인증서를 얻기 위한 속성 정보를 나타낸다.

Identity에 대한 인증서 정보 설정 : <user-cert-map.xml>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user-cert-map xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
   <user-cert>
      <username>user1</username>
      <alias>alias1</alias>
      <keypassword>changeit</keypassword>
      <secretkey>
         <keyname>testkeypass</keyname>
         <keyalgorithm>AES</keyalgorithm>
         <keyvalue>bjhTUjJvSXRTOGlkVEdlNHJnM2N3VnljSDZXV0JkYz0=</keyvalue>
      </secretkey>
   </user-cert>
</user-cert-map>

각 <user-cert> 태그는 다음과 같은 하위 태그를 가지고 있다.

  • <username> (필수)

    Keystore 내의 Certificate에 대한 사용자 이름을 정의한다. "primary" identify로서 유일해야 한다.

    (예: 사용자명, 사용자 ID)

  • <alias> (필수)

    Keystore 내의 Certificate에 대한 Alias를 정의한다.

  • <keypassword> (선택)

    Keystore 내의 Certificate에 대한 Private Key를 얻기위한 Keypassword를 정의한다. (예: changeit)

  • <secretkey> (선택)

    Private Key를 정의한다.

    각 <secretkey> 태그는 다음과 같은 하위 태그를 가지고 있다.

    태그 설명

    <keyname> (필수)

    Private Key의 이름을 정의한다. <user-cert-map> 태그 하위에 존재하는 keyname 값은 유일해야 한다. (문자열)

    <keyalgorithm> (필수)

    Private Key의 키 알고리듬을 나타낸다. (문자열)

    <keyvalue> (필수)

    Private Key의 값을 Base64 형태로 나타낸다.