Table of Contents
This chapter describes the concepts, structure, and key features of the security system.
In general, the concept of security refers to a set of measures used for preventing and detecting potential and actual infringements on a system that might cause internal and external damage.
This concept is relevant to an enterprise or computing environment that manages user information and provides users with services. In this environment, security measures are provided to protect the users' names, passwords, and addresses as well as resources that provide a service or operate the system. To protect the critical data and system resources, each enterprise or computing system uses software or hardware designed to provide security.
JEUS provides various security services as well. The JEUS security services implement Service Provider Interface (SPI), which provides various security service types that protect user information and resources defined in JEUS.
This guide outlines the basic structure of the JEUS security system and general security management.
The JEUS security system is designed to achieve the following:
Have a flexible and pluggable framework.
The framework should be able to integrate the security system with any existing third-party security mechanism and/or persistent storage mechanism.
Ensure security.
The security system should prevent any unauthorized access to the system, even by a highly sophisticated intruder who can decompile the security system sources.
Provide high performance.
The security system should have minimal impact on the overall performance while ensuring security for the entire system and application codes. While there is a general trade off between security level and system performance, the JEUS security system is designed to offer both maximum security and high performance.
Provide a simple, unambiguous API and SPI for facilitating maintenance and the creation of 3rd party security services.
Maintain data integrity.
Comply with the standards.
The JEUS security system meets all the objectives.
The following are the key features of the JEUS security system:
The system has an open architecture and framework with a complete set of security integration SPI for customers and 3rd parties to use as needed.
The system fully supports dynamic principal-to-role and role-to-resource authorization mappings.
This means that the authorization mappings (principal-to-role and role-to-resource) are applied at runtime.
This enables the following security policies:
User U is granted the R role only during the 9 to 5 business hours, Monday to Friday
Everyone is granted the R role
No-one is granted the R role
The system supports the concept of a security domain (hereafter domain). This allows different J2EE applications access different security services.
Note that domain and security domain refer to different concepts in the JEUS system. In the system, a domain refers to a server management unit and a security domain refers to a security management unit.
The system provides default implementations of all critical security operations such as authentication, authorization, repositories, auditing, and clustering.
The system supports security auditing mechanisms through a flexible event handling model.
The system enables the user to add simple security functions, such as Subjects and policies, to the servlet, EJB, and application source codes.
The system fully supports JDK 1.7 and JACC 1.5 specifications.
The system provides full support through this document and additional Javadoc.
The system runs independently from other JEUS modules, which makes it easy to use in a different context.
The following figure shows the basic architecture of the security system.
The following are the main components (package) of the security system:
The security SPI classes (represented by the large box in the middle of the figure) is the core of the JEUS security system. These abstract classes contain methods that are called by user code (JEUS containers etc.), as well as abstract methods that will be implemented by third party sub-classes.
There are currently eleven SPI classes available, each related to a specific aspect of security such as authentication and authorization.
Repository and external security mechanism
Repositories and external security mechanisms (represented by the boxes at the bottom) include databases, LDAP servers, or XML files.
The repositories are used to persistently store security attributes, such as Subject and Policy information.
External security mechanisms refer to mechanisms that perform authentication or authorization. An example of an external security mechanism is the JACC provider. However, the boundaries for plain repositories and security mechanisms are not clearly defined. As shown, it is the responsibility of the SPI implementation classes (in this case, the class included in jeus.security.impl.* package) to decide which repository and security mechanism to apply.
This chapter covers the core concepts necessary to understand the overall security system.
In the JEUS security system, a login is a process that associates a Subject with a Java execution thread. This process is different from authentication, which takes place before the Subject is associated with an execution thread. Therefore, if the authentication is successful, a login will proceed. But if the authentication fails, a login also fails.
After a Subject has logged in successfully, the Subject goes through authorization. The login concept may thus be seen as an umbrella that spans both authentication and authorization. The opposite of a login process is a logout process, which disassociates a Subject from its execution thread.
Note that the implementation of a login process requires a stack-based operation. Several Subjects can be logged in at any time with each new Subject being pushed onto the top of a stack. Only the Subject on top of the stack is used for authorization. When the Subject logs out, the top Subject is removed from the stack, and the next Subject at the top of the stack is activated.
The following illustrates this mechanism.
In the JEUS security system, only one login stack is allowed for each Java thread. As shown in the Security System Architecture figure, the login mechanism is implemented by the jeus.security.impl.login.CommonLoginService interface.
Authentication is a process of obtaining the identity of a caller for the purpose of using it for authorization at a later time.
In the JEUS security system, an identity is represented as a Principal that is defined by the java.security.Principal interface.
A Principal is stored as an attribute value of a Subject, which, as described in the previous section, is implemented by the jeus.security.base.Subject class and associated with an execution thread. A Subject includes Principals and credentials as its security attributes.
The Subject implementation used in the JEUS security system is not equivalent to the JAAS Subject defined by the class javax.security.auth.Subject. However, these two implementations are similar in many aspects. Also, it is possible to convert from one to the other so that even if some information is lost, that lost information can be referred to by an alias.
The following is a UML diagram for a JEUS Subject.
As shown, the Subject has a main Principal as its unique ID. The Subject may also carry any number of additional optional Principals. These are non-unique Principals that may be shared by several Subjects, and these non-unique Principals are referred to as group group Principals.
Subject can also have public or private credentials. Credentials are usually used as a proof to authenticate the Subject or to deliver specific information. An example of a private credential is a password. An example of a public credential is a digital certificate.
The credentials of a given Subject may be created by using its sub-class, credentialFactory class. The actual credentials are obtained from the credential factories using the refresh() method, and they are added to the public or private credential sets.
Each Subject always belongs to exactly one domain. A Subject with the main Principal "user1" in domain A is thus different from another Subject with the main principal "user1" in domain B.
In the JEUS security system, authorization is a process of determining whether a previously authenticated Subject should be allowed to perform a particular operation.
Authorization happens at the system level. For example, authorization is required to determine whether a certain Subject, usually an administrator, is authorized to boot or shut down the JEUS server. Authorization is also required at the application level, for example, when a JEUS engine checks whether a remote caller should be allowed to access a particular application component, such as a specific EJB method or a servlet.
As in J2EE, authorization in the JEUS security system is a role-based mechanism. The developer or assembler of a J2EE application sets up security restrictions that are assigned to roles, to which Principals are mapped during the deployment of an application.
The role-based approach is also used for JEUS system authorization as well as for J2EE applications.
In the JEUS security system, authorization mappings are referred to as permissions (sub-classes of java.security.Permission). For example, the Principal "user1" is said to have the permission to access a role called R. That is, user1 belongs to the role group R.
Let's suppose that the role R includes the permission to access the resource JNDI and execute the lookup action.
The following illustrates role-based authorization.
As seen in the previous figure, only Principals and roles are represented as physical entities. The resource circle in the figure has a dashed outline to denote that resources are implied and not physically modeled in the authorization process.
In the previous figure, the two boxes marked RolePermission and ResourcePermission represent instances of the two classes jeus.security.resource.RolePermission and jeus.security.resource.ResourcePermission, respectively. Both of these classes extend the basic java.security.Permission abstract class, and there are various other sub-classes of the Permission class.
Briefly summarized, a Principal owns a set of permissions and those permissions grant the Principal a set of logical roles. These roles in turn own another set of permissions that grant those roles access to a set of actions on the resources. By following these indirect mappings, one can determine whether a principal should be allowed to perform a specific action on a resource.
The figure above shows that the Principal user1 owns a RolePermission. The arrows marked "owns" in the figure intuitively denote a direct, static binding. However, the term "implies" used to show that the RolePermission implies role R is different. This implication indicates that binding is not static. Rather, the relationship between the RolePermission and the role R is determined dynamically at runtime by invoking the method implies(Permission p) on then RolePermission instance.
If the implies() method returns true, the RolePermission is said to imply role R, otherwise it is not. Thus, in the former case, principal user1 is granted the role R, and in the latter case it is not. The same logic applies for the implication between the role R and the Resource JNDI.
For more information about Permission, refer to the java.security.Permission section in J2SE Javadoc.
Given the previous information, it is not difficult to implement dynamic mappings. If we just change the implementation of the implies() method, we can make a permission imply a role or resource under certain conditions. For example, we might want to create a dynamic mapping between principal user1 and role R, so that user1 is granted with role R during the business hours (9 AM to 5 PM). To do this, we could simply create a new RolePermission sub-class, called TimeConstrainedRolePermisson, and override the implementation of the implies() method. In this method, you can add a check for the additional time-constraint.
For more examples of implementing dynamic mappings, refer to [Figure 1.5] and [Figure 1.6].
As shown in [Figure 1.5], principal user1 is not granted role R.
As shown in the previous figures, the TimeConstrainedRolePermission class contains two variables, Name and Actions. Name is set to the name of the implied role, which is R in the example, and the Actions are set to the time when the implication is valid, which is between 9 AM and 5 PM in the example. Both Name and Actions are standard variables that are declared in most java.security.Permission class implementations.
Moreover, apart from the basic Permission-based mappings, every permission in the authorization system belongs to one of the following three types.
In the JEUS security system, all permission mappings are the classes that implement the jeus.security.base.PermissionMap class. These PermissionMap classes are included in the jeus.security.base.Policy class.
Policy class has two kinds of PermissionMaps.
Principal-to-Role Map (Role Policy0)
Role-to-Resource Map (Resource Policy)
Each PermissionMap contains the three aforementioned permission types--excluded, unchecked and checked permissions. In the case of checked permissions, a permission and role PermissionMap are combined through a Principal or role. A Policy and resource PermissionMap are combined through a context ID, which indicates the authorization scope.
The following is a UML diagram of Policy and PermissionMap classes.
The following figure summarizes information about mappings. .
In the previous figure, we have a Policy instance that contains one principal-to-role mapping, which is required, and also two role-to-resource mappings with context IDs A and B, respectively. All three PermissionMaps contain three sets of permissions as follows.
The oval figures inside the boxes represent the actual permission instances (Name: Action) with Name and Action variables.
Let's suppose that a Subject, with context ID "A" and the Principal "user1", wants to access JNDI to modify it.
This authorization query would be processed by the authorization system as follows:
A new ResourcePermission (hereafter RSP), is created with the name "JNDI" and action "modify."
The RSP is passed along with the context ID "A" and Principal "user1" to the Policy.
Policy selects the Role-to-ResourcePermissionMap for context ID "A."
Policy checks whether excluded permissions of PermissionMap A contain the RSP, and receives the result that it is not included in excluded permissions.
Policy checks whether unchecked permissions of PermissionMap A contains the RSP, and receives the result that it is not included in unchecked permissions.
Policy checks whether checked permission of PermissionMap A contains the RSP, and receives the result that it is included in Checked Permission.
Policy retrieves a list of permission owners that implied the RSP, and finds that there is only one such owner, the role called Administrator.
Policy constructs a RolePermission (hereafter RLP) object with the name Administrator.
Policy checks whether excluded permission of Principal-to-RolePermission contains RLP, and receives the result that RLP is included in Excluded Permission.
The fact RLP is included in excluded permission indicates that the role Administrator has excluded permission. Therefore, nobody can access Policy. As a result, the entire authorization process will be terminated, and the value DENIED will be returned.
In this process, although user1 is mapped to the role Administrator, since Administrator is also in the excluded set, user1 is not granted the role Administrator. This is because excluded permissions have higher precedence over both unchecked and checked permissions.
Using the previous figure and following the step-by-step instructions above, you can work out the following authorization queries.
Security auditing generally involves capturing security-related events such as failed authentication and runtime exceptions and evaluating these events for better system security.
The JEUS security system features a simple yet flexible auditing mechanism using security events. Whenever something significant happens in the system, such as failed authentication or failed authorization, an event will be posted to a set of registered event handlers.
The handler implementations, which can be fully customized, responds with an appropriate action, such as locking a Subject's credential when authentication has failed too many times in a row.
Each class in the security system that implements security functionalities constitutes as a Service. A Service is simply an implementation of an Service Provider Interface (SPI) that provides some security functionality, whether it is authentication, authorization, or networking.
SPI is an abstract class of the Java package jeus.security.spi. These SPI class should be extended and implemented in order to implement customized security functionality. The extended sub-classes of an SPI class are called Services.
All instances of Services in the security system are treated individually as independent entities whose services are called as needed. However, it is common for a Service implementation to make calls to another SPI, and some dependency may exist among different Services. In order to initialize Services. All Services receives a key–value pair property value used to initialize the Service. The configuration data of a Service can also be saved in a configuration file.
All Services may also optionally define a JMX bean that will be exported to the JEUS management system. The JMX MBean is normally created based on a MBeanInfo instance returned by the Service.getMBeanInfo() method.
All Services have two states, a created state and a destroyed state. The create() and destroy() methods are called to transition between the two states. Calling these methods will invoke doCreate() and doDestroy() abstract methods. These abstract methods should be implemented by Service sub-classes for service initialization and management.
Users do not need to understand the Service and SPI architecture when only using the JEUS security system.
Security domain is a collection of security Service instances. Several domains may exist concurrently within the security system. The purpose of a domain is to allow deployed applications and JEUS sub-systems to use individual security Services. A domain separates the security Services for each application.
For example, the JEUS server could be set up to use a special domain. In this case, it is call the SYSTEM_DOMAIN. This domain contains Subjects and Policies that are used to manage the JEUS server. For example, the SYSTEM_DOMAIN contains the user information for a main Subject called administrator, which can be used to boot or shut down the server.
Another domain, let's call it APP_DOMAIN, could be used by a deployed J2EE application. That domain might also contain a user information for a Subject called administrator, which is different from the JEUS server administrator. You could also configure a different repository mechanism for each domain. While the SYSTEM_DOMAIN can be configured to use a simple XML file to store Subject information, the APP_DOMAIN can be configured to use a remote database to read and write Subject information.
The domain concept is illustrated in the following figure.
Use of the domain feature is optional. If no domain is
specified, a special SYSTEM_DOMAIN is used.
It is our convention to name domains using capital letters and to append "_DOMAIN" to the name. This is not a requirement, just a convention. Also note that whenever the term domain is used within this document, it refers to the Security domain. These Security domains have nothing in common with J2EE server domains.
By default, JEUS uses two domains, SYSTEM_DOMAIN and SHARED_DOMAIN, as follows:
The domain name that is used when managing the JEUS server through its standard management tools. This domain contains JEUS administrator accounts and permissions to manage the JEUS server, such as booting and shutting down.
The name of a special domain whose security services will be shared by all other configured domains. Thus, the SHARED_DOMAIN contains security services that will be applied to all other domains.
To apply different security services to applications, create a separate domain and configure the domain.xml file. For more information about creating and configuring security domains, refer to "Chapter 2. Configuring the Security System".
To a certain degree, the information given in this chapter conflicts with the attributes a security system must have. Basically, there is always a trade off between performance and security. Thus, you need to control the level of performance and security to an appropriate level according to the task requirements.
This chapter explains how to minimize the performance impact that the security system has on the overall performance of the JEUS server.
The following are measures for improving performance of the overall security system.
Do Not Use Secured Connection in JEUS Domain.
Secure connection uses a socket to send an encoded packet, which means that larger amount of data will be transmitted than with a general socket communication.
To improve performance, it is recommended not to use secured connections in JEUS domain.
Do Not Use JEUS SecurityManager
You can avoid executing unnecessary operations by not using the SecurityManager. This means that authorization is not used, but instead authentication is required.
Network blocking occurrences can be reduced by using Non-Blocking I/O. Non-blocking I/O removes blocking while waiting for the next I/O request to occur.
Therefore, CPU usage and the number of FD are reduced because a separate thread for I/O is not needed for each connection. non-blocking I/O is used in JEUS by default. It guarantees higher performance than blocking I/O.
This section explains how to improve the security system level despite a performance hit.
The following are the ways to improve the overall security level of JEUS:
Set the global system password.
Use secured connection in JEUS security domain
Configure the network security service to use secured connection, which is usually protected with SSL/TLS. For more information about how to set a secured connection when the default network service is used, refer to Reference. This prevents anyone from network eavesdropping and picking up sensitive information.
Protect Subject and Policy from Unauthorized Access
It is essential to protect user information of a Subject and the Policy repository location from unauthorized access. The method for this depends on the repository type. The following are some example cases.
If a database is in use, the table that stores user information of a Subject and the table where Policy is stored must be protected through authentication and authorization configured on the database side. You must also protect connections between the JEUS security repository and the database by using SSL, etc. Refer to the database documents to learn how to configure this setting.
If security information is stored in an XML file such as accounts.xml and policies.xml, you must create proper file access permissions to ensure that only the JEUS security system and administrators have access to this file. Use encryption, if encryption is supported regardless of the repository. Refer to the repository document to learn how to apply security to files. Refer to the operating system manual to learn how to set read/write access to the files.
Use Security Auditing
Create a security event log for events that occur in the system and periodically audit the log. JEUS security auditing mechanism is usually implemented by using the service SPI class, jeus.security.spi.EventHandling. Note that a log file must be protected from unauthorized access. For information about various security auditing mechanisms, refer to Reference.
Use JavaSE SecurityManager
Set JavaSE SecurityManager as explained in "2.7.1. Configuring Java SE SecurityManager" to improve the robustness of the JEUS system and to protect JEUS from potentially malicious EJB and Servlet code injections.
Use Third-Party Security Mechanism
In an environment that deals with sensitive information such as in a banking application, it is strongly recommended to use additional security mechanisms such as firewalls or virtual private networks (VPNs) along with the JEUS security system.
Configure Security for Operating System
Regardless of the operating system in which JEUS operates, do as follows to protect the operating system.
Restrict physical access to the servers where JEUS is installed. For example, keep the servers in a locked place.
Set process and file privileges so that only trusted administrator can access the JEUS files and processes. Refer to the operating system manual.
Update the operating system with the latest security related patches.
Periodically execute an antivirus software.
Keep all written security related documents safe. For example, keep written passwords in a locked cabinet.