[jboss-cvs] JBossAS SVN: r101228 - in projects/docs/enterprise/5.1: JBoss_Security_Guide and 2 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon Feb 22 01:09:11 EST 2010
Author: jaredmorgs
Date: 2010-02-22 01:09:11 -0500 (Mon, 22 Feb 2010)
New Revision: 101228
Added:
projects/docs/enterprise/5.1/JBoss_Security_Guide/
projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample
projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg
Removed:
projects/docs/enterprise/5.1/JBoss_Security_Chapter/
projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml
projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg
Modified:
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Book_Info.xml
projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Preface.xml
Log:
Updated name of JBoss Security Chapter to its own guide proper
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide (from rev 101059, projects/docs/enterprise/5.1/JBoss_Security_Chapter)
Deleted: projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Chapter/Chapter_Rejig 2010-02-17 06:01:22 UTC (rev 101059)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig 2010-02-22 06:09:11 UTC (rev 101228)
@@ -1,14 +0,0 @@
-Summary of changes in 5.x security:
-
-* JaasSecurityMgrRealm and JaccAuthorizationRealm have been merged into org.jboss.web.tomcat.security.jBossWebRealm
- (no instances of these keywords in 4.3 info)
-
-* move away from JaasSecurityManagerService MBean in conf/jboss-service.xml-----------------|
- |--- these are affected in (sect 2.4, 2.4.2, other 2.4.x)
-* SecurityManager ^^ replaced by POJO beans such as deployers/security-deployer-beans.xml --|
-
-* SecurityAssociation is replaced by SecurityContext for ejb2 and web deployers -- impact on sect 2.4.2 and 2.5.3.10
-
-* Securing a Web Application has new and exciting ways of being configured.
- - Set a simple security domain for JBossSX
- -
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig (from rev 101058, projects/docs/enterprise/5.1/JBoss_Security_Chapter/Chapter_Rejig)
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig (rev 0)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/Chapter_Rejig 2010-02-22 06:09:11 UTC (rev 101228)
@@ -0,0 +1,14 @@
+Summary of changes in 5.x security:
+
+* JaasSecurityMgrRealm and JaccAuthorizationRealm have been merged into org.jboss.web.tomcat.security.jBossWebRealm
+ (no instances of these keywords in 4.3 info)
+
+* move away from JaasSecurityManagerService MBean in conf/jboss-service.xml-----------------|
+ |--- these are affected in (sect 2.4, 2.4.2, other 2.4.x)
+* SecurityManager ^^ replaced by POJO beans such as deployers/security-deployer-beans.xml --|
+
+* SecurityAssociation is replaced by SecurityContext for ejb2 and web deployers -- impact on sect 2.4.2 and 2.5.3.10
+
+* Securing a Web Application has new and exciting ways of being configured.
+ - Set a simple security domain for JBossSX
+ -
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US (from rev 101058, projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US)
Modified: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Book_Info.xml
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/Book_Info.xml 2010-02-17 02:56:54 UTC (rev 101058)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Book_Info.xml 2010-02-22 06:09:11 UTC (rev 101228)
@@ -2,9 +2,9 @@
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<bookinfo id="book-JBoss_Security_Chapter-JBoss_Security_Chapter">
- <title>JBoss_Security_Chapter</title>
- <subtitle>For inclusion in the EAP 5.1 Admin and Config Guide</subtitle>
- <productname>JBoss Enterprise Application Platform </productname>
+ <title>JBoss Security Guide</title>
+ <subtitle>Configuring platform and application security</subtitle>
+ <productname>JBoss Enterprise Application Platform</productname>
<productnumber>5.1</productnumber>
<edition>0</edition>
<pubsnumber>0</pubsnumber>
@@ -16,10 +16,14 @@
<corpauthor>
<inlinemediaobject>
<imageobject>
- <imagedata fileref="Common_Content/images/title_logo.svg" format="SVG"/>
+ <imagedata fileref="/images/title_logo.svg" format="SVG"/>
</imageobject>
</inlinemediaobject>
</corpauthor>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Common_Content/Legal_Notice.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Common_Content/Legal_Notice.xml">
+ <xi:fallback xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="fallback_content/Legal_Notice.xml" xmlns:xi="http://www.w3.org/2001/XInclude"></xi:include>
+ </xi:fallback>
+ </xi:include>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
</bookinfo>
Modified: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Preface.xml
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/Preface.xml 2010-02-17 02:56:54 UTC (rev 101058)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/Preface.xml 2010-02-22 06:09:11 UTC (rev 101228)
@@ -4,8 +4,10 @@
<preface id="pref-JBoss_Security_Chapter-Preface">
<title>Preface</title>
<xi:include href="Common_Content/Conventions.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude"><xi:fallback xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="Common_Content/Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- </xi:fallback>
+ <xi:include href="Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:fallback xmlns:xi="http://www.w3.org/2001/XInclude">
+ <xi:include href="Common_Content/Feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </xi:fallback>
</xi:include>
</preface>
Deleted: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/chap-Security_Configuration_And_Architecture.xml 2010-02-17 02:56:54 UTC (rev 101058)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml 2010-02-22 06:09:11 UTC (rev 101228)
@@ -1,3556 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-]>
-<chapter id="Security_on_JBoss">
- <title>Security on JBoss</title>
- <subtitle>J2EE Security Configuration and Architecture</subtitle>
- <para>
- Security is a fundamental part of any enterprise application. You need to be able to restrict who is allowed to access your applications and control what operations application users may perform. The J2EE specifications define a simple role-based security model for EJBs and web components. The JBoss component framework that handles security is the JBossSX extension framework. The JBossSX security extension provides support for both the role-based declarative J2EE security model and integration of custom security via a security proxy layer. The default implementation of the declarative security model is based on Java Authentication and Authorization Service (JAAS) login modules and subjects. The security proxy layer allows custom security that cannot be described using the declarative model to be added to an EJB in a way that is independent of the EJB business object. Before getting into the JBoss security implementation details, we will review EJB and servlet specificatio!
n security models, as well as JAAS to establish the foundation for these details.
- </para>
- <section id="Security_on_JBoss-J2EE_Declarative_Security_Overview">
- <title>J2EE Declarative Security Overview</title>
- <para>
- The J2EE security model declarative in that you describe the security roles and permissions in a standard XML descriptor rather than embedding security into your business component. This isolates security from business-level code because security tends to be more a function of where the component is deployed than an inherent aspect of the component's business logic. For example, consider an ATM component that is to be used to access a bank account. The security requirements, roles and permissions will vary independently of how you access the bank account, based on what bank is managing the account, where the ATM is located, and so on.
- </para>
- <para>
- Securing a J2EE application is based on the specification of the application security requirements via the standard J2EE deployment descriptors. You secure access to EJBs and web components in an enterprise application by using the <literal>ejb-jar.xml</literal> and <literal>web.xml</literal> deployment descriptors. The following sections look at the purpose and usage of the various security elements.
- </para>
- <section id="J2EE_Declarative_Security_Overview-Security_References">
- <title>Security References</title>
- <para>
- Both EJBs and servlets can declare one or more <literal>security-role-ref</literal> elements as shown in <xref linkend="Security_References-The_security_role_ref_element"/>. This element declares that a component is using the <literal>role-name</literal> value as an argument to the <literal>isCallerInRole(String)</literal> method. By using the <literal>isCallerInRole</literal> method, a component can verify whether the caller is in a role that has been declared with a <literal>security-role-ref/role-name</literal> element. The <literal>role-name</literal> element value must link to a <literal>security-role</literal> element through the <literal>role-link</literal> element. The typical use of <literal>isCallerInRole</literal> is to perform a security check that cannot be defined by using the role-based <literal>method-permissions</literal> elements.
- </para>
- <figure id="Security_References-The_security_role_ref_element">
- <title>The security-role-ref element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_security_role_ref.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="Security_References-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage."/> shows the use of <literal>security-role-ref</literal> in an <literal>ejb-jar.xml</literal>.
- </para>
- <example id="Security_References-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage.">
- <title>An ejb-jar.xml descriptor fragment that illustrates the security-role-ref element usage.</title>
- <programlisting><!-- A sample ejb-jar.xml fragment -->
-<ejb-jar>
- <enterprise-beans>
- <session>
- <ejb-name>ASessionBean</ejb-name>
- ...
- <security-role-ref>
- <role-name>TheRoleICheck</role-name>
- <role-link>TheApplicationRole</role-link>
- </security-role-ref>
- </session>
- </enterprise-beans>
- ...
-</ejb-jar>
-</programlisting>
- </example>
- <para>
- <xref linkend="Security_References-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage."/> shows the use of <literal>security-role-ref</literal> in a <literal>web.xml</literal>.
- </para>
- <example id="Security_References-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage.">
- <title>An example web.xml descriptor fragment that illustrates the security-role-ref element usage.</title>
- <programlisting><web-app>
- <servlet>
- <servlet-name>AServlet</servlet-name>
- ...
- <security-role-ref>
- <role-name>TheServletRole</role-name>
- <role-link>TheApplicationRole</role-link>
- </security-role-ref>
- </servlet>
- ...
-</web-app>
-</programlisting>
- </example>
- </section>
- <section id="J2EE_Declarative_Security_Overview-Security_Identity">
- <title>Security Identity</title>
- <para>
- An EJB has the capability to specify what identity an EJB should use when it invokes methods on other components using the <literal>security-identity</literal> element, shown in <xref linkend="Security_Identity-The_security_identity_element"/>
- </para>
- <figure id="Security_Identity-The_security_identity_element">
- <title>The security-identity element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_security_identity.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- The invocation identity can be that of the current caller, or it can be a specific role. The application assembler uses the <literal>security-identity</literal> element with a <literal>use-caller-identity</literal> child element to indicate that the current caller's identity should be propagated as the security identity for method invocations made by the EJB. Propagation of the caller's identity is the default used in the absence of an explicit <literal>security-identity</literal> element declaration.
- </para>
- <para>
- Alternatively, the application assembler can use the <literal>run-as/role-name</literal> child element to specify that a specific security role given by the <literal>role-name</literal> value should be used as the security identity for method invocations made by the EJB. Note that this does not change the caller's identity as seen by the <literal>EJBContext.getCallerPrincipal()</literal> method. Rather, the caller's security roles are set to the single role specified by the <literal>run-as/role-name</literal> element value. One use case for the <literal>run-as</literal> element is to prevent external clients from accessing internal EJBs. You accomplish this by assigning the internal EJB <literal>method-permission</literal> elements that restrict access to a role never assigned to an external client. EJBs that need to use internal EJB are then configured with a <literal>run-as/role-name</literal> equal to the restricted role. The following descriptor fragment t!
hat illustrates <literal>security-identity</literal> element usage.
- </para>
- <programlisting><!-- A sample ejb-jar.xml fragment -->
-<ejb-jar>
- <enterprise-beans>
- <session>
- <ejb-name>ASessionBean</ejb-name>
- <!-- ... -->
- <security-identity>
- <use-caller-identity/>
- </security-identity>
- </session>
- <session>
- <ejb-name>RunAsBean</ejb-name>
- <!-- ... -->
- <security-identity>
- <run-as>
- <description>A private internal role</description>
- <role-name>InternalRole</role-name>
- </run-as>
- </security-identity>
- </session>
- </enterprise-beans>
- <!-- ... -->
-</ejb-jar>
-</programlisting>
- <para>
- When you use <literal>run-as</literal> to assign a specific role to outgoing calls, JBoss associates a principal named <literal>anonymous</literal>. If you want another principal to be associated with the call, you need to associate a <literal>run-as-principal</literal> with the bean in the <literal>jboss.xml</literal> file. The following fragment associates a principal named <literal>internal</literal> with <literal>RunAsBean</literal> from the prior example.
- </para>
- <programlisting><session>
- <ejb-name>RunAsBean</ejb-name>
- <security-identity>
- <run-as-principal>internal</run-as-principal>
- </security-identity>
-</session>
-</programlisting>
- <para>
- The <literal>run-as</literal> element is also available in servlet definitions in a <literal>web.xml</literal> file. The following example shows how to assign the role <literal>InternalRole</literal> to a servlet:
- </para>
- <programlisting><servlet>
- <servlet-name>AServlet</servlet-name>
- <!-- ... -->
- <run-as>
- <role-name>InternalRole</role-name>
- </run-as>
-</servlet>
-</programlisting>
- <para>
- Calls from this servlet will be associated with the anonymous <literal>principal</literal>. The <literal>run-as-principal</literal> element is available in the <literal>jboss-web.xml</literal> file to assign a specific principal to go along with the <literal>run-as</literal> role. The following fragment shows how to associate a principal named <literal>internal</literal> to the servlet in the prior example.
- </para>
- <programlisting><servlet>
- <servlet-name>AServlet</servlet-name>
- <run-as-principal>internal</run-as-principal>
-</servlet>
-</programlisting>
- </section>
- <section id="J2EE_Declarative_Security_Overview-Security_roles">
- <title>Security roles</title>
- <para>
- The security role name referenced by either the <literal>security-role-ref</literal> or <literal>security-identity</literal> element needs to map to one of the application's declared roles. An application assembler defines logical security roles by declaring <literal>security-role</literal> elements. The <literal>role-name</literal> value is a logical application role name like Administrator, Architect, SalesManager, etc.
- </para>
- <para>
- The J2EE specifications note that it is important to keep in mind that the security roles in the deployment descriptor are used to define the logical security view of an application. Roles defined in the J2EE deployment descriptors should not be confused with the user groups, users, principals, and other concepts that exist in the target enterprise's operational environment. The deployment descriptor roles are application constructs with application domain-specific names. For example, a banking application might use role names such as BankManager, Teller, or Customer.
- </para>
- <figure id="Security_roles-The_security_role_element">
- <title>The security-role element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_security_role.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- In JBoss, a <literal>security-role</literal> element is only used to map <literal>security-role-ref/role-name</literal> values to the logical role that the component role references. The user's assigned roles are a dynamic function of the application's security manager, as you will see when we discuss the JBossSX implementation details. JBoss does not require the definition of <literal>security-role</literal> elements in order to declare method permissions. However, the specification of <literal>security-role</literal> elements is still a recommended practice to ensure portability across application servers and for deployment descriptor maintenance. <xref linkend="Security_roles-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage."/> shows the usage of the <literal>security-role</literal> in an <literal>ejb-jar.xml</literal> file.
- </para>
- <example id="Security_roles-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage.">
- <title>An ejb-jar.xml descriptor fragment that illustrates the security-role element usage.</title>
- <programlisting><!-- A sample ejb-jar.xml fragment -->
-<ejb-jar>
- <!-- ... -->
- <assembly-descriptor>
- <security-role>
- <description>The single application role</description>
- <role-name>TheApplicationRole</role-name>
- </security-role>
- </assembly-descriptor>
-</ejb-jar>
-</programlisting>
- </example>
- <para>
- <xref linkend="Security_roles-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage."/> shows the usage of the <literal>security-role</literal> in an <literal>web.xml</literal> file.
- </para>
- <example id="Security_roles-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage.">
- <title>An example web.xml descriptor fragment that illustrates the security-role element usage.</title>
- <programlisting><!-- A sample web.xml fragment -->
-<web-app>
- <!-- ... -->
- <security-role>
- <description>The single application role</description>
- <role-name>TheApplicationRole</role-name>
- </security-role>
-</web-app>
-</programlisting>
- </example>
- </section>
- <section id="J2EE_Declarative_Security_Overview-EJB_method_permissions">
- <title>EJB method permissions</title>
- <para>
- An application assembler can set the roles that are allowed to invoke an EJB's home and remote interface methods through method-permission element declarations.
- </para>
- <figure id="EJB_method_permissions-The_method_permissions_element">
- <title>The method-permissions element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_method_permission.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- Each <literal>method-permission</literal> element contains one or more role-name child elements that define the logical roles that are allowed to access the EJB methods as identified by method child elements. You can also specify an <literal>unchecked</literal> element instead of the <literal>role-name</literal> element to declare that any authenticated user can access the methods identified by method child elements. In addition, you can declare that no one should have access to a method that has the <literal>exclude-list</literal> element. If an EJB has methods that have not been declared as accessible by a role using a <literal>method-permission</literal> element, the EJB methods default to being excluded from use. This is equivalent to defaulting the methods into the <literal>exclude-list</literal>.
- </para>
- <figure id="EJB_method_permissions-The_method_element">
- <title>The method element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_method.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- There are three supported styles of method element declarations.
- </para>
- <para>
- The first is used for referring to all the home and component interface methods of the named enterprise bean:
- </para>
- <programlisting><method>
- <ejb-name>EJBNAME</ejb-name>
- <method-name>*</method-name>
-</method>
-</programlisting>
- <para>
- The second style is used for referring to a specified method of the home or component interface of the named enterprise bean:
- </para>
- <programlisting><method>
- <ejb-name>EJBNAME</ejb-name>
- <method-name>METHOD</method-name>
- </method>
-</programlisting>
- <para>
- If there are multiple methods with the same overloaded name, this style refers to all of the overloaded methods.
- </para>
- <para>
- The third style is used to refer to a specified method within a set of methods with an overloaded name:
- </para>
- <programlisting><method>
- <ejb-name>EJBNAME</ejb-name>
- <method-name>METHOD</method-name>
- <method-params>
- <method-param>PARAMETER_1</method-param>
- <!-- ... -->
- <method-param>PARAMETER_N</method-param>
- </method-params>
-</method>
-</programlisting>
- <para>
- The method must be defined in the specified enterprise bean's home or remote interface. The method-param element values are the fully qualified name of the corresponding method parameter type. If there are multiple methods with the same overloaded signature, the permission applies to all of the matching overloaded methods.
- </para>
- <para>
- The optional <literal>method-intf</literal> element can be used to differentiate methods with the same name and signature that are defined in both the home and remote interfaces of an enterprise bean.
- </para>
- <para>
- <xref linkend="EJB_method_permissions-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_method_permission_element_usage."/> provides complete examples of the <literal>method-permission</literal> element usage.
- </para>
- <example id="EJB_method_permissions-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_method_permission_element_usage.">
- <title>An ejb-jar.xml descriptor fragment that illustrates the method-permission element usage.</title>
- <programlisting><ejb-jar>
- <assembly-descriptor>
- <method-permission>
- <description>The employee and temp-employee roles may access any
- method of the EmployeeService bean </description>
- <role-name>employee</role-name>
- <role-name>temp-employee</role-name>
- <method>
- <ejb-name>EmployeeService</ejb-name>
- <method-name>*</method-name>
- </method>
- </method-permission>
- <method-permission>
- <description>The employee role may access the findByPrimaryKey,
- getEmployeeInfo, and the updateEmployeeInfo(String) method of
- the AardvarkPayroll bean </description>
- <role-name>employee</role-name>
- <method>
- <ejb-name>AardvarkPayroll</ejb-name>
- <method-name>findByPrimaryKey</method-name>
- </method>
- <method>
- <ejb-name>AardvarkPayroll</ejb-name>
- <method-name>getEmployeeInfo</method-name>
- </method>
- <method>
- <ejb-name>AardvarkPayroll</ejb-name>
- <method-name>updateEmployeeInfo</method-name>
- <method-params>
- <method-param>java.lang.String</method-param>
- </method-params>
- </method>
- </method-permission>
- <method-permission>
- <description>The admin role may access any method of the
- EmployeeServiceAdmin bean </description>
- <role-name>admin</role-name>
- <method>
- <ejb-name>EmployeeServiceAdmin</ejb-name>
- <method-name>*</method-name>
- </method>
- </method-permission>
- <method-permission>
- <description>Any authenticated user may access any method of the
- EmployeeServiceHelp bean</description>
- <unchecked/>
- <method>
- <ejb-name>EmployeeServiceHelp</ejb-name>
- <method-name>*</method-name>
- </method>
- </method-permission>
- <exclude-list>
- <description>No fireTheCTO methods of the EmployeeFiring bean may be
- used in this deployment</description>
- <method>
- <ejb-name>EmployeeFiring</ejb-name>
- <method-name>fireTheCTO</method-name>
- </method>
- </exclude-list>
- </assembly-descriptor>
-</ejb-jar>
-</programlisting>
- </example>
- </section>
- <section id="J2EE_Declarative_Security_Overview-Web_Content_Security_Constraints">
- <title>Web Content Security Constraints</title>
- <para>
- In a web application, security is defined by the roles that are allowed access to content by a URL pattern that identifies the protected content. This set of information is declared by using the <literal>web.xml</literal><literal>security-constraint</literal> element.
- </para>
- <figure id="Web_Content_Security_Constraints-The_security_constraint_element">
- <title>The security-constraint element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/webapp_security_constraint.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- The content to be secured is declared using one or more <literal>web-resource-collection</literal> elements. Each <literal>web-resource-collection</literal> element contains an optional series of <literal>url-pattern</literal> elements followed by an optional series of <literal>http-method</literal> elements. The <literal>url-pattern</literal> element value specifies a URL pattern against which a request URL must match for the request to correspond to an attempt to access secured content. The <literal>http-method</literal> element value specifies a type of HTTP request to allow.
- </para>
- <para>
- The optional <literal>user-data-constraint</literal> element specifies the requirements for the transport layer of the client to server connection. The requirement may be for content integrity (preventing data tampering in the communication process) or for confidentiality (preventing reading while in transit). The transport-guarantee element value specifies the degree to which communication between the client and server should be protected. Its values are <literal>NONE</literal>, <literal>INTEGRAL</literal>, and <literal>CONFIDENTIAL</literal>. A value of <literal>NONE</literal> means that the application does not require any transport guarantees. A value of <literal>INTEGRAL</literal> means that the application requires the data sent between the client and server to be sent in such a way that it can't be changed in transit. A value of <literal>CONFIDENTIAL</literal> means that the application requires the data to be transmitted in a fashion that prevents other ent!
ities from observing the contents of the transmission. In most cases, the presence of the <literal>INTEGRAL</literal> or <literal>CONFIDENTIAL</literal> flag indicates that the use of SSL is required.
- </para>
- <para>
- The optional <literal>login-config</literal> element is used to configure the authentication method that should be used, the realm name that should be used for rhw application, and the attributes that are needed by the form login mechanism.
- </para>
- <figure id="Web_Content_Security_Constraints-The_login_config_element">
- <title>The login-config element</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/webapp_login_config.jpg"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- The <literal>auth-method</literal> child element specifies the authentication mechanism for the web application. As a prerequisite to gaining access to any web resources that are protected by an authorization constraint, a user must have authenticated using the configured mechanism. Legal <literal>auth-method</literal> values are <literal>BASIC</literal>, <literal>DIGEST</literal>, <literal>FORM</literal>, and <literal>CLIENT-CERT</literal>. The <literal>realm-name</literal> child element specifies the realm name to use in HTTP basic and digest authorization. The <literal>form-login-config</literal> child element specifies the log in as well as error pages that should be used in form-based login. If the <literal>auth-method</literal> value is not <literal>FORM</literal>, then <literal>form-login-config</literal> and its child elements are ignored.
- </para>
- <para>
- As an example, the <literal>web.xml</literal> descriptor fragment given in <xref linkend="Web_Content_Security_Constraints-_A_web.xml_descriptor_fragment_which_illustrates_the_use_of_the_security_constraint_and_related_elements."/> indicates that any URL lying under the web application's <literal>/restricted</literal> path requires an <literal>AuthorizedUser</literal> role. There is no required transport guarantee and the authentication method used for obtaining the user identity is BASIC HTTP authentication.
- </para>
- <example id="Web_Content_Security_Constraints-_A_web.xml_descriptor_fragment_which_illustrates_the_use_of_the_security_constraint_and_related_elements.">
- <title> A web.xml descriptor fragment which illustrates the use of the security-constraint and related elements.</title>
- <programlisting><web-app>
- <!-- ... -->
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>Secure Content</web-resource-name>
- <url-pattern>/restricted/*</url-pattern>
- </web-resource-collection>
- <auth-constraint>
- <role-name>AuthorizedUser</role-name>
- </auth-constraint>
- <user-data-constraint>
- <transport-guarantee>NONE</transport-guarantee>
- </user-data-constraint>
- </security-constraint>
- <!-- ... -->
- <login-config>
- <auth-method>BASIC</auth-method>
- <realm-name>The Restricted Zone</realm-name>
- </login-config>
- <!-- ... -->
- <security-role>
- <description>The role required to access restricted content </description>
- <role-name>AuthorizedUser</role-name>
- </security-role>
-</web-app>
-</programlisting>
- </example>
- </section>
- <section id="J2EE_Declarative_Security_Overview-Enabling_Declarative_Security_in_JBoss">
- <title>Enabling Declarative Security in JBoss</title>
- <para>
- The J2EE security elements that have been covered so far describe the security requirements only from the application's perspective. Because J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The J2EE specifications omit these application server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model using JBoss server specific deployment descriptors. The details behind the security configuration are discussed in <xref linkend="Security_on_JBoss-The_JBoss_Security_Model"/>.
- </para>
- </section>
- </section>
- <section id="Security_on_JBoss-An_Introduction_to_JAAS">
- <title>An Introduction to JAAS</title>
- <para>
- The JBossSX framework is based on the JAAS API. It is important that you understand the basic elements of the JAAS API to understand the implementation details of JBossSX. The following sections provide an introduction to JAAS to prepare you for the JBossSX architecture discussion later in this chapter.
- </para>
- <section id="An_Introduction_to_JAAS-What_is_JAAS">
- <title>What is JAAS?</title>
- <para>
- The JAAS 1.0 API consists of a set of Java packages designed for user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with JDK 1.4+. Because the JBossSX framework uses only the authentication capabilities of JAAS to implement the declarative role-based J2EE security model, this introduction focuses on only that topic.
- </para>
- <para>
- JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can be achieved without changing the JBossSX security manager implementation. All that needs to change is the configuration of the authentication stack that JAAS uses.
- </para>
- <section id="What_is_JAAS-The_JAAS_Core_Classes">
- <title>The JAAS Core Classes</title>
- <para>
- The JAAS core classes can be broken down into three categories: common, authentication, and authorization. The following list presents only the common and authentication classes because these are the specific classes used to implement the functionality of JBossSX covered in this chapter.
- </para>
- <para>
- The are the common classes:
- </para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>Subject</literal> (<literal>javax.security.auth.Subject</literal>)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>Principal</literal> (<literal>java.security.Principal</literal>)
- </para>
- </listitem>
- </itemizedlist>
- <para>
- These are the authentication classes:
- </para>
- <itemizedlist spacing="compact">
- <listitem>
- <para>
- <literal>Callback</literal> (<literal>javax.security.auth.callback.Callback</literal>)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>CallbackHandler</literal> (<literal>javax.security.auth.callback.CallbackHandler</literal>)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>Configuration</literal> (<literal>javax.security.auth.login.Configuration</literal>)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>LoginContext</literal> (<literal>javax.security.auth.login.LoginContext</literal>)
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>LoginModule</literal> (<literal>javax.security.auth.spi.LoginModule</literal>)
- </para>
- </listitem>
- </itemizedlist>
- <section id="The_JAAS_Core_Classes-The_Subject_and_Principal_Classes">
- <title>The Subject and Principal Classes</title>
- <para>
- To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term subject to represent a request's source. The <literal>Subject</literal> class is the central class in JAAS. A <literal>Subject</literal> represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 <literal>java.security.Principal</literal> interface to represent a principal, which is essentially just a typed name.
- </para>
- <para>
- During the authentication process, a subject is populated with associated identities, or principals. A subject may have many principals. For example, a person may have a name principal (John Doe), a social security number principal (123-45-6789), and a username principal (johnd), all of which help distinguish the subject from other subjects. To retrieve the principals associated with a subject, two methods are available:
- </para>
- <programlisting>public Set getPrincipals() {...}
-public Set getPrincipals(Class c) {...}
-</programlisting>
- <para>
- The first method returns all principals contained in the subject. The second method returns only those principals that are instances of class <literal>c</literal> or one of its subclasses. An empty set is returned if the subject has no matching principals. Note that the <literal>java.security.acl.Group</literal> interface is a subinterface of <literal>java.security.Principal</literal>, so an instance in the principals set may represent a logical grouping of other principals or groups of principals.
- </para>
- </section>
- <section id="The_JAAS_Core_Classes-Authentication_of_a_Subject">
- <title>Authentication of a Subject</title>
- <para>
- Authentication of a subject requires a JAAS login. The login procedure consists of the following steps:
- </para>
- <orderedlist>
- <listitem>
- <para>
- An application instantiates a <literal>LoginContext</literal> and passes in the name of the login configuration and a <literal>CallbackHandler</literal> to populate the <literal>Callback</literal> objects, as required by the configuration <literal>LoginModule</literal>s.
- </para>
- </listitem>
- <listitem>
- <para>
- The <literal>LoginContext</literal> consults a <literal>Configuration</literal> to load all the <literal>LoginModules</literal> included in the named login configuration. If no such named configuration exists the <literal>other</literal> configuration is used as a default.
- </para>
- </listitem>
- <listitem>
- <para>
- The application invokes the <literal>LoginContext.login</literal> method.
- </para>
- </listitem>
- <listitem>
- <para>
- The login method invokes all the loaded <literal>LoginModule</literal>s. As each <literal>LoginModule</literal> attempts to authenticate the subject, it invokes the handle method on the associated <literal>CallbackHandler</literal> to obtain the information required for the authentication process. The required information is passed to the handle method in the form of an array of <literal>Callback</literal> objects. Upon success, the <literal>LoginModule</literal>s associate relevant principals and credentials with the subject.
- </para>
- </listitem>
- <listitem>
- <para>
- The <literal>LoginContext</literal> returns the authentication status to the application. Success is represented by a return from the login method. Failure is represented through a LoginException being thrown by the login method.
- </para>
- </listitem>
- <listitem>
- <para>
- If authentication succeeds, the application retrieves the authenticated subject using the <literal>LoginContext.getSubject</literal> method.
- </para>
- </listitem>
- <listitem>
- <para>
- After the scope of the subject authentication is complete, all principals and related information associated with the subject by the login method can be removed by invoking the <literal>LoginContext.logout</literal> method.
- </para>
- </listitem>
- </orderedlist>
- <para>
- The <literal>LoginContext</literal> class provides the basic methods for authenticating subjects and offers a way to develop an application that is independent of the underlying authentication technology. The <literal>LoginContext</literal> consults a <literal>Configuration</literal> to determine the authentication services configured for a particular application. <literal>LoginModule</literal> classes represent the authentication services. Therefore, you can plug different login modules into an application without changing the application itself. The following code shows the steps required by an application to authenticate a subject.
- </para>
- <programlisting>CallbackHandler handler = new MyHandler();
-LoginContext lc = new LoginContext("some-config", handler);
-
-try {
- lc.login();
- Subject subject = lc.getSubject();
-} catch(LoginException e) {
- System.out.println("authentication failed");
- e.printStackTrace();
-}
-
-// Perform work as authenticated Subject
-// ...
-
-// Scope of work complete, logout to remove authentication info
-try {
- lc.logout();
-} catch(LoginException e) {
- System.out.println("logout failed");
- e.printStackTrace();
-}
-
-// A sample MyHandler class
-class MyHandler
- implements CallbackHandler
-{
- public void handle(Callback[] callbacks) throws
- IOException, UnsupportedCallbackException
- {
- for (int i = 0; i < callbacks.length; i++) {
- if (callbacks[i] instanceof NameCallback) {
- NameCallback nc = (NameCallback)callbacks[i];
- nc.setName(username);
- } else if (callbacks[i] instanceof PasswordCallback) {
- PasswordCallback pc = (PasswordCallback)callbacks[i];
- pc.setPassword(password);
- } else {
- throw new UnsupportedCallbackException(callbacks[i],
- "Unrecognized Callback");
- }
- }
- }
-}
-</programlisting>
- <para>
- Developers integrate with an authentication technology by creating an implementation of the <literal>LoginModule</literal> interface. This allows an administrator to plug different authentication technologies into an application. You can chain together multiple <literal>LoginModule</literal>s to allow for more than one authentication technology to participate in the authentication process. For example, one <literal>LoginModule</literal> may perform username/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators.
- </para>
- <para>
- The life cycle of a <literal>LoginModule</literal> is driven by the <literal>LoginContext</literal> object against which the client creates and issues the login method. The process consists of two phases. The steps of the process are as follows:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- The <literal>LoginContext</literal> creates each configured <literal>LoginModule</literal> using its public no-arg constructor.
- </para>
- </listitem>
- <listitem>
- <para>
- Each <literal>LoginModule</literal> is initialized with a call to its initialize method. The <literal>Subject</literal> argument is guaranteed to be non-null. The signature of the initialize method is: <literal>public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- The <literal>login</literal> method is called to start the authentication process. For example, a method implementation might prompt the user for a username and password and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices, or simply extract user information from the underlying operating system. The validation of user identity by each <literal>LoginModule</literal> is considered phase 1 of JAAS authentication. The signature of the <literal>login</literal> method is <literal>boolean login() throws LoginException</literal>. A <literal>LoginException</literal> indicates failure. A return value of true indicates that the method succeeded, whereas a return valueof false indicates that the login module should be ignored.
- </para>
- </listitem>
- <listitem>
- <para>
- If the <literal>LoginContext</literal>'s overall authentication succeeds, <literal>commit</literal> is invoked on each <literal>LoginModule</literal>. If phase 1 succeeds for a <literal>LoginModule</literal>, then the commit method continues with phase 2 and associates the relevant principals, public credentials, and/or private credentials with the subject. If phase 1 fails for a <literal>LoginModule</literal>, then <literal>commit</literal> removes any previously stored authentication state, such as usernames or passwords. The signature of the <literal>commit</literal> method is: <literal>boolean commit() throws LoginException</literal>. Failure to complete the commit phase is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
- </para>
- </listitem>
- <listitem>
- <para>
- If the <literal>LoginContext</literal>'s overall authentication fails, then the <literal>abort</literal> method is invoked on each <literal>LoginModule</literal>. The <literal>abort</literal> method removes or destroys any authentication state created by the login or initialize methods. The signature of the <literal>abort</literal> method is <literal>boolean abort() throws LoginException</literal>. Failure to complete the <literal>abort</literal> phase is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
- </para>
- </listitem>
- <listitem>
- <para>
- To remove the authentication state after a successful login, the application invokes <literal>logout</literal> on the <literal>LoginContext</literal>. This in turn results in a <literal>logout</literal> method invocation on each <literal>LoginModule</literal>. The <literal>logout</literal> method removes the principals and credentials originally associated with the subject during the <literal>commit</literal> operation. Credentials should be destroyed upon removal. The signature of the <literal>logout</literal> method is: <literal>boolean logout() throws LoginException</literal>. Failure to complete the logout process is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- When a <literal>LoginModule</literal> must communicate with the user to obtain authentication information, it uses a <literal>CallbackHandler</literal> object. Applications implement the <literal>CallbackHandler</literal> interface and pass it to the LoginContext, which forwards it directly to the underlying login modules. Login modules use the <literal>CallbackHandler</literal> both to gather input from users, such as a password or smart card PIN, and to supply information to users, such as status information. By allowing the application to specify the <literal>CallbackHandler</literal>, underlying <literal>LoginModule</literal>s remain independent from the different ways applications interact with users. For example, a <literal>CallbackHandler</literal>'s implementation for a GUI application might display a window to solicit user input. On the other hand, a <literal>callbackhandler</literal>'s implementation for a non-GUI environment, such as an applicatio!
n server, might simply obtain credential information by using an application server API. The <literal>callbackhandler</literal> interface has one method to implement:
- </para>
- <programlisting>void handle(Callback[] callbacks)
- throws java.io.IOException,
- UnsupportedCallbackException;
-</programlisting>
- <para>
- The <literal>Callback</literal> interface is the last authentication class we will look at. This is a tagging interface for which several default implementations are provided, including the <literal>NameCallback</literal> and <literal>PasswordCallback</literal> used in an earlier example. A <literal>LoginModule</literal> uses a <literal>Callback</literal> to request information required by the authentication mechanism. <literal>LoginModule</literal>s pass an array of <literal>Callback</literal>s directly to the <literal>CallbackHandler.handle</literal> method during the authentication's login phase. If a <literal>callbackhandler</literal> does not understand how to use a <literal>Callback</literal> object passed into the handle method, it throws an <literal>UnsupportedCallbackException</literal> to abort the login call.
- </para>
- </section>
- </section>
- </section>
- </section>
- <section id="Security_on_JBoss-The_JBoss_Security_Model">
- <title>The JBoss Security Model</title>
- <para>
- Similar to the rest of the JBoss architecture, security at the lowest level is defined as a set of interfaces for which alternate implementations may be provided. Three basic interfaces define the JBoss server security layer: <literal>org.jboss.security.AuthenticationManager</literal>, <literal>org.jboss.security.RealmMapping</literal>, and <literal>org.jboss.security.SecurityProxy</literal>. <xref linkend="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements."/> shows a class diagram of the security interfaces and their relationship to the EJB container architecture.
- </para>
- <figure id="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements.">
- <title>The key security model interfaces and their relationship to the JBoss server EJB container elements.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-6.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- The light blue classes represent the security interfaces while the yellow classes represent the EJB container layer. The two interfaces required for the implementation of the J2EE security model are <literal>org.jboss.security.AuthenticationManager</literal> and <literal>org.jboss.security.RealmMapping</literal>. The roles of the security interfaces presented in <xref linkend="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements."/> are summarized in the following list.
- </para>
- <itemizedlist>
- <listitem>
- <para><classname>AuthenticationManager</classname>: This interface is responsible for validating credentials associated with principals. Principals are identities, such as usernames, employee numbers, and social security numbers. Credentials are proof of the identity, such as passwords, session keys, and digital signatures. The <literal>isValid</literal> method is invoked to determine whether a user identity and associated credentials as known in the operational environment are valid proof of the user's identity.
- </para>
- </listitem>
- <listitem>
- <para><classname>RealmMapping</classname>: This interface is responsible for principal mapping and role mapping. The <literal>getPrincipal</literal> method takes a user identity as known in the operational environment and returns the application domain identity. The <literal>doesUserHaveRole</literal> method validates that the user identity in the operation environment has been assigned the indicated role from the application domain.
- </para>
- </listitem>
- <listitem>
- <para><classname>SecurityProxy</classname>: This interface describes the requirements for a custom <literal>SecurityProxyInterceptor</literal> plugin. A <literal>SecurityProxy</literal> allows for the externalization of custom security checks on a per-method basis for both the EJB home and remote interface methods.
- </para>
- </listitem>
- <listitem>
- <para><classname>SubjectSecurityManager</classname>: This is a subinterface of <literal>AuthenticationManager</literal> that adds accessor methods for obtaining the security domain name of the security manager and the current thread's authenticated <literal>Subject</literal>.
- </para>
- </listitem>
- <listitem>
- <para><classname>SecurityDomain</classname>: This is an extension of the <literal>AuthenticationManager</literal>, <literal>RealmMapping</literal>, and <literal>SubjectSecurityManager</literal> interfaces. <classname>SecurityDomain</classname> is the recommended way to implement security in components, because of the advantages the JAAS Subject offers, and the increased support offered to to ASP-style application and resource deployments. A <literal>java.security.KeyStore</literal>, and the JSSE <literal>com.sun.net.ssl.KeyManagerFactory</literal> and <literal>com.sun.net.ssl.TrustManagerFactory</literal> interfaces are included in the class.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Note that the <literal>AuthenticationManager</literal>, <literal>RealmMapping</literal> and <literal>SecurityProxy</literal> interfaces have no association to JAAS related classes. Although the JBossSX framework is heavily dependent on JAAS, the basic security interfaces required for implementation of the J2EE security model are not. The JBossSX framework is simply an implementation of the basic security plug-in interfaces that are based on JAAS. </para>
- <para>The component diagram presented in <xref linkend="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer."/> illustrates this fact. The implication of this plug-in architecture is that you are free to replace the JAAS-based JBossSX implementation classes with your own custom security manager implementation that does not make use of JAAS, if you so desire. You'll see how to do this when you look at the JBossSX MBeans available for the configuration of JBossSX in <xref linkend="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer."/>.
- </para>
- <figure id="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer.">
- <title>The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-7.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <section id="The_JBoss_Security_Model-Enabling_Declarative_Security_in_JBoss_Revisited">
- <title>Enabling Declarative Security in JBoss Revisited</title>
- <para>
- Earlier in this chapter, the discussion of the J2EE standard security model ended with a requirement for the use of JBoss server-specific deployment descriptor to enable security. The details of this configuration are presented here. <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_security_element_subsets_of_the_JBoss_server_jboss.xml_and_jboss_web.xml_deployment_descriptors."/> shows the JBoss-specific EJB and web application deployment descriptor's security-related elements.
- </para>
- <figure id="Enabling_Declarative_Security_in_JBoss_Revisited-The_security_element_subsets_of_the_JBoss_server_jboss.xml_and_jboss_web.xml_deployment_descriptors.">
- <title>The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-8.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>The value of a <literal>security-domain</literal> element specifies the JNDI name of the security manager interface implementation that JBoss uses for the EJB and web containers. This is an object that implements both of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces. When specified as a top-level element it defines what security domain in effect for all EJBs in the deployment unit. This is the typical usage because mixing security managers within a deployment unit complicates inter-component operation and administration.
- </para>
- <para>To specify the security domain for an individual EJB, you specify the <literal>security-domain</literal> at the container configuration level. This will override any top-level security-domain element.
- </para>
- <para>The <literal>unauthenticated-principal</literal> element specifies the name to use for the <literal>Principal</literal> object returned by the <literal>EJBContext.getUserPrincipal</literal> method when an unauthenticated user invokes an EJB. Note that this conveys no special permissions to an unauthenticated caller. Its primary purpose is to allow unsecured servlets and JSP pages to invoke unsecured EJBs and allow the target EJB to obtain a non-null <literal>Principal</literal> for the caller using the <literal>getUserPrincipal</literal> method. This is a J2EE specification requirement.
- </para>
- <para>The <literal>security-proxy</literal> element identifies a custom security proxy implementation that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. This may be an implementation of the <literal>org.jboss.security.SecurityProxy</literal> interface, or just an object that implements methods in the home, remote, local home or local interfaces of the EJB to secure without implementing any common interface. If the given class does not implement the <literal>SecurityProxy</literal> interface, the instance must be wrapped in a <literal>SecurityProxy</literal> implementation that delegates the method invocations to the object. The <literal>org.jboss.security.SubjectSecurityProxy</literal> is an example <literal>SecurityProxy</literal> implementation used by the default JBossSX installation.
- </para>
- <para>
- Take a look at a simple example of a custom <literal>SecurityProxy</literal> in the context of a trivial stateless session bean. The custom <literal>SecurityProxy</literal> validates that no one invokes the bean's <literal>echo</literal> method with a four-letter word as its argument. This is a check that is not possible with role-based security; you cannot define a <literal>FourLetterEchoInvoker</literal> role because the security context is the method argument, not a property of the caller. The code for the custom <literal>SecurityProxy</literal> is given in <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_example_1_custom_EchoSecurityProxy_implementation_that_enforces_the_echo_argument_based_security_constraint."/>, and the full source code is available in the <literal>src/main/org/jboss/book/security/ex1</literal> directory of the book examples.
- </para>
- <example id="Enabling_Declarative_Security_in_JBoss_Revisited-The_example_1_custom_EchoSecurityProxy_implementation_that_enforces_the_echo_argument_based_security_constraint.">
- <title>The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint.</title>
- <programlisting>package org.jboss.book.security.ex1;
-
-import java.lang.reflect.Method;
-import javax.ejb.EJBContext;
-
-import org.apache.log4j.Category;
-
-import org.jboss.security.SecurityProxy;
-
-/** A simple example of a custom SecurityProxy implementation
- * that demonstrates method argument based security checks.
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.4 $
- */
-public class EchoSecurityProxy implements SecurityProxy
-{
- Category log = Category.getInstance(EchoSecurityProxy.class);
- Method echo;
-
- public void init(Class beanHome, Class beanRemote,
- Object securityMgr)
- throws InstantiationException
- {
- log.debug("init, beanHome="+beanHome
- + ", beanRemote="+beanRemote
- + ", securityMgr="+securityMgr);
- // Get the echo method for equality testing in invoke
- try {
- Class[] params = {String.class};
- echo = beanRemote.getDeclaredMethod("echo", params);
- } catch(Exception e) {
- String msg = "Failed to finde an echo(String) method";
- log.error(msg, e);
- throw new InstantiationException(msg);
- }
- }
-
- public void setEJBContext(EJBContext ctx)
- {
- log.debug("setEJBContext, ctx="+ctx);
- }
-
- public void invokeHome(Method m, Object[] args)
- throws SecurityException
- {
- // We don't validate access to home methods
- }
-
- public void invoke(Method m, Object[] args, Object bean)
- throws SecurityException
- {
- log.debug("invoke, m="+m);
- // Check for the echo method
- if (m.equals(echo)) {
- // Validate that the msg arg is not 4 letter word
- String arg = (String) args[0];
- if (arg == null || arg.length() == 4)
- throw new SecurityException("No 4 letter words");
- }
- // We are not responsible for doing the invoke
- }
-}
-
-</programlisting>
- </example>
- <para>
- The <literal>EchoSecurityProxy</literal> checks that the method to be invoked on the bean instance corresponds to the <literal>echo(String)</literal> method loaded the init method. If there is a match, the method argument is obtained and its length compared against 4 or null. Either case results in a <literal>SecurityException</literal> being thrown. Certainly this is a contrived example, but only in its application. It is a common requirement that applications must perform security checks based on the value of method arguments. The point of the example is to demonstrate how custom security beyond the scope of the standard declarative security model can be introduced independent of the bean implementation. This allows the specification and coding of the security requirements to be delegated to security experts. Since the security proxy layer can be done independent of the bean implementation, security can be changed to match the deployment environment requirements.
- </para>
- <para>
- The associated <literal>jboss.xml</literal> descriptor that installs the <literal>EchoSecurityProxy</literal> as the custom proxy for the <literal>EchoBean</literal> is given in <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_jboss.xml_descriptor_which_configures_the_EchoSecurityProxy_as_the_custom_security_proxy_for_the_EchoBean."/>.
- </para>
- <example id="Enabling_Declarative_Security_in_JBoss_Revisited-The_jboss.xml_descriptor_which_configures_the_EchoSecurityProxy_as_the_custom_security_proxy_for_the_EchoBean.">
- <title>The jboss.xml descriptor, which configures the EchoSecurityProxy as the custom security proxy for the EchoBean.</title>
- <programlisting><jboss>
- <security-domain>java:/jaas/other</security-domain>
-
- <enterprise-beans>
- <session>
- <ejb-name>EchoBean</ejb-name>
- <security-proxy>org.jboss.book.security.ex1.EchoSecurityProxy</security-proxy>
- </session>
- </enterprise-beans>
-</jboss>
-</programlisting>
- </example>
- <para>
- Now test the custom proxy by running a client that attempts to invoke the <literal>EchoBean.echo</literal> method with the arguments <literal>Hello</literal> and <literal>Four</literal> as illustrated in this fragment:
- </para>
- <programlisting>public class ExClient
-{
- public static void main(String args[])
- throws Exception
- {
- Logger log = Logger.getLogger("ExClient");
- log.info("Looking up EchoBean");
-
- InitialContext iniCtx = new InitialContext();
- Object ref = iniCtx.lookup("EchoBean");
- EchoHome home = (EchoHome) ref;
- Echo echo = home.create();
-
- log.info("Created Echo");
- log.info("Echo.echo('Hello') = "+echo.echo("Hello"));
- log.info("Echo.echo('Four') = "+echo.echo("Four"));
- }
-}
-</programlisting>
- <para>
- The first call should succeed, while the second should fail due to the fact that <literal>Four</literal> is a four-letter word. Run the client as follows using Ant from the examples directory:
- </para>
- <programlisting>[examples]$ ant -Dchap=security -Dex=1 run-example
-run-example1:
-...
- [echo] Waiting for 5 seconds for deploy...
- [java] [INFO,ExClient] Looking up EchoBean
- [java] [INFO,ExClient] Created Echo
- [java] [INFO,ExClient] Echo.echo('Hello') = Hello
- [java] Exception in thread "main" java.rmi.AccessException: SecurityException; nested exception is:
- [java] java.lang.SecurityException: No 4 letter words
-...
- [java] Caused by: java.lang.SecurityException: No 4 letter words
-...
-</programlisting>
- <para>
- The result is that the <literal>echo('Hello')</literal> method call succeeds as expected and the <literal>echo('Four')</literal> method call results in a rather messy looking exception, which is also expected. The above output has been truncated to fit in the book. The key part to the exception is that the <literal>SecurityException("No 4 letter words")</literal> generated by the <literal>EchoSecurityProxy</literal> was thrown to abort the attempted method invocation as desired.
- </para>
- </section>
- </section>
- <section id="Security_on_JBoss-The_JBoss_Security_Extension_Architecture">
- <title>The JBoss Security Extension Architecture</title>
- <para>
- The preceding discussion of the general JBoss security layer has stated that the JBossSX security extension framework is an implementation of the security layer interfaces. This is the primary purpose of the JBossSX framework. The details of the implementation are interesting in that it offers a great deal of customization for integration into existing security infrastructures. A security infrastructure can be anything from a database or LDAP server to a sophisticated security software suite. The integration flexibility is achieved using the pluggable authentication model available in the JAAS framework.
- </para>
- <para>
- The heart of the JBossSX framework is <literal>org.jboss.security.plugins.JaasSecurityManager</literal>. This is the default implementation of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces. <xref linkend="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager."/> shows how the <literal>JaasSecurityManager</literal> integrates into the EJB and web container layers based on the <literal>security-domain</literal> element of the corresponding component deployment descriptor.
- </para>
- <figure id="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager.">
- <title>The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-9.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager."/> depicts an enterprise application that contains both EJBs and web content secured under the security domain <literal>jwdomain</literal>. The EJB and web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the <literal>security-domain</literal> element value in the <literal>jboss.xml</literal> and <literal>jboss-web.xml</literal> descriptors is used to obtain the security manager instance associated with the container. The security interceptor then uses the security manager to perform its role. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container.
- </para>
- <para>
- The JBossSX <literal>JaasSecurityManager</literal> implementation performs security checks based on the information associated with the <literal>Subject</literal> instance that results from executing the JAAS login modules configured under the name matching the <literal>security-domain</literal> element value. We will drill into the <literal>JaasSecurityManager</literal> implementation and its use of JAAS in the following section.
- </para>
- <section id="The_JBoss_Security_Extension_Architecture-How_the_JaasSecurityManager_Uses_JAAS">
- <title>How the JaasSecurityManager Uses JAAS</title>
- <para>
- The <literal>JaasSecurityManager</literal> uses the JAAS packages to implement the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interface behavior. In particular, its behavior derives from the execution of the login module instances that are configured under the name that matches the security domain to which the <literal>JaasSecurityManager</literal> has been assigned. The login modules implement the security domain's principal authentication and role-mapping behavior. Thus, you can use the <literal>JaasSecurityManager</literal> across different security domains simply by plugging in different login module configurations for the domains.
- </para>
- <para>
- To illustrate the details of the <literal>JaasSecurityManager</literal>'s usage of the JAAS authentication process, you will walk through a client invocation of an EJB home method invocation. The prerequisite setting is that the EJB has been deployed in the JBoss server and its home interface methods have been secured using <literal>method-permission</literal> elements in the <literal>ejb-jar.xml</literal> descriptor, and it has been assigned a security domain named <literal>jwdomain</literal> using the <literal>jboss.xml</literal> descriptor <literal>security-domain</literal> element.
- </para>
- <figure id="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation.">
- <title>An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/authsteps.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- <xref linkend="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation."/> provides a view of the client to server communication we will discuss. The numbered steps shown are:
- </para>
- <orderedlist>
- <listitem>
- <para>
- The client first has to perform a JAAS login to establish the principal and credentials for authentication, and this is labeled <emphasis>Client Side Login</emphasis> in the figure. This is how clients establish their login identities in JBoss. Support for presenting the login information via JNDI <literal>InitialContext</literal> properties is provided via an alternate configuration. A JAAS login entails creating a <literal>LoginContext</literal> instance and passing the name of the configuration to use. The configuration name is <literal>other</literal>. This one-time login associates the login principal and credentials with all subsequent EJB method invocations. Note that the process might not authenticate the user. The nature of the client-side login depends on the login module configuration that the client uses. In this example, the <literal>other</literal> client-side login configuration entry is set up to use the <literal>ClientLoginModule</literal> module (an !
<literal>org.jboss.security.ClientLoginModule</literal>). This is the default client side module that simply binds the username and password to the JBoss EJB invocation layer for later authentication on the server. The identity of the client is not authenticated on the client.
- </para>
- </listitem>
- <listitem>
- <para>
- Later, the client obtains the EJB home interface and attempts to create a bean. This event is labeled as <emphasis>Home Method Invocation</emphasis>. This results in a home interface method invocation being sent to the JBoss server. The invocation includes the method arguments passed by the client along with the user identity and credentials from the client-side JAAS login performed in step 1.
- </para>
- </listitem>
- <listitem>
- <para>
- On the server side, the security interceptor first requires authentication of the user invoking the call, which, as on the client side, involves a JAAS login.
- </para>
- </listitem>
- <listitem>
- <para>
- The security domain under which the EJB is secured determines the choice of login modules. The security domain name is used as the login configuration entry name passed to the <literal>LoginContext</literal> constructor. The EJB security domain is <literal>jwdomain</literal>. If the JAAS login authenticates the user, a JAAS <literal>Subject</literal> is created that contains the following in its <literal>PrincipalsSet</literal>:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- A <literal>java.security.Principal</literal> that corresponds to the client identity as known in the deployment security environment.
- </para>
- </listitem>
- <listitem>
- <para>
- A <literal>java.security.acl.Group</literal> named <literal>Roles</literal> that contains the role names from the application domain to which the user has been assigned. <literal>org.jboss.security.SimplePrincipal</literal> objects are used to represent the role names; <literal>SimplePrincipal</literal> is a simple string-based implementation of <literal>Principal</literal>. These roles are used to validate the roles assigned to methods in <literal>ejb-jar.xml</literal> and the <literal>EJBContext.isCallerInRole(String)</literal> method implementation.
- </para>
- </listitem>
- <listitem>
- <para>
- An optional <literal>java.security.acl.Group</literal> named <literal>CallerPrincipal</literal>, which contains a single <literal>org.jboss.security.SimplePrincipal</literal> that corresponds to the identity of the application domain's caller. The <literal>CallerPrincipal</literal> sole group member will be the value returned by the <literal>EJBContext.getCallerPrincipal()</literal> method. The purpose of this mapping is to allow a <literal>Principal</literal> as known in the operational security environment to map to a <literal>Principal</literal> with a name known to the application. In the absence of a <literal>CallerPrincipal</literal> mapping the deployment security environment principal is used as the <literal>getCallerPrincipal</literal> method value. That is, the operational principal is the same as the application domain principal.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>
- The final step of the security interceptor check is to verify that the authenticated user has permission to invoke the requested method This is labeled as <emphasis>Server Side Authorization</emphasis> in <xref linkend="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation."/>. Performing the authorization this entails the following steps:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Obtain the names of the roles allowed to access the EJB method from the EJB container. The role names are determined by <literal>ejb-jar.xml</literal> descriptor role-name elements of all <literal>method-permission</literal> elements containing the invoked method.
- </para>
- </listitem>
- <listitem>
- <para>
- If no roles have been assigned, or the method is specified in an <literal>exclude-list</literal> element, then access to the method is denied. Otherwise, the <literal>doesUserHaveRole</literal> method is invoked on the security manager by the security interceptor to see if the caller has one of the assigned role names. This method iterates through the role names and checks if the authenticated user's Subject <literal>Roles</literal> group contains a <literal>SimplePrincipal</literal> with the assigned role name. Access is allowed if any role name is a member of the <literal>Roles</literal> group. Access is denied if none of the role names are members.
- </para>
- </listitem>
- <listitem>
- <para>
- If the EJB was configured with a custom security proxy, the method invocation is delegated to it. If the security proxy wants to deny access to the caller, it will throw a <literal>java.lang.SecurityException</literal>. If no <literal>SecurityException</literal> is thrown, access to the EJB method is allowed and the method invocation passes to the next container interceptor. Note that the <literal>SecurityProxyInterceptor</literal> handles this check and this interceptor is not shown.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- </orderedlist>
- <para>
- Every secured EJB method invocation, or secured web content access, requires the authentication and authorization of the caller because security information is handled as a stateless attribute of the request that must be presented and validated on each request. This can be an expensive operation if the JAAS login involves client-to-server communication. Because of this, the <literal>JaasSecurityManager</literal> supports the notion of an authentication cache that is used to store principal and credential information from previous successful logins. You can specify the authentication cache instance to use as part of the <literal>JaasSecurityManager</literal> configuration as you will see when the associated MBean service is discussed in following section. In the absence of any user-defined cache, a default cache that maintains credential information for a configurable period of time is used.
- </para>
- </section>
- <section id="The_JBoss_Security_Extension_Architecture-The_JaasSecurityManagerService_MBean">
- <title>The JaasSecurityManagerService MBean</title>
- <para>
- The <literal>JaasSecurityManagerService</literal> MBean service manages security managers. Although its name begins with <emphasis>Jaas</emphasis>, the security managers it handles need not use JAAS in their implementation. The name arose from the fact that the default security manager implementation is the <literal>JaasSecurityManager</literal>. The primary role of the <literal>JaasSecurityManagerService</literal> is to externalize the security manager implementation. You can change the security manager implementation by providing an alternate implementation of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces.
- </para>
- <para>
- The second fundamental role of the <literal>JaasSecurityManagerService</literal> is to provide a JNDI <literal>javax.naming.spi.ObjectFactory</literal> implementation to allow for simple code-free management of the JNDI name to security manager implementation mapping. It has been mentioned that security is enabled by specifying the JNDI name of the security manager implementation via the <literal>security-domain</literal> deployment descriptor element. When you specify a JNDI name, there has to be an object-binding there to use. To simplify the setup of the JNDI name to security manager bindings, the <literal>JaasSecurityManagerService</literal> manages the association of security manager instances to names by binding a next naming system reference with itself as the JNDI ObjectFactory under the name <literal>java:/jaas</literal>. This allows one to use a naming convention of the form <literal>java:/jaas/XYZ</literal> as the value for the <literal>security-domain</liter!
al> element, and the security manager instance for the <literal>XYZ</literal> security domain will be created as needed for you. The security manager for the domain <literal>XYZ</literal> is created on the first lookup against the <literal>java:/jaas/XYZ</literal> binding by creating an instance of the class specified by the <literal>SecurityManagerClassName</literal> attribute using a constructor that takes the name of the security domain. For example, consider the following container security configuration snippet:
- </para>
- <programlisting><jboss>
- <!-- Configure all containers to be secured under the "hades" security domain -->
- <security-domain>java:/jaas/hades</security-domain>
- <!-- ... -->
-</jboss>
-</programlisting>
- <para>
- Any lookup of the name <literal>java:/jaas/hades</literal> will return a security manager instance that has been associated with the security domain named <literal>hades</literal>. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the <literal>JaasSecurityManagerService</literal><literal>SecurityManagerClassName</literal> attribute.
- </para>
- <para>
- The <literal>JaasSecurityManagerService</literal> MBean is configured by default for use in the standard JBoss distribution, and you can often use the default configuration as is. The configurable attributes of the <literal>JaasSecurityManagerService</literal> include:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">SecurityManagerClassName</emphasis>: The name of the class that provides the security manager implementation. The implementation must support both the <literal>org.jboss.security.AuthenticationManager</literal> and <literal>org.jboss.security.RealmMapping</literal> interfaces. If not specified this defaults to the JAAS-based <literal>org.jboss.security.plugins.JaasSecurityManager</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">CallbackHandlerClassName</emphasis>: The name of the class that provides the <literal>javax.security.auth.callback.CallbackHandler</literal> implementation used by the <literal>JaasSecurityManager</literal>. You can override the handler used by the <literal>JaasSecurityManager</literal> if the default implementation (<literal>org.jboss.security.auth.callback.SecurityAssociationHandler</literal>) does not meet your needs. This is a rather deep configuration that generally should not be set unless you know what you are doing.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">SecurityProxyFactoryClassName</emphasis>: The name of the class that provides the <literal>org.jboss.security.SecurityProxyFactory</literal> implementation. If not specified this defaults to <literal>org.jboss.security.SubjectSecurityProxyFactory</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">AuthenticationCacheJndiName</emphasis>: Specifies the location of the security credential cache policy. This is first treated as an <literal>ObjectFactory</literal> location capable of returning <literal>CachePolicy</literal> instances on a per-security-domain basis. This is done by appending the name of the security domain to this name when looking up the <literal>CachePolicy</literal> for a domain. If this fails, the location is treated as a single <literal>CachePolicy</literal> for all security domains. As a default, a timed cache policy is used.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">DefaultCacheTimeout</emphasis>: Specifies the default timed cache policy timeout in seconds. The default value is 1800 seconds (30 minutes). The value you use for the timeout is a tradeoff between frequent authentication operations and how long credential information may be out of sync with respect to the security information store. If you want to disable caching of security credentials, set this to 0 to force authentication to occur every time. This has no affect if the <literal>AuthenticationCacheJndiName</literal> has been changed from the default value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">DefaultCacheResolution</emphasis>: Specifies the default timed cache policy resolution in seconds. This controls the interval at which the cache current timestamp is updated and should be less than the <literal>DefaultCacheTimeout</literal> in order for the timeout to be meaningful. The default resolution is 60 seconds(1 minute). This has no affect if the <literal>AuthenticationCacheJndiName</literal> has been changed from the default value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">DefaultUnauthenticatedPrincipal</emphasis>: Specifies the principal to use for unauthenticated users. This setting makes it possible to set default permissions for users who have not been authenticated.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The <literal>JaasSecurityManagerService</literal> also supports a number of useful operations. These include flushing any security domain authentication cache at runtime, getting the list of active users in a security domain authentication cache, and any of the security manager interface methods.
- </para>
- <para>
- Flushing a security domain authentication cache can be used to drop all cached credentials when the underlying store has been updated and you want the store state to be used immediately. The MBean operation signature is: <literal>public void flushAuthenticationCache(String securityDomain)</literal>.
- </para>
- <para>
- This can be invoked programmatically using the following code snippet:
- </para>
- <programlisting>MBeanServer server = ...;
-String jaasMgrName = "jboss.security:service=JaasSecurityManager";
-ObjectName jaasMgr = new ObjectName(jaasMgrName);
-Object[] params = {domainName};
-String[] signature = {"java.lang.String"};
-server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);
-</programlisting>
- <para>
- Getting the list of active users provides a snapshot of the <literal>Principals</literal> keys in a security domain authentication cache that are not expired. The MBean operation signature is: <literal>public List getAuthenticationCachePrincipals(String securityDomain)</literal>.
- </para>
- <para>
- This can be invoked programmatically using the following code snippet:
- </para>
- <programlisting>MBeanServer server = ...;
-String jaasMgrName = "jboss.security:service=JaasSecurityManager";
-ObjectName jaasMgr = new ObjectName(jaasMgrName);
-Object[] params = {domainName};
-String[] signature = {"java.lang.String"};
-List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals",
- params, signature);
-</programlisting>
- <para>
- The security manager has a few additional access methods.
- </para>
- <programlisting>public boolean isValid(String securityDomain, Principal principal, Object credential);
-public Principal getPrincipal(String securityDomain, Principal principal);
-public boolean doesUserHaveRole(String securityDomain, Principal principal,
- Object credential, Set roles);
-public Set getUserRoles(String securityDomain, Principal principal, Object credential);
-</programlisting>
- <para>
- They provide access to the corresponding <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interface method of the associated security domain named by the <literal>securityDomain</literal> argument.
- </para>
- </section>
- <section id="The_JBoss_Security_Extension_Architecture-The_JaasSecurityDomain_MBean">
- <title>The JaasSecurityDomain MBean</title>
- <para>
- The <literal>org.jboss.security.plugins.JaasSecurityDomain</literal> is an extension of <literal>JaasSecurityManager</literal> that adds the notion of a <literal>KeyStore</literal>, a JSSE <literal>KeyManagerFactory</literal> and a <literal>TrustManagerFactory</literal> for supporting SSL and other cryptographic use cases. The additional configurable attributes of the <literal>JaasSecurityDomain</literal> include:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">KeyStoreType</emphasis>: The type of the <literal>KeyStore</literal> implementation. This is the type argument passed to the <literal>java.security.KeyStore.getInstance(String type)</literal> factory method. The default is <literal>JKS</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">KeyStoreURL</emphasis>: A URL to the location of the <literal>KeyStore</literal> database. This is used to obtain an <literal>InputStream</literal> to initialize the <literal>KeyStore</literal>. If the string is not a value URL, it is treated as a file.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">KeyStorePass</emphasis>: The password associated with the <literal>KeyStore</literal> database contents. The <literal>KeyStorePass</literal> is also used in combination with the <literal>Salt</literal> and <literal>IterationCount</literal> attributes to create a PBE secret key used with the encode/decode operations. The <literal>KeyStorePass</literal> attribute value format is one of the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- The plaintext password for the <literal>KeyStore</literal> The <literal>toCharArray()</literal> value of the string is used without any manipulation.
- </para>
- </listitem>
- <listitem>
- <para>
- A command to execute to obtain the plaintext password. The format is <literal>{EXT}...</literal> where the <literal>...</literal> is the exact command line that will be passed to the <literal>Runtime.exec(String)</literal> method to execute a platform-specific command. The first line of the command output is used as the password.
- </para>
- </listitem>
- <listitem>
- <para>
- A class to create to obtain the plaintext password. The format is <literal>{CLASS}classname[:ctorarg]</literal> where the <literal>[:ctorarg]</literal> is an optional string that will be passed to the constructor when instantiating the <literal>classname</literal>. The password is obtained from classname by invoking a <literal>toCharArray()</literal> method if found, otherwise, the <literal>toString()</literal> method is used.
- </para>
- </listitem>
- </itemizedlist>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">Salt</emphasis>: The <literal>PBEParameterSpec</literal> salt value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">IterationCount</emphasis>: The <literal>PBEParameterSpec</literal> iteration count value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">TrustStoreType</emphasis>: The type of the <literal>TrustStore</literal> implementation. This is the type argument passed to the <literal>java.security.KeyStore.getInstance(String type)</literal> factory method. The default is <literal>JKS</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">TrustStoreURL</emphasis>: A URL to the location of the <literal>TrustStore</literal> database. This is used to obtain an <literal>InputStream</literal> to initialize the <literal>KeyStore</literal>. If the string is not a value URL, it is treated as a file.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">TrustStorePass</emphasis>: The password associated with the trust store database contents. The <literal>TrustStorePass</literal> is a simple password and doesn't have the same configuration options as the <literal>KeyStorePass</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ManagerServiceName</emphasis>: Sets the JMX object name string of the security manager service MBean. This is used to register the defaults to register the <literal>JaasSecurityDomain</literal> as a the security manager under <literal>java:/jaas/<domain></literal> where <literal><domain></literal> is the name passed to the MBean constructor. The name defaults to <literal>jboss.security:service=JaasSecurityManager</literal>.
- </para>
- </listitem>
- </itemizedlist>
- </section>
- </section>
- <section id="Security_on_JBoss-Defining_Security_Domains">
- <title>Configuring Security Domains</title>
- <para>The standard way of configuring security domains for authentication and authorization in JBoss is to use the XML login configuration file. The login configuration policy defines a set of named security domains that each define a stack of login modules that will be called upon to authenticate and authorize users.
- </para>
- <para>
- The XML configuration file conforms to the DTD given by <xref linkend="Defining_Security_Domains-The_XMLLoginConfig_DTD"/>. This DTD can be found in <literal>docs/dtd/security_config.dtd</literal>.
- </para>
- <figure id="Defining_Security_Domains-The_XMLLoginConfig_DTD">
- <title>The XMLLoginConfig DTD</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/security_config_policy.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/security_config_login_module.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- The following example shows a simple configuration named jmx-console that is backed by a single login module. The login module is configured by a simple set of name/value configuration pairs that have meaning to the login module in question. We'll see what these options mean later, for now we'll just be concerned with the structure of the configuration file.
- </para>
- <programlisting><application-policy name="jmx-console">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
- <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
- <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- <para>
- The <literal>name</literal> attribute of the <literal>application-policy</literal> is the login configuration name. Applications policy elements will be bound by that name in JNDI under the the <literal>java:/jaas</literal> context. Applications will link to security domains through this JNDI name in their deployment descriptors. (See the <literal>security-domain</literal> elements in <literal>jboss.xml</literal>, <literal>jboss-web.xml</literal> and <literal>jboss-service.xml</literal> files for examples)
- </para>
- <para>
- The <literal>code</literal> attribute of the <literal>login-module</literal> element specifies the class name of the login module implementation. The <literal>required</literal> flag attribute controls the overall behavior of the authentication stack. The allowed values and meanings are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">required</emphasis>: The login module is required to succeed for the authentication to be successful. If any required module fails, the authentication will fail. The remaining login modules in the stack will be called regardless of the outcome of the authentication.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">requisite</emphasis>: The login module is required to succeed. If it succeeds, authentication continues down the login stack. If it fails, control immediately returns to the application.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">sufficient</emphasis>: The login module is not required to succeed. If it does succeed, control immediately returns to the application. If it fails, authentication continues down the login stack.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">optional</emphasis>: The login module is not required to succeed. Authentication still continues to proceed down the login stack regardless of whether the login module succeeds or fails.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The following example shows the definition of a security domain that uses multiple login modules. Since both modules are marked as sufficient, only one of them need to succeed for login to proceed.
- </para>
- <programlisting><application-policy name="todo">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
- flag="sufficient">
- <!-- LDAP configuration -->
- </login-module>
- <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
- flag="sufficient">
- <!-- database configuration -->
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- <para>
- Each login module has its own set of configuration options. These are set as name/value pairs using the <literal>module-option</literal> elements. We'll cover module options in more depth when we look at the individual login modules available in JBoss AS.
- </para>
- <section id="JBoss-Security-Configuring_Microcontainer_Security_Domains">
- <title>Configuring Microcontainer Security Domains</title>
-<!--Added this section from http://server.dzone.com/articles/security-features-jboss-510--> <para>Historically, the Enterprise Application Platform used the static <filename>login-config.xml</filename> file to configure the security domain. Extra functionality was provided with the introduction of the DynamicLoginConfig security service. This functionality allowed you to specify a Java Authentication and Authorisation Service (JAAS) as part of an application deployment, rather than having to include the configuration information in <filename>login-config.xml</filename>.</para>
- <para>The Enterprise Application Platform now provides these security requirements through the use of the JBoss Microcontainer and EJBs. </para>
- <para>In a security-conscious system, JavaEE components such as Web or Enterprise Java Bean (EJB) components require a Security Domain to manage the authentication, authorization, auditing, and mapping functionality. </para>
- <para>The latest security implementation allows you to create a logically-named deployment descriptor file and specify the security domains within the file. The deployment descriptor can be deployed directly in the deploy folder, or packaged as part of the application JAR or WAR file.</para>
- <procedure>
- <title>Security Domain Deployment Descriptor</title>
- <para>Follow this procedure to configure a security domain deployment descriptor with two domains named web-test and ejb-test.</para>
- <step>
- <title>Create deployment descriptor</title>
- <para>You must create a deployment descriptor file to contain the security domain configuration.</para>
- <para>The filename takes the format <filename><replaceable>[domain_name]</replaceable>-jboss-beans.xml</filename>. The <replaceable>domain_name</replaceable> is arbitrary, however you should choose a name that is meaningful to the application. </para>
- <para>The file must contain the standard XML declaration, and a correctly configured <sgmltag><deployment></sgmltag> element.</para>
- <programlisting role="XML" language="XML"><?xml version="1.0" encoding="UTF-8"?>
-
-<deployment xmlns="urn:jboss:bean-deployer:2.0">
-
-
-</deployment></programlisting>
- </step>
- <step>
- <title>Define application policies</title>
- <para>Within the <sgmltag><deployment></sgmltag> element, the individual application policies are defined. Each policy specifies the login module to use, and any required options. </para>
- <para>In the example below, two application policies are specified. Each policy uses the same login module, and module parameters.</para>
- <note>
- <para>Other login modules are available for use with the Enterprise Application Platform. For more information about the available login modules, refer to <xref linkend="Defining_Security_Domains-Using_JBoss_Login_Modules"/></para>
- </note>
- <programlisting language="XML" lang="XML"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/jboss-beans.xml_sample" parse="text"/></programlisting>
- </step>
- <step>
- <title>Deploy or package the deployment descriptor</title>
- <para>Move the deployment descriptor file to the <filename>deploy</filename> directory of the required server profile in your installation. </para>
- <para>Alternatively, package the deployment descriptor in the <filename>META-INF</filename> directory of the EJB Jar, or the Web application (WAR).</para>
- </step>
- </procedure>
-<!--TODO: Thought I should mention this here, but technically the link provided in the Note links forward, instead of backwards. I wanted to mention the Login Modules here just in case readers didn't want to go old-school and use the login-config.xml method.--> </section>
- <section>
- <title>Configuring Authorization Stacks</title>
- <para>If a security domain does not define an authorization module, the default <parameter>jboss-web-policy</parameter> and <parameter>jboss-ejb-policy</parameter> authorization configured in <filename>security-policies-jboss-beans.xml</filename> is used. If you specify an JAAS authorization module, or create a custom deployment descriptor file with valid authorization configuration, these settings override the default settings in <filename>security-policies-jboss-beans.xml</filename>. </para>
- <para>Overriding the default authorization for EJB or Web components is implemented using Java Authorization Contract for Containers (JACC), Extensible Access Control Markup Language (XACML), or custom authorization methods. Configuring this functionality allows access control stacks to be pluggable for a particular component, overriding the default authorization contained in <filename>jboss.xml</filename> (for EJBs) and <filename>jboss-web.xml</filename> (for WAR).</para>
- <formalpara>
- <title>Setting authorization for all EJB and WEB components</title>
- <para>You can override authorization for all EJBs and Web components, or for a particular component.</para>
- </formalpara>
- <procedure id="proc-Set_Auth_Policies_For_All_EJB_WAR_Components">
- <title>Set authorization policies for all EJB and WAR components</title>
- <para>This procedure describes how to define JACC Authorization control for all EJB and WAR components. The example defines application policy modules for three components: <filename>jboss-web-policy</filename>, <filename>jboss-ejb-policy</filename>, and <filename>jacc-test</filename>.</para>
- <step>
- <title>Open the security policy bean</title>
- <para>Navigate to <filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/deploy/security</filename></para>
- <para>Open the <filename>security-policies-jboss-beans.xml</filename> file. </para>
- <para>By default, the security-policies-jboss-beans.xml file contains the configuration in <xref linkend="exam-security_policies_default_configuration"/></para>
- <example id="exam-security_policies_default_configuration">
- <title>security-policies default configuration</title>
- <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-jboss-beans_default.xml_sample" parse="text"/></programlisting>
- </example>
- </step>
- <step>
- <title>Change the application-policy definitions</title>
- <para>To set a single authorization policy for each component using JACC, amend each <sgmltag><policy-module></sgmltag> <parameter>code</parameter> attribute with the name of the JACC auuthorization module.</para>
- <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-jboss-beans_all_ejb_war.xml_sample" parse="text"/></programlisting>
- </step>
- <step>
- <title>Restart server</title>
- <para>You have now configured the <filename>security-policy-jboss-beans.xml</filename> file with JACC authorization enabled for each application policy.</para>
- <para>Restart the server to ensure the new security policy takes effect.</para>
- </step>
- </procedure>
- <formalpara>
- <title>Setting authorization for specific EJB and WEB components</title>
- <para>If applications require more granular security policies, you can declare multiple authorization security policies for each application policy. New security domains can inherit base settings from another application policy, and override specific settings such as the authorization policy module. </para>
- </formalpara>
- <procedure id="proc-Set_Auth_Policies_For_Specific_Domains">
- <title>Set authorization policies for specific security domains </title>
- <para>This procedure describes how to inherit settings from other application policy definitions, and specify different authorization policies per security domain. </para>
- <para>In this procedure, two security domains are defined. The <parameter>test-domain</parameter> security domain uses the UsersRolesLoginModule login module and uses JACC authorization. The <parameter>test-domain-inherited</parameter> security domain inherits the login module information from <parameter>test-domain</parameter>, and specifies XACML authorization must be used.</para>
- <step>
- <title>Open the security policy </title>
- <para>You can specify the security domain settings in the <filename>login-config.xml</filename> file, or create a deployment descriptor file containing the settings. Choose the deployment descriptor if you want to package the security domain settings with your application.</para>
- <stepalternatives performance="required">
- <step performance="optional">
- <title>Locate and open login-config.xml</title>
- <para>Navigate to the <filename>login-config.xml</filename> file for the server profile you are using and open the file for editing. For example: </para>
- <para><filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/conf/login.config.xml</filename></para>
- </step>
- <step performance="optional">
- <title>Create a jboss-beans.xml descriptor</title>
- <para>Create a <filename><replaceable>[prefix]</replaceable>-jboss-beans.xml</filename> descriptor, replacing <replaceable>[prefix]</replaceable> with a meaningful name (for example, <filename>test-war-jboss-beans.xml</filename>)</para>
- <para>Save this file in the deploy directory of the server profile you are configuring. For example:</para>
- <para><filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/deploy/test-war-jboss-beans.xml</filename></para>
- </step>
- </stepalternatives>
- </step>
- <step>
- <title>Specify the test-domain security domain</title>
- <para>In the target file chosen in step 1, specify the <parameter>test-domain</parameter> security domain. This domain contains the authentication information, including the <sgmltag><login-module></sgmltag> definition, and the JACC authorization policy module definition.</para>
- <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/authorization-policy-specific-security-domain-1.xml_sample" parse="text"/></programlisting>
- </step>
- <step>
- <title>Append the test-domain-inherited security domain</title>
- <para>Append the <parameter>test-domain-inherited</parameter> application policy definition after the <parameter>test-domain</parameter> application policy. Set the <parameter>extends</parameter> attribute to <literal>other</literal>, so the login module information is inherited. Specify the XACML authorization module in the <sgmltag><policy.module></sgmltag> element.</para>
- <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/authorization-policy-specific-security-domain-2.xml_sample" parse="text"/></programlisting>
- </step>
- <step>
- <title>Restart server</title>
- <para>You have now configured the target file with two security domains that use different authorization methods.</para>
- <para>Restart the server to ensure the new security policy takes effect.</para>
- </step>
- </procedure>
- <formalpara>
- <title>Setting authorization module delegates</title>
- <para><xref linkend="proc-Set_Auth_Policies_For_All_EJB_WAR_Components"/> and <xref linkend="proc-Set_Auth_Policies_For_Specific_Domains"/> describe simplistic examples that show how authentication and authorization can be configured in security domains. </para>
- </formalpara>
- <para>Because authorization relates to the type of component (not the layer) you want to protect, you can use delegation within a deployment descriptor to specify different authorization policies to the standard authentication in your implementation. </para>
- <para>The delegates must be a subclass of <classname>AuthorizationModuleDelegate</classname>. <xref linkend="exam-security-AuthorizationModuleDelegate_Class"/> describes the base <classname>AuthorizationModuleDelegate</classname> interface. </para>
- <para> </para>
- <example id="exam-security-AuthorizationModuleDelegate_Class">
- <title>AuthorizationModuleDelegate class</title>
- <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-authorization_delegate_example.java" parse="text"/></programlisting>
- </example>
- <para>Some examples of authorization delegation are included for reference. <xref linkend="exam-security-EJBJACCPolicyModuleDelegate_Module"/> describes an authorization module responsible for authorization decisions for the EJB layer. <xref linkend="exam-security-WebJACCPolicyModuleDelegate_Module"/> describes a JACC-based authorization module helper that controls web layer authorization decisions.</para>
- <example id="exam-security-EJBJACCPolicyModuleDelegate_Module">
- <title>EJBJACCPolicyModuleDelegate.java</title>
- <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-EJBJACCPolicyModuleDelegate.java" parse="text"/></programlisting>
- </example>
- <example id="exam-security-WebJACCPolicyModuleDelegate_Module">
- <title>WebJACCPolicyModuleDelegate.java</title>
- <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-WebJACCPolicyModuleDelegate.java" parse="text"/></programlisting>
- </example>
- </section>
- <section id="Defining_Security_Domains-Loading_Security_Domains">
- <title>Loading Security Domains</title>
- <para>
- Authentication security domains are configured statically in the <literal>conf/login-config.xml</literal> file, or deployed using <filename>jboss-beans.xml</filename> deployment descriptors (refer to . For static domains, the <literal>XMLLoginConfig</literal> MBean is responsible for loading security configurations from this configurations from a local configuration file. The MBean is defined as shown below.
- </para>
- <programlisting><mbean code="org.jboss.security.auth.login.XMLLoginConfig"
- name="jboss.security:service=XMLLoginConfig">
- <attribute name="ConfigResource">login-config.xml</attribute>
-</mbean>
-</programlisting>
- <para>
- The MBean supports the following attributes:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">ConfigURL</emphasis>: specifies the URL of the XML login configuration file that should be loaded by this MBean on startup. This must be a valid URL string representation.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ConfigResource</emphasis>: specifies the resource name of the XML login configuration file that should be loaded by this MBean on startup. The name is treated as a classpath resource for which a URL is located using the thread context class loader.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ValidateDTD</emphasis>: a flag indicating if the XML configuration should be validated against its DTD. This defaults to true.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The MBean also supports the following operations that allow one to dynamically extend the login configurations at runtime. Note that any operation that attempts to alter login configuration requires a <literal>javax.security.auth.AuthPermission("refreshLoginConfiguration")</literal> when running with a security manager. The <literal>org.jboss.book.security.service.SecurityConfig</literal> service demonstrates how this can be used to add/remove a deployment specific security configuration dynamically.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>void addAppConfig(String appName, AppConfigurationEntry[] entries)</literal>: this adds the given login module configuration stack to the current configuration under the given <literal>appName</literal>. This replaces any existing entry under that name.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>void removeAppConfig(String appName)</literal>: this removes the login module configuration registered under the given <literal>appName</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>String[] loadConfig(URL configURL) throws Exception</literal>: this loads one or more login configurations from a URL representing either an XML or legacy Sun login configuration file. Note that all login configurations must be added or none will be added. It returns the names of the login configurations that were added.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>void removeConfigs(String[] appNames)</literal>: this removes the login configurations specified <literal>appNames</literal> array.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>String displayAppConfig(String appName)</literal>: this operation displays a simple string format of the named configuration if it exists.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The <literal>SecurityConfig</literal> MBean is responsible for selecting the <literal>javax.security.auth.login.Configuration</literal> to be used. The default configuration simply references the <literal>XMLLoginConfig</literal> MBean.
- </para>
- <programlisting> <mbean code="org.jboss.security.plugins.SecurityConfig"
- name="jboss.security:service=SecurityConfig">
- <attribute name="LoginConfig">jboss.security:service=XMLLoginConfig</attribute>
- </mbean>
-</programlisting>
- <para>
- There is one configurable attribute:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">LoginConfig</emphasis>: Specifies the JMX <literal>ObjectName</literal> string of the MBean that provides the default JAAS login configuration. When the <literal>SecurityConfig</literal> is started, this MBean is queried for its <literal>javax.security.auth.login.Configuration</literal> by calling its <literal>getConfiguration(Configuration currentConfig)</literal> operation. If the <literal>LoginConfig</literal> attribute is not specified then the default Sun <literal>Configuration</literal> implementation described in the <literal>Configuration</literal> class JavaDocs is used.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- In addition to allowing for a custom JAAS login configuration implementation, this service allows configurations to be chained together in a stack at runtime. This allows one to push a login configuration onto the stack and latter pop it. This is a feature used by the security unit tests to install custom login configurations into a default JBoss installation. Pushing a new configuration is done using:
- </para>
- <programlisting>public void pushLoginConfig(String objectName) throws
- JMException, MalformedObjectNameException;
-</programlisting>
- <para>
- The <literal>objectName</literal> parameters specifies an MBean similar to the <literal>LoginConfig</literal> attribute. The current login configuration may be removed using:
- </para>
- <programlisting>public void popLoginConfig() throws JMException;</programlisting>
- </section>
- <section id="Defining_Security_Domains-The_DynamicLoginConfig_service">
- <title>The DynamicLoginConfig service</title>
- <para>
- Security domains defined in the <literal>login-config.xml</literal> file are essentially static. They are read when JBoss starts up, but there is no easy way to add a new security domain or change the definition for an existing one. The <literal>DynamicLoginConfig</literal> service allows you to dynamically deploy security domains. This allows you to specify JAAS login configuration as part of a deployment (or just as a standalone service) rather than having to edit the static <literal>login-config.xml</literal> file.
- </para>
- <para>
- The service supports the following attributes:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">AuthConfig</emphasis>: The resource path to the JAAS login configuration file to use. This defaults to <literal>login-config.xml</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">LoginConfigService</emphasis>: the <literal>XMLLoginConfig</literal> service name to use for loading. This service must support a <literal>String loadConfig(URL)</literal> operation to load the configurations.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">SecurityManagerService</emphasis>: The <literal>SecurityManagerService</literal> name used to flush the registered security domains. This service must support a <literal>flushAuthenticationCache(String)</literal> operation to flush the case for the argument security domain. Setting this triggers the flush of the authentication caches when the service is stopped.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Here is an example MBean definition using the <literal>DynamicLoginConfig</literal> service.
- </para>
- <programlisting><server>
- <mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="...">
- <attribute name="AuthConfig">login-config.xml</attribute>
-
- <!-- The service which supports dynamic processing of login-config.xml
- configurations.
- -->
- <depends optional-attribute-name="LoginConfigService">
- jboss.security:service=XMLLoginConfig </depends>
-
- <!-- Optionally specify the security mgr service to use when
- this service is stopped to flush the auth caches of the domains
- registered by this service.
- -->
- <depends optional-attribute-name="SecurityManagerService">
- jboss.security:service=JaasSecurityManager </depends>
- </mbean>
-</server>
-</programlisting>
- <para>
- This will load the specified <literal>AuthConfig</literal> resource using the specified <literal>LoginConfigService</literal> MBean by invoking <literal>loadConfig</literal> with the appropriate resource URL. When the service is stopped the configurations are removed. The resource specified may be either an XML file, or a Sun JAAS login configuration.
- </para>
- </section>
- <section id="Defining_Security_Domains-Using_JBoss_Login_Modules">
- <title>Using JBoss Login Modules</title>
- <para>
- JBoss includes several bundled login modules suitable for most user management needs. JBoss can read user information from a relational database, an LDAP server or flat files. In addition to these core login modules, JBoss provides several other login modules that provide user information for very customized needs in JBoss. Before we explore the individual login modules, let's take a look at a few login module configuration options that are common to multiple modules.
- </para>
- <section id="Using_JBoss_Login_Modules-Password_Stacking">
- <title>Password Stacking</title>
- <para>
- Multiple login modules can be chained together in a stack, with each login module providing both the authentication and authorization components. This works for many use cases, but sometimes authentication and authorization are split across multiple user management stores. A previous example showed how to combine LDAP and a relational database, allowing a user to be authenticated by either system. However, consider the case where users are managed in a central LDAP server but application-specific roles are stored in the application's relational database. The password-stacking module option captures this relationship.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">password-stacking</emphasis>: When <literal>password-stacking</literal> option is set to <literal>useFirstPass</literal>, this module first looks for a shared username and password under the property names <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively in the login module shared state map. If found these are used as the principal name and password. If not found the principal name and password are set by this login module and stored under the property names <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- To use password stacking, each login module should set <literal>password-stacking</literal> to <literal>useFirstPass</literal>. If a previous module configured for password stacking has authenticated the user, all the other stacking modules will consider the user authenticated and only attempt to provide a set of roles for the authorization step.
- </para>
- <para>
- The following listing shows how password stacking could be used:
- </para>
- <programlisting><application-policy name="todo">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
- flag="required">
- <!-- LDAP configuration -->
- <module-option name="password-stacking">useFirstPass</module-option>
- </login-module>
- <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
- flag="required">
- <!-- database configuration -->
- <module-option name="password-stacking">useFirstPass</module-option>
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- <para>
- When using password stacking, it is usually appropriate to set all modules to be required to make sure that all modules are considered and have chance to contribute roles to the authorization process.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-Password_Hashing">
- <title>Password Hashing</title>
- <para>
- Most of the login modules need to compare a client-supplied password to a password stored in a user management system. These modules generally work with plain text passwords, but can also be configured to support hashed passwords to prevent plain text passwords from being stored on the server side.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">hashAlgorithm</emphasis>: The name of the <literal>java.security.MessageDigest</literal> algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. Typical values are <literal>MD5</literal> and <literal>SHA</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">hashEncoding</emphasis>: The string format for the hashed pass and must be either <literal>base64</literal>, <literal>hex</literal> or <literal>rfc2617</literal>. The default is <literal>base64</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">hashCharset</emphasis>: The encoding used to convert the clear text password to a byte array. The platform default encoding is the default.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">hashUserPassword</emphasis>: This indicates that the hashing algorithm should be applied to the password the user submits. The hashed user password will be compared against the value in the login module, which is expected to be a hash of the password. The default is true.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">hashStorePassword</emphasis>: This indicates that the hashing algorithm should be applied to the password stored on the server side. This is used for digest authentication where the user submits a hash of the user password along with a request-specific tokens from the server to be comare. JBoss uses the hash algorithm (for digest, this would be <literal>rfc2617</literal>) to compute a server-side hash that should match the hashed value sent from the client.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The following is an login module configuration that assigns unauthenticated users the principal name <literal>nobody</literal> and contains based64-encoded, MD5 hashes of the passwords in a <literal>usersb64.properties</literal> file.
- </para>
- <programlisting><policy>
- <application-policy name="testUsersRoles">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
- flag="required">
- <module-option name="hashAlgorithm">MD5</module-option>
- <module-option name="hashEncoding">base64</module-option>
- </login-module>
- </authentication>
- </application-policy>
-</policy>
-</programlisting>
- <para>
- If you need to generate passwords in code, <literal>the org.jboss.security.Util</literal> class provides a static helper method that will hash a password using a given encoding.
- </para>
- <programlisting>String hashedPassword = Util.createPasswordHash("MD5",
- Util.BASE64_ENCODING,
- null,
- null,
- "password");
-</programlisting>
- <para>
- OpenSSL provides an alternative way to quickly generate hashed passwords.
- </para>
- <programlisting>echo -n password | openssl dgst -md5 -binary | openssl base64</programlisting>
- <para>
- In both cases, the text password should hash to "X03MO1qnZdYdgyfeuILPmQ==". This is the value that would need to be stored in the user store.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-Unauthenticated_Identity">
- <title>Unauthenticated Identity</title>
- <para>
- Not all requests come in authenticated. The unauthenticated identity is a login module configuration option that assigns a specific identity (guest, for example) to requests that are made with no associated authentication information. This can be used to allow unprotected servlets to invoke methods on EJBs that do not require a specific role. Such a principal has no associated roles and so can only access either unsecured EJBs or EJB methods that are associated with the unchecked permission constraint.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">unauthenticatedIdentity</emphasis>: This defines the principal name that should be assigned to requests that contain no authentication information.
- </para>
- </listitem>
- </itemizedlist>
- </section>
- <section id="Using_JBoss_Login_Modules-UsersRolesLoginModule">
- <title>UsersRolesLoginModule</title>
- <para>
- The <literal>UsersRolesLoginModule</literal> is a simple login module that supports multiple users and user roles loaded from Java properties files. The username-to-password mapping file is called <literal>users.properties</literal> and the username-to-roles mapping file is called <literal>roles.properties</literal>. The properties files are loaded during initialization using the initialize method thread context class loader. This means that these files can be placed into the J2EE deployment JAR, the JBoss configuration directory, or any directory on the JBoss server or system classpath. The primary purpose of this login module is to easily test the security settings of multiple users and roles using properties files deployed with the application.
- </para>
- <para>
- The <literal>users.properties</literal> file uses a <literal>username=password</literal> format with each user entry on a separate line as show here:
- </para>
- <programlisting>username1=password1
-username2=password2
-...
-</programlisting>
- <para>
- The <literal>roles.properties</literal> file uses as <literal>username=role1,role2,...</literal> format with an optional group name value. For example:
- </para>
- <programlisting>username1=role1,role2,...
-username1.RoleGroup1=role3,role4,...
-username2=role1,role3,...
-</programlisting>
- <para>
- The <literal>username.XXX</literal> form of property name is used to assign the username roles to a particular named group of roles where the <literal>XXX</literal> portion of the property name is the group name. The <literal>username=...</literal> form is an abbreviation for <literal>username.Roles=...</literal>, where the <literal>Roles</literal> group name is the standard name the <literal>JaasSecurityManager</literal> expects to contain the roles which define the users permissions.
- </para>
- <para>
- The following would be equivalent definitions for the <literal>jduke</literal> username:
- </para>
- <programlisting>jduke=TheDuke,AnimatedCharacter
-jduke.Roles=TheDuke,AnimatedCharacter
-</programlisting>
- <para>
- The supported login module configuration options include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">usersProperties</emphasis>: The name of the properties resource containing the username to password mappings. This defaults to <literal>users.properties</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">rolesProperties</emphasis>: The name of the properties resource containing the username to roles mappings. This defaults to <literal>roles.properties</literal>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- This login module supports password stacking, password hashing and unauthenticated identity.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-LdapLoginModule">
- <title>LdapLoginModule</title>
- <para>
- The <literal>LdapLoginModule</literal> is a <literal>LoginModule</literal> implementation that authenticates against an LDAP server. You would use the <literal>LdapLoginModule</literal> if your username and credentials are stored in an LDAP server that is accessible using a JNDI LDAP provider.
- </para>
- <para>
- The LDAP connectivity information is provided as configuration options that are passed through to the environment object used to create JNDI initial context. The standard LDAP JNDI properties used include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.factory.initial</emphasis>: The classname of the <literal>InitialContextFactory</literal> implementation. This defaults to the Sun LDAP provider implementation <literal>com.sun.jndi.ldap.LdapCtxFactory</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.provider.url</emphasis>: The LDAP URL for the LDAP server
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.security.authentication</emphasis>: The security level to use. This defaults to <literal>simple</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.security.protocol</emphasis>: The transport protocol to use for secure access, such as, SSL.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.security.principal</emphasis>: The principal for authenticating the caller to the service. This is built from other properties as described below.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.naming.security.credentials</emphasis>: The value of the property depends on the authentication scheme. For example, it could be a hashed password, clear-text password, key, certificate, and so on.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The supported login module configuration options include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">principalDNPrefix</emphasis>: A prefix to add to the username to form the user distinguished name. See <literal>principalDNSuffix</literal> for more info.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">principalDNSuffix</emphasis>: A suffix to add to the username when forming the user distinguished name. This is useful if you prompt a user for a username and you don't want the user to have to enter the fully distinguished name. Using this property and <literal>principalDNSuffix</literal> the <literal>userDN</literal> will be formed as <literal>principalDNPrefix + username + principalDNSuffix</literal>
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">useObjectCredential</emphasis>: A true/false value that indicates that the credential should be obtained as an opaque <literal>Object</literal> using the <literal>org.jboss.security.auth.callback.ObjectCallback</literal> type of <literal>Callback</literal> rather than as a <literal>char[]</literal> password using a JAAS <literal>PasswordCallback</literal>. This allows for passing non-<literal>char[]</literal> credential information to the LDAP server.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">rolesCtxDN</emphasis>: The fixed distinguished name to the context to search for user roles.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">userRolesCtxDNAttributeName</emphasis>: The name of an attribute in the user object that contains the distinguished name to the context to search for user roles. This differs from <literal>rolesCtxDN</literal> in that the context to search for a user's roles can be unique for each user.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">roleAttributeID</emphasis>: The name of the attribute that contains the user roles. If not specified this defaults to <literal>roles</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">roleAttributeIsDN</emphasis>: A flag indicating whether the <literal>roleAttributeID</literal> contains the fully distinguished name of a role object, or the role name. If false, the role name is taken from the value of <literal>roleAttributeID</literal>. If true, the role attribute represents the distinguished name of a role object. The role name is taken from the value of the <literal>roleNameAttributeId</literal> attribute of the context name by the distinguished name. In certain directory schemas (e.g., MS ActiveDirectory), role attributes in the user object are stored as DNs to role objects instead of as simple names, in which case, this property should be set to true. The default is false.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">roleNameAttributeID</emphasis>: The name of the attribute of the context pointed to by the <literal>roleCtxDN</literal> distinguished name value which contains the role name. If the <literal>roleAttributeIsDN</literal> property is set to true, this property is used to find the role object's name attribute. The default is <literal>group</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">uidAttributeID</emphasis>: The name of the attribute in the object containing the user roles that corresponds to the userid. This is used to locate the user roles. If not specified this defaults to <literal>uid</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">matchOnUserDN</emphasis>: A true/false flag indicating if the search for user roles should match on the user's fully distinguished name. If false, just the username is used as the match value against the <literal>uidAttributeName</literal> attribute. If true, the full <literal>userDN</literal> is used as the match value.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">unauthenticatedIdentity</emphasis>: The principal name that should be assigned to requests that contain no authentication information. This behavior is inherited from the <literal>UsernamePasswordLoginModule</literal> superclass.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">allowEmptyPasswords</emphasis>: A flag indicating if empty (length 0) passwords should be passed to the LDAP server. An empty password is treated as an anonymous login by some LDAP servers and this may not be a desirable feature. Set this to false to reject empty passwords or true to have the LDAP server validate the empty password. The default is true.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The authentication of a user is performed by connecting to the LDAP server based on the login module configuration options. Connecting to the LDAP server is done by creating an <literal>InitialLdapContext</literal> with an environment composed of the LDAP JNDI properties described previously in this section. The <literal>Context.SECURITY_PRINCIPAL</literal> is set to the distinguished name of the user as obtained by the callback handler in combination with the <literal>principalDNPrefix</literal> and <literal>principalDNSuffix</literal> option values, and the <literal>Context.SECURITY_CREDENTIALS</literal> property is either set to the <literal>String</literal> password or the <literal>Object</literal> credential depending on the <literal>useObjectCredential</literal> option.
- </para>
- <para>
- Once authentication has succeeded by virtue of being able to create an <literal>InitialLdapContext</literal> instance, the user's roles are queried by performing a search on the <literal>rolesCtxDN</literal> location with search attributes set to the <literal>roleAttributeName</literal> and <literal>uidAttributeName</literal> option values. The roles names are obtaining by invoking the <literal>toString</literal> method on the role attributes in the search result set.
- </para>
- <para>
- The following is a sample <literal>login-config.xml</literal> entry.
- </para>
- <programlisting>
- <application-policy name="testLDAP">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
- flag="required">
- <module-option name="java.naming.factory.initial">
- com.sun.jndi.ldap.LdapCtxFactory
- </module-option>
- <module-option name="java.naming.provider.url">
- ldap://ldaphost.jboss.org:1389/
- </module-option>
- <module-option name="java.naming.security.authentication">
- simple
- </module-option>
- <module-option name="principalDNPrefix">uid=</module-option>
- <module-option name="principalDNSuffix">
- ,ou=People,dc=jboss,dc=org
- </module-option>
-
- <module-option name="rolesCtxDN">
- ou=Roles,dc=jboss,dc=org
- </module-option>
- <module-option name="uidAttributeID">member</module-option>
- <module-option name="matchOnUserDN">true</module-option>
-
- <module-option name="roleAttributeID">cn</module-option>
- <module-option name="roleAttributeIsDN">false </module-option>
- </login-module>
- </authentication>
- </application-policy>
-</programlisting>
- <para>
- An LDIF file representing the structure of the directory this data operates against is shown below.
- </para>
- <programlisting>dn: dc=jboss,dc=org
-objectclass: top
-objectclass: dcObject
-objectclass: organization
-dc: jboss
-o: JBoss
-
-dn: ou=People,dc=jboss,dc=org
-objectclass: top
-objectclass: organizationalUnit
-ou: People
-
-dn: uid=jduke,ou=People,dc=jboss,dc=org
-objectclass: top
-objectclass: uidObject
-objectclass: person
-uid: jduke
-cn: Java Duke
-sn: Duke
-userPassword: theduke
-
-dn: ou=Roles,dc=jboss,dc=org
-objectclass: top
-objectclass: organizationalUnit
-ou: Roles
-
-dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org
-objectclass: top
-objectclass: groupOfNames
-cn: JBossAdmin
-member: uid=jduke,ou=People,dc=jboss,dc=org
-description: the JBossAdmin group
-</programlisting>
- <para>
- Looking back at the <literal>testLDAP</literal> login module configuration, the <literal>java.naming.factory.initial</literal>, <literal>java.naming.factory.url</literal> and <literal>java.naming.security</literal> options indicate the Sun LDAP JNDI provider implementation will be used, the LDAP server is located on host <literal>ldaphost.jboss.org</literal> on port 1389, and that the LDAP simple authentication method will be use to connect to the LDAP server.
- </para>
- <para>
- The login module attempts to connect to the LDAP server using a DN representing the user it is trying to authenticate. This DN is constructed from the <literal>principalDNPrefix</literal>, passed in, the username of the user and the <literal>principalDNSuffix</literal> as described above. In this example, the username <literal>jduke</literal> would map to <literal>uid=jduke,ou=People,dc=jboss,dc=org</literal>. We've assumed the LDAP server authenticates users using the <literal>userPassword</literal> attribute of the user's entry (<literal>theduke</literal> in this example). This is the way most LDAP servers work, however, if your LDAP server handles authentication differently you will need to set the authentication credentials in a way that makes sense for your server.
- </para>
- <para>
- Once authentication succeeds, the roles on which authorization will be based are retrieved by performing a subtree search of the <literal>rolesCtxDN</literal> for entries whose <literal>uidAttributeID</literal> match the user. If <literal>matchOnUserDN</literal> is true the search will be based on the full DN of the user. Otherwise the search will be based on the actual user name entered. In this example, the search is under <literal>ou=Roles,dc=jboss,dc=org</literal> for any entries that have a <literal>member</literal> attribute equal to <literal>uid=jduke,ou=People,dc=jboss,dc=org</literal>. The search would locate <literal>cn=JBossAdmin</literal> under the roles entry.
- </para>
- <para>
- The search returns the attribute specified in the <literal>roleAttributeID</literal> option. In this example, the attribute is <literal>cn</literal>. The value returned would be <literal>JBossAdmin</literal>, so the jduke user is assigned to the <literal>JBossAdmin</literal> role.
- </para>
- <para>
- It's often the case that a local LDAP server provides identity and authentication services but is unable to use the authorization services. This is because application roles don't always map well onto LDAP groups, and LDAP administrators are often hesitant to allow external application-specific data in central LDAP servers. For this reason, the LDAP authentication module is often paired with another login module, such as the database login module, that can provide roles more suitable to the application being developed.
- </para>
- <para>
- This login module also supports unauthenticated identity and password stacking.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-DatabaseServerLoginModule">
- <title>DatabaseServerLoginModule</title>
- <para>
- The <literal>DatabaseServerLoginModule</literal> is a JDBC based login module that supports authentication and role mapping. You would use this login module if you have your username, password and role information relational database. The <literal>DatabaseServerLoginModule</literal> is based on two logical tables:
- </para>
- <programlisting>Table Principals(PrincipalID text, Password text)
-Table Roles(PrincipalID text, Role text, RoleGroup text)
-</programlisting>
- <para>
- The <literal>Principals</literal> table associates the user <literal>PrincipalID</literal> with the valid password and the <literal>Roles</literal> table associates the user <literal>PrincipalID</literal> with its role sets. The roles used for user permissions must be contained in rows with a <literal>RoleGroup</literal> column value of <literal>Roles</literal>. The tables are logical in that you can specify the SQL query that the login module uses. All that is required is that the <literal>java.sql.ResultSet</literal> has the same logical structure as the <literal>Principals</literal> and <literal>Roles</literal> tables described previously. The actual names of the tables and columns are not relevant as the results are accessed based on the column index. To clarify this notion, consider a database with two tables, <literal>Principals</literal> and <literal>Roles</literal>, as already declared. The following statements build the tables to contain a <literal>PrincipalID!
</literal><literal>java</literal> with a <literal>Password</literal> of <literal>echoman</literal> in the <literal>Principals</literal> table, a <literal>PrincipalID</literal><literal>java</literal> with a role named <literal>Echo</literal> in the <literal>Roles</literal><literal>RoleGroup</literal> in the <literal>Roles</literal> table, and a <literal>PrincipalID</literal><literal>java</literal> with a role named <literal>caller_java</literal> in the <literal>CallerPrincipal</literal><literal>RoleGroup</literal> in the <literal>Roles</literal> table:
- </para>
- <programlisting>INSERT INTO Principals VALUES('java', 'echoman')
-INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
-INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
-</programlisting>
- <para>
- The supported login module configuration options include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">dsJndiName</emphasis>: The JNDI name for the <literal>DataSource</literal> of the database containing the logical <literal>Principals</literal> and <literal>Roles</literal> tables. If not specified this defaults to <literal>java:/DefaultDS</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">principalsQuery</emphasis>: The prepared statement query equivalent to: <literal>select Password from Principals where PrincipalID=?</literal>. If not specified this is the exact prepared statement that will be used.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">rolesQuery</emphasis>: The prepared statement query equivalent to: <literal>select Role, RoleGroup from Roles where PrincipalID=?</literal>. If not specified this is the exact prepared statement that will be used.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ignorePasswordCase</emphasis>: A boolean flag indicating if the password comparison should ignore case. This can be useful for hashed password encoding where the case of the hashed password is not significant.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">principalClass</emphasis>: An option that specifies a <literal>Principal</literal> implementation class. This must support a constructor taking a string argument for the principal name.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- As an example <literal>DatabaseServerLoginModule</literal> configuration, consider a custom table schema like the following:
- </para>
- <programlisting>CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
-CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32))
-</programlisting>
- <para>
- A corresponding <literal>login-config.xml</literal> entry would be:
- </para>
- <programlisting><policy>
- <application-policy name="testDB">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
- flag="required">
- <module-option name="dsJndiName">java:/MyDatabaseDS</module-option>
- <module-option name="principalsQuery">
- select passwd from Users username where username=?</module-option>
- <module-option name="rolesQuery">
- select userRoles, 'Roles' from UserRoles where username=?</module-option>
- </login-module>
- </authentication>
- </application-policy>
-</policy>
-</programlisting>
- <para>
- This module supports password stacking, password hashing and unathenticated identity.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-BaseCertLoginModule">
- <title>BaseCertLoginModule</title>
- <para>
- This is a login module which authenticates users based on X509 certificates. A typical use case for this login module is <literal>CLIENT-CERT</literal> authentication in the web tier. This login module only performs authentication. You need to combine it with another login module capable of acquiring the authorization roles to completely define access to a secured web or EJB component. Two subclasses of this login module, <literal>CertRolesLoginModule</literal> and <literal>DatabaseCertLoginModule</literal> extend the behavior to obtain the authorization roles from either a properties file or database.
- </para>
- <para>
- The <literal>BaseCertLoginModule</literal> needs a <literal>KeyStore</literal> to perform user validation. This is obtained through a <literal>org.jboss.security.SecurityDomain</literal> implementation. Typically, the <literal>SecurityDomain</literal> implementation is configured using the <literal>org.jboss.security.plugins.JaasSecurityDomain</literal> MBean as shown in this <literal>jboss-service.xml</literal> configuration fragment:
- </para>
- <programlisting><mbean code="org.jboss.security.plugins.JaasSecurityDomain"
- name="jboss.ch8:service=SecurityDomain">
- <constructor>
- <arg type="java.lang.String" value="jmx-console"/>
- </constructor>
- <attribute name="KeyStoreURL">resource:localhost.keystore</attribute>
- <attribute name="KeyStorePass">unit-tests-server</attribute>
-</mbean>
-</programlisting>
- <para>
- This creates a security domain with the name <literal>jmx-console</literal> whose <literal>SecurityDomain</literal> implementation is available via JNDI under the name <literal>java:/jaas/jmx-console</literal> following the JBossSX security domain naming pattern. To secure a web application such as the <literal>jmx-console.war</literal> using client certs and role based authorization, one would first modify the <literal>web.xml</literal> to declare the resources to be secured, along with the allowed roles and security domain to be used for authentication and authorization.
- </para>
- <programlisting><?xml version="1.0"?>
-<!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd">
-<web-app>
- ...
- <security-constraint>
- <web-resource-collection>
- <web-resource-name>HtmlAdaptor</web-resource-name>
- <description>An example security config that only allows users with
- the role JBossAdmin to access the HTML JMX console web
- application </description>
- <url-pattern>/*</url-pattern>
- <http-method>GET</http-method>
- <http-method>POST</http-method>
- </web-resource-collection>
- <auth-constraint>
- <role-name>JBossAdmin</role-name>
- </auth-constraint>
- </security-constraint>
- <login-config>
- <auth-method>CLIENT-CERT</auth-method>
- <realm-name>JBoss JMX Console</realm-name>
- </login-config>
- <security-role>
- <role-name>JBossAdmin</role-name>
- </security-role>
-</web-app>
-</programlisting>
- <para>
- Next we, need to specify the JBoss security domain in <literal>jboss-web.xml</literal>:
- </para>
- <programlisting><jboss-web>
- <security-domain>java:/jaas/jmx-console</security-domain>
-</jboss-web>
-</programlisting>
- <para>
- Finally, you need to define the login module configuration for the jmx-console security domain you just specified. This is done in the <literal>conf/login-config.xml</literal> file.
- </para>
- <programlisting><application-policy name="jmx-console">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
- flag="required">
- <module-option name="password-stacking">useFirstPass</module-option>
- <module-option name="securityDomain">java:/jaas/jmx-console</module-option>
- </login-module>
- <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
- flag="required">
- <module-option name="password-stacking">useFirstPass</module-option>
- <module-option name="usersProperties">jmx-console-users.properties</module-option>
- <module-option name="rolesProperties">jmx-console-roles.properties</module-option>
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- <para>
- Here the <literal>BaseCertLoginModule</literal> is used for authentication of the client cert, and the <literal>UsersRolesLoginModule</literal> is only used for authorization due to the <literal>password-stacking=useFirstPass</literal> option. Both the <literal>localhost.keystore</literal> and the <literal>jmx-console-roles.properties</literal> need an entry that maps to the principal associated with the client cert. By default, the principal is created using the client certificate distinguished name. Consider the following certificate:
- </para>
- <programlisting>[starksm at banshee9100 conf]$ keytool -printcert -file unit-tests-client.export
-Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US
-Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin
- at jboss.com, OU=QA, O=JBoss Inc.
-Serial number: 100103
-Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005
-Certificate fingerprints:
- MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB
- SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58
-</programlisting>
- <para>
- The <literal>localhost.keystore</literal> would need this cert stored with an alias of <literal>CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US</literal> and the <literal>jmx-console-roles.properties</literal> would also need an entry for the same entry. Since the DN contains many characters that are normally treated as delimiters, you will need to escape the problem characters using a backslash ('<literal>\</literal>') as shown here:
- </para>
- <programlisting># A sample roles.properties file for use with the UsersRolesLoginModule
-CN\=unit-tests-client,\ OU\=JBoss\ Inc.,\ O\=JBoss\ Inc.,\ ST\=Washington,\ C\=US=JBossAdmin
-admin=JBossAdmin
-</programlisting>
- </section>
- <section id="Using_JBoss_Login_Modules-IdentityLoginModule">
- <title>IdentityLoginModule</title>
- <para>
- The <literal>IdentityLoginModule</literal> is a simple login module that associates a hard-coded user name a to any subject authenticated against the module. It creates a <literal>SimplePrincipal</literal> instance using the name specified by the <literal>principal</literal> option. This login module is useful when you need to provide a fixed identity to a service and in development environments when you want to test the security associated with a given principal and associated roles.
- </para>
- <para>
- The supported login module configuration options include:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">principal</emphasis>: This is the name to use for the <literal>SimplePrincipal</literal> all users are authenticated as. The principal name defaults to <literal>guest</literal> if no principal option is specified.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">roles</emphasis>: This is a comma-delimited list of roles that will be assigned to the user.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- A sample XMLLoginConfig configuration entry that would authenticate all users as the principal named <literal>jduke</literal> and assign role names of <literal>TheDuke</literal>, and <literal>AnimatedCharacter</literal> is:
- </para>
- <programlisting><policy>
- <application-policy name="testIdentity">
- <authentication>
- <login-module code="org.jboss.security.auth.spi.IdentityLoginModule"
- flag="required">
- <module-option name="principal">jduke</module-option>
- <module-option name="roles">TheDuke,AnimatedCharater</module-option>
- </login-module>
- </authentication>
- </application-policy>
-</policy>
-</programlisting>
- <para>
- This module supports password stacking.
- </para>
- </section>
- <section id="Using_JBoss_Login_Modules-RunAsLoginModule">
- <title>RunAsLoginModule</title>
- <para>
- JBoss has a helper login module called <literal>RunAsLoginModule</literal> that pushes a run as role for the duration of the login phase of authentication, and pops the run as role in either the commit or abort phase. The purpose of this login module is to provide a role for other login modules that need to access secured resources in order to perform their authentication. An example would be a login module that accesses an secured EJB. This login module must be configured ahead of the login module(s) that need a run as role established.
- </para>
- <para>
- The only login module configuration option is:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">roleName</emphasis>: the name of the role to use as the run as role during login phase. If not specified a default of <literal>nobody</literal> is used.
- </para>
- </listitem>
- </itemizedlist>
- </section>
- <section id="Using_JBoss_Login_Modules-ClientLoginModule">
- <title>ClientLoginModule</title>
- <para>
- The <literal>ClientLoginModule</literal> is an implementation of <literal>LoginModule</literal> for use by JBoss clients for the establishment of the caller identity and credentials. This simply sets the <literal>org.jboss.security.SecurityAssociation.principal</literal> to the value of the <literal>NameCallback</literal> filled in by the <literal>callbackhandler</literal>, and the <literal>org.jboss.security.SecurityAssociation.credential</literal> to the value of the <literal>PasswordCallback</literal> filled in by the <literal>callbackhandler</literal>. This is the only supported mechanism for a client to establish the current thread's caller. Both stand-alone client applications and server environments, acting as JBoss EJB clients where the security environment has not been configured to use JBossSX transparently, need to use the <literal>ClientLoginModule</literal>. Of course, you could always set the <literal>org.jboss.security.SecurityAssociation</literal> !
information directly, but this is considered an internal API that is subject to change without notice.
- </para>
- <para>
- Note that this login module does not perform any authentication. It merely copies the login information provided to it into the JBoss server EJB invocation layer for subsequent authentication on the server. If you need to perform client-side authentication of users you would need to configure another login module in addition to the <literal>ClientLoginModule</literal>.
- </para>
- <para>
- The supported login module configuration options include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">multi-threaded</emphasis>: When the multi-threaded option is set to true, each login thread has its own principal and credential storage. This is useful in client environments where multiple user identities are active in separate threads. When true, each separate thread must perform its own login. When set to false the login identity and credentials are global variables that apply to all threads in the VM. The default for this option is false.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">password-stacking</emphasis>: When <literal>password-stacking</literal> option is set to <literal>useFirstPass</literal>, this module first looks for a shared username and password using <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively in the login module shared state map. This allows a module configured prior to this one to establish a valid username and password that should be passed to JBoss. You would use this option if you want to perform client-side authentication of clients using some other login module such as the <literal>LdapLoginModule</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">restore-login-identity</emphasis>: When <literal>restore-login-identity</literal> is true, the <literal>SecurityAssociation</literal> principal and credential seen on entry to the <literal>login()</literal> method are saved and restored on either abort or logout. When false (the default), the abort and logout simply clear the <literal>SecurityAssociation</literal>. A <literal>restore-login-identity</literal> of true is needed if one need to change identities and then restore the original caller identity.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- A sample login configuration for <literal>ClientLoginModule</literal> is the default configuration entry found in the JBoss distribution <literal>client/auth.conf</literal> file. The configuration is:
- </para>
- <programlisting>other {
- // Put your login modules that work without jBoss here
-
- // jBoss LoginModule
- org.jboss.security.ClientLoginModule required;
-
- // Put your login modules that need jBoss here
-};
-</programlisting>
- </section>
- </section>
- <section id="Defining_Security_Domains-Writing_Custom_Login_Modules">
- <title>Writing Custom Login Modules</title>
- <para>
- If the login modules bundled with the JBossSX framework do not work with your security environment, you can write your own custom login module implementation that does. Recall from the section on the <literal>JaasSecurityManager</literal> architecture that the <literal>JaasSecurityManager</literal> expected a particular usage pattern of the <literal>Subject</literal> principals set. You need to understand the JAAS Subject class's information storage features and the expected usage of these features to be able to write a login module that works with the <literal>JaasSecurityManager</literal>. This section examines this requirement and introduces two abstract base <literal>LoginModule</literal> implementations that can help you implement your own custom login modules.
- </para>
- <para>
- You can obtain security information associated with a <literal>Subject</literal> in six ways in JBoss using the following methods:
- </para>
- <programlisting>java.util.Set getPrincipals()
-java.util.Set getPrincipals(java.lang.Class c)
-java.util.Set getPrivateCredentials()
-java.util.Set getPrivateCredentials(java.lang.Class c)
-java.util.Set getPublicCredentials()
-java.util.Set getPublicCredentials(java.lang.Class c)
-</programlisting>
- <para>
- For <literal>Subject</literal> identities and roles, JBossSX has selected the most natural choice: the principals sets obtained via <literal>getPrincipals()</literal> and <literal>getPrincipals(java.lang.Class)</literal>. The usage pattern is as follows:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- User identities (username, social security number, employee ID, and so on) are stored as <literal>java.security.Principal</literal> objects in the <literal>Subject</literal><literal>Principals</literal> set. The <literal>Principal</literal> implementation that represents the user identity must base comparisons and equality on the name of the principal. A suitable implementation is available as the <literal>org.jboss.security.SimplePrincipal</literal> class. Other <literal>Principal</literal> instances may be added to the <literal>Subject</literal><literal>Principals</literal> set as needed.
- </para>
- </listitem>
- <listitem>
- <para>
- The assigned user roles are also stored in the <literal>Principals</literal> set, but they are grouped in named role sets using <literal>java.security.acl.Group</literal> instances. The <literal>Group</literal> interface defines a collection of <literal>Principal</literal>s and/or <literal>Group</literal>s, and is a subinterface of <literal>java.security.Principal</literal>. Any number of role sets can be assigned to a <literal>Subject</literal>. Currently, the JBossSX framework uses two well-known role sets with the names <literal>Roles</literal> and <literal>CallerPrincipal</literal>. The <literal>Roles</literal> Group is the collection of <literal>Principal</literal>s for the named roles as known in the application domain under which the <literal>Subject</literal> has been authenticated. This role set is used by methods like the <literal>EJBContext.isCallerInRole(String)</literal>, which EJBs can use to see if the current caller belongs to the named application dom!
ain role. The security interceptor logic that performs method permission checks also uses this role set. The <literal>CallerPrincipal</literal><literal>Group</literal> consists of the single <literal>Principal</literal> identity assigned to the user in the application domain. The <literal>EJBContext.getCallerPrincipal() </literal>method uses the <literal>CallerPrincipal</literal> to allow the application domain to map from the operation environment identity to a user identity suitable for the application. If a <literal>Subject</literal> does not have a <literal>CallerPrincipal</literal><literal>Group</literal>, the application identity is the same as operational environment identity.
- </para>
- </listitem>
- </itemizedlist>
- <section id="Writing_Custom_Login_Modules-Support_for_the_Subject_Usage_Pattern">
- <title>Support for the Subject Usage Pattern</title>
- <para>
- To simplify correct implementation of the <literal>Subject</literal> usage patterns described in the preceding section, JBossSX includes two abstract login modules that handle the population of the authenticated <literal>Subject</literal> with a template pattern that enforces correct <literal>Subject</literal> usage. The most generic of the two is the <literal>org.jboss.security.auth.spi.AbstractServerLoginModule</literal> class. It provides a concrete implementation of the <literal>javax.security.auth.spi.LoginModule</literal> interface and offers abstract methods for the key tasks specific to an operation environment security infrastructure. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses.
- </para>
- <programlisting>package org.jboss.security.auth.spi;
-/**
- * This class implements the common functionality required for a JAAS
- * server-side LoginModule and implements the JBossSX standard
- * Subject usage pattern of storing identities and roles. Subclass
- * this module to create your own custom LoginModule and override the
- * login(), getRoleSets(), and getIdentity() methods.
- */
-public abstract class AbstractServerLoginModule
- implements javax.security.auth.spi.LoginModule
-{
- protected Subject subject;
- protected CallbackHandler callbackHandler;
- protected Map sharedState;
- protected Map options;
- protected Logger log;
-
- /** Flag indicating if the shared credential should be used */
- protected boolean useFirstPass;
- /**
- * Flag indicating if the login phase succeeded. Subclasses that
- * override the login method must set this to true on successful
- * completion of login
- */
- protected boolean loginOk;
-
- // ...
- /**
- * Initialize the login module. This stores the subject,
- * callbackHandler and sharedState and options for the login
- * session. Subclasses should override if they need to process
- * their own options. A call to super.initialize(...) must be
- * made in the case of an override.
- *
- * <p>
- * The options are checked for the <em>password-stacking</em> parameter.
- * If this is set to "useFirstPass", the login identity will be taken from the
- * <code>javax.security.auth.login.name</code> value of the sharedState map,
- * and the proof of identity from the
- * <code>javax.security.auth.login.password</code> value of the sharedState map.
- *
- * @param subject the Subject to update after a successful login.
- * @param callbackHandler the CallbackHandler that will be used to obtain the
- * the user identity and credentials.
- * @param sharedState a Map shared between all configured login module instances
- * @param options the parameters passed to the login module.
- */
- public void initialize(Subject subject,
- CallbackHandler callbackHandler,
- Map sharedState,
- Map options)
- {
- // ...
- }
-
-
- /**
- * Looks for javax.security.auth.login.name and
- * javax.security.auth.login.password values in the sharedState
- * map if the useFirstPass option was true and returns true if
- * they exist. If they do not or are null this method returns
- * false.
- * Note that subclasses that override the login method
- * must set the loginOk var to true if the login succeeds in
- * order for the commit phase to populate the Subject. This
- * implementation sets loginOk to true if the login() method
- * returns true, otherwise, it sets loginOk to false.
- */
- public boolean login()
- throws LoginException
- {
- // ...
- }
-
- /**
- * Overridden by subclasses to return the Principal that
- * corresponds to the user primary identity.
- */
- abstract protected Principal getIdentity();
-
- /**
- * Overridden by subclasses to return the Groups that correspond
- * to the role sets assigned to the user. Subclasses should
- * create at least a Group named "Roles" that contains the roles
- * assigned to the user. A second common group is
- * "CallerPrincipal," which provides the application identity of
- * the user rather than the security domain identity.
- *
- * @return Group[] containing the sets of roles
- */
- abstract protected Group[] getRoleSets() throws LoginException;
-}
-</programlisting>
- <para>
- You'll need to pay attention to the <literal>loginOk</literal> instance variable. This must be set to true if the login succeeds, false otherwise by any subclasses that override the login method. Failure to set this variable correctly will result in the commit method either not updating the subject when it should, or updating the subject when it should not. Tracking the outcome of the login phase was added to allow login modules to be chained together with control flags that do not require that the login module succeed in order for the overall login to succeed.
- </para>
- <para>
- The second abstract base login module suitable for custom login modules is the <literal>org.jboss.security.auth.spi.UsernamePasswordLoginModule</literal>. This login module further simplifies custom login module implementation by enforcing a string-based username as the user identity and a <literal>char[]</literal> password as the authentication credentials. It also supports the mapping of anonymous users (indicated by a null username and password) to a principal with no roles. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses.
- </para>
- <programlisting>package org.jboss.security.auth.spi;
-
-/**
- * An abstract subclass of AbstractServerLoginModule that imposes a
- * an identity == String username, credentials == String password
- * view on the login process. Subclasses override the
- * getUsersPassword() and getUsersRoles() methods to return the
- * expected password and roles for the user.
- */
-public abstract class UsernamePasswordLoginModule
- extends AbstractServerLoginModule
-{
- /** The login identity */
- private Principal identity;
- /** The proof of login identity */
- private char[] credential;
- /** The principal to use when a null username and password are seen */
- private Principal unauthenticatedIdentity;
-
- /**
- * The message digest algorithm used to hash passwords. If null then
- * plain passwords will be used. */
- private String hashAlgorithm = null;
-
- /**
- * The name of the charset/encoding to use when converting the
- * password String to a byte array. Default is the platform's
- * default encoding.
- */
- private String hashCharset = null;
-
- /** The string encoding format to use. Defaults to base64. */
- private String hashEncoding = null;
-
- // ...
-
- /**
- * Override the superclass method to look for an
- * unauthenticatedIdentity property. This method first invokes
- * the super version.
- *
- * @param options,
- * @option unauthenticatedIdentity: the name of the principal to
- * assign and authenticate when a null username and password are
- * seen.
- */
- public void initialize(Subject subject,
- CallbackHandler callbackHandler,
- Map sharedState,
- Map options)
- {
- super.initialize(subject, callbackHandler, sharedState,
- options);
- // Check for unauthenticatedIdentity option.
- Object option = options.get("unauthenticatedIdentity");
- String name = (String) option;
- if (name != null) {
- unauthenticatedIdentity = new SimplePrincipal(name);
- }
- }
-
- // ...
-
- /**
- * A hook that allows subclasses to change the validation of the
- * input password against the expected password. This version
- * checks that neither inputPassword or expectedPassword are null
- * and that inputPassword.equals(expectedPassword) is true;
- *
- * @return true if the inputPassword is valid, false otherwise.
- */
- protected boolean validatePassword(String inputPassword,
- String expectedPassword)
- {
- if (inputPassword == null || expectedPassword == null) {
- return false;
- }
- return inputPassword.equals(expectedPassword);
- }
-
- /**
- * Get the expected password for the current username available
- * via the getUsername() method. This is called from within the
- * login() method after the CallbackHandler has returned the
- * username and candidate password.
- *
- * @return the valid password String
- */
- abstract protected String getUsersPassword()
- throws LoginException;
-}
-</programlisting>
- <para>
- The choice of subclassing the <literal>AbstractServerLoginModule</literal> versus <literal>UsernamePasswordLoginModule</literal> is simply based on whether a string-based username and credentials are usable for the authentication technology you are writing the login module for. If the string-based semantic is valid, then subclass <literal>UsernamePasswordLoginModule</literal>, otherwise subclass <literal>AbstractServerLoginModule</literal>.
- </para>
- <para>
- The steps you are required to perform when writing a custom login module are summarized in the following depending on which base login module class you choose. When writing a custom login module that integrates with your security infrastructure, you should start by subclassing <literal>AbstractServerLoginModule</literal> or <literal>UsernamePasswordLoginModule</literal> to ensure that your login module provides the authenticated <literal>Principal</literal> information in the form expected by the JBossSX security manager.
- </para>
- <para>
- When subclassing the <literal>AbstractServerLoginModule</literal>, you need to override the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>void initialize(Subject, CallbackHandler, Map, Map)</literal>: if you have custom options to parse.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>boolean login()</literal>: to perform the authentication activity. Be sure to set the <literal>loginOk</literal> instance variable to true if login succeeds, false if it fails.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>Principal getIdentity()</literal>: to return the <literal>Principal</literal> object for the user authenticated by the <literal>log()</literal> step.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>Group[] getRoleSets()</literal>: to return at least one <literal>Group</literal> named <literal>Roles</literal> that contains the roles assigned to the <literal>Principal</literal> authenticated during <literal>login()</literal>. A second common <literal>Group</literal> is named <literal>CallerPrincipal</literal> and provides the user's application identity rather than the security domain identity.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- When subclassing the <literal>UsernamePasswordLoginModule</literal>, you need to override the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>void initialize(Subject, CallbackHandler, Map, Map)</literal>: if you have custom options to parse.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>Group[] getRoleSets()</literal>: to return at least one <literal>Group</literal> named <literal>Roles</literal> that contains the roles assigned to the <literal>Principal</literal> authenticated during <literal>login()</literal>. A second common <literal>Group</literal> is named <literal>CallerPrincipal</literal> and provides the user's application identity rather than the security domain identity.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>String getUsersPassword()</literal>: to return the expected password for the current username available via the <literal>getUsername()</literal> method. The <literal>getUsersPassword()</literal> method is called from within <literal>login()</literal> after the <literal>callbackhandler</literal> returns the username and candidate password.
- </para>
- </listitem>
- </itemizedlist>
- </section>
- <section id="Writing_Custom_Login_Modules-A_Custom_LoginModule_Example">
- <title>A Custom LoginModule Example</title>
- <para>
- In this section we will develop a custom login module example. It will extend the <literal>UsernamePasswordLoginModule</literal> and obtains a user's password and role names from a JNDI lookup. The idea is that there is a JNDI context that will return a user's password if you perform a lookup on the context using a name of the form <literal>password/<username></literal> where <literal><username></literal> is the current user being authenticated. Similarly, a lookup of the form <literal>roles/<username></literal> returns the requested user's roles.
- </para>
- <para>
- The source code for the example is located in the <literal>src/main/org/jboss/book/security/ex2</literal> directory of the book examples. <xref linkend="A_Custom_LoginModule_Example-_A_JndiUserAndPass_custom_login_module"/> shows the source code for the <literal>JndiUserAndPass</literal> custom login module. Note that because this extends the JBoss <literal>UsernamePasswordLoginModule</literal>, all the <literal>JndiUserAndPass</literal> does is obtain the user's password and roles from the JNDI store. The <literal>JndiUserAndPass</literal> does not concern itself with the JAAS <literal>LoginModule</literal> operations.
- </para>
- <example id="A_Custom_LoginModule_Example-_A_JndiUserAndPass_custom_login_module">
- <title> A JndiUserAndPass custom login module</title>
- <programlisting>package org.jboss.book.security.ex2;
-
-import java.security.acl.Group;
-import java.util.Map;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginException;
-
-import org.jboss.security.SimpleGroup;
-import org.jboss.security.SimplePrincipal;
-import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
-
-/**
- * An example custom login module that obtains passwords and roles
- * for a user from a JNDI lookup.
- *
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.4 $
-*/
-public class JndiUserAndPass
- extends UsernamePasswordLoginModule
-{
- /** The JNDI name to the context that handles the password/username lookup */
- private String userPathPrefix;
- /** The JNDI name to the context that handles the roles/ username lookup */
- private String rolesPathPrefix;
-
- /**
- * Override to obtain the userPathPrefix and rolesPathPrefix options.
- */
- public void initialize(Subject subject, CallbackHandler callbackHandler,
- Map sharedState, Map options)
- {
- super.initialize(subject, callbackHandler, sharedState, options);
- userPathPrefix = (String) options.get("userPathPrefix");
- rolesPathPrefix = (String) options.get("rolesPathPrefix");
- }
-
- /**
- * Get the roles the current user belongs to by querying the
- * rolesPathPrefix + '/' + super.getUsername() JNDI location.
- */
- protected Group[] getRoleSets() throws LoginException
- {
- try {
- InitialContext ctx = new InitialContext();
- String rolesPath = rolesPathPrefix + '/' + super.getUsername();
-
- String[] roles = (String[]) ctx.lookup(rolesPath);
- Group[] groups = {new SimpleGroup("Roles")};
- log.info("Getting roles for user="+super.getUsername());
- for(int r = 0; r < roles.length; r ++) {
- SimplePrincipal role = new SimplePrincipal(roles[r]);
- log.info("Found role="+roles[r]);
- groups[0].addMember(role);
- }
- return groups;
- } catch(NamingException e) {
- log.error("Failed to obtain groups for
- user="+super.getUsername(), e);
- throw new LoginException(e.toString(true));
- }
- }
-
- /**
- * Get the password of the current user by querying the
- * userPathPrefix + '/' + super.getUsername() JNDI location.
- */
- protected String getUsersPassword()
- throws LoginException
- {
- try {
- InitialContext ctx = new InitialContext();
- String userPath = userPathPrefix + '/' + super.getUsername();
- log.info("Getting password for user="+super.getUsername());
- String passwd = (String) ctx.lookup(userPath);
- log.info("Found password="+passwd);
- return passwd;
- } catch(NamingException e) {
- log.error("Failed to obtain password for
- user="+super.getUsername(), e);
- throw new LoginException(e.toString(true));
- }
- }
-}
-</programlisting>
- </example>
- <para>
- The details of the JNDI store are found in the <literal>org.jboss.book.security.ex2.service.JndiStore</literal> MBean. This service binds an <literal>ObjectFactory</literal> that returns a <literal>javax.naming.Context</literal> proxy into JNDI. The proxy handles lookup operations done against it by checking the prefix of the lookup name against <literal>password</literal> and <literal>roles</literal>. When the name begins with <literal>password</literal>, a user's password is being requested. When the name begins with <literal>roles</literal> the user's roles are being requested. The example implementation always returns a password of <literal>theduke</literal> and an array of roles names equal to <literal>{"TheDuke", "Echo"}</literal> regardless of what the username is. You can experiment with other implementations as you wish.
- </para>
- <para>
- The example code includes a simple session bean for testing the custom login module. To build, deploy and run the example, execute the following command in the examples directory.
- </para>
- <programlisting>[examples]$ ant -Dchap=security -Dex=2 run-example
-...
-run-example2:
- [echo] Waiting for 5 seconds for deploy...
- [java] [INFO,ExClient] Login with username=jduke, password=theduke
- [java] [INFO,ExClient] Looking up EchoBean2
- [java] [INFO,ExClient] Created Echo
- [java] [INFO,ExClient] Echo.echo('Hello') = Hello
-</programlisting>
- <para>
- The choice of using the <literal>JndiUserAndPass</literal> custom login module for the server side authentication of the user is determined by the login configuration for the example security domain. The EJB JAR <literal>META-INF/jboss.xml</literal> descriptor sets the security domain
- </para>
- <programlisting><?xml version="1.0"?>
-<jboss>
- <security-domain>java:/jaas/security-ex2</security-domain>
-</jboss>
-</programlisting>
- <para>
- The SAR <literal>META-INF/login-config.xml</literal> descriptor defines the login module configuration.
- </para>
- <programlisting><application-policy name = "security-ex2">
- <authentication>
- <login-module code="org.jboss.book.security.ex2.JndiUserAndPass"
- flag="required">
- <module-option name = "userPathPrefix">/security/store/password</module-option>
- <module-option name = "rolesPathPrefix">/security/store/roles</module-option>
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- </section>
- </section>
- </section>
- <section id="Security_on_JBoss-The_Secure_Remote_Password_SRP_Protocol">
- <title>The Secure Remote Password (SRP) Protocol</title>
- <para>
- The SRP protocol is an implementation of a public key exchange handshake described in the Internet standards working group request for comments 2945(RFC2945). The RFC2945 abstract states:
- </para>
- <para>
- This document describes a cryptographically strong network authentication mechanism known as the Secure Remote Password (SRP) protocol. This mechanism is suitable for negotiating secure connections using a user-supplied password, while eliminating the security problems traditionally associated with reusable passwords. This system also performs a secure key exchange in the process of authentication, allowing security layers (privacy and/or integrity protection) to be enabled during the session. Trusted key servers and certificate infrastructures are not required, and clients are not required to store or manage any long-term keys. SRP offers both security and deployment advantages over existing challenge-response techniques, making it an ideal drop-in replacement where secure password authentication is needed.
- </para>
- <para>
- Note: The complete RFC2945 specification can be obtained from <ulink url="http://www.rfc-editor.org/rfc.html"/>. Additional information on the SRP algorithm and its history can be found at <ulink url="http://www-cs-students.stanford.edu/~tjw/srp/"/>.
- </para>
- <para>
- SRP is similar in concept and security to other public key exchange algorithms, such as Diffie-Hellman and RSA. SRP is based on simple string passwords in a way that does not require a clear text password to exist on the server. This is in contrast to other public key-based algorithms that require client certificates and the corresponding certificate management infrastructure.
- </para>
- <para>
- Algorithms like Diffie-Hellman and RSA are known as public key exchange algorithms. The concept of public key algorithms is that you have two keys, one public that is available to everyone, and one that is private and known only to you. When someone wants to send encrypted information to you, then encrpyt the information using your public key. Only you are able to decrypt the information using your private key. Contrast this with the more traditional shared password based encryption schemes that require the sender and receiver to know the shared password. Public key algorithms eliminate the need to share passwords.
- </para>
- <para>
- The JBossSX framework includes an implementation of SRP that consists of the following elements:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- An implementation of the SRP handshake protocol that is independent of any particular client/server protocol
- </para>
- </listitem>
- <listitem>
- <para>
- An RMI implementation of the handshake protocol as the default client/server SRP implementation
- </para>
- </listitem>
- <listitem>
- <para>
- A client side JAAS <literal>LoginModule</literal> implementation that uses the RMI implementation for use in authenticating clients in a secure fashion
- </para>
- </listitem>
- <listitem>
- <para>
- A JMX MBean for managing the RMI server implementation. The MBean allows the RMI server implementation to be plugged into a JMX framework and externalizes the configuration of the verification information store. It also establishes an authentication cache that is bound into the JBoss server JNDI namespace.
- </para>
- </listitem>
- <listitem>
- <para>
- A server side JAAS <literal>LoginModule</literal> implementation that uses the authentication cache managed by the SRP JMX MBean.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- <xref linkend="The_Secure_Remote_Password_SRP_Protocol-The_JBossSX_components_of_the_SRP_client_server_framework."/> gives a diagram of the key components involved in the JBossSX implementation of the SRP client/server framework.
- </para>
- <figure id="The_Secure_Remote_Password_SRP_Protocol-The_JBossSX_components_of_the_SRP_client_server_framework.">
- <title>The JBossSX components of the SRP client-server framework.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-13.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>
- On the client side, SRP shows up as a custom JAAS <literal>LoginModule</literal> implementation that communicates to the authentication server through an <literal>org.jboss.security.srp.SRPServerInterface</literal> proxy. A client enables authentication using SRP by creating a login configuration entry that includes the <literal>org.jboss.security.srp.jaas.SRPLoginModule</literal>. This module supports the following configuration options:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">principalClassName</emphasis>: This option is no longer supported. The principal class is now always <literal>org.jboss.security.srp.jaas.SRPPrincipal</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">srpServerJndiName</emphasis>: The JNDI name of the <literal>SRPServerInterface</literal> object to use for communicating with the SRP authentication server. If both <literal>srpServerJndiName</literal> and <literal>srpServerRmiUrl</literal> options are specified, the <literal>srpServerJndiName</literal> is tried before <literal>srpServerRmiUrl</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">srpServerRmiUrl</emphasis>: The RMI protocol URL string for the location of the <literal>SRPServerInterface</literal> proxy to use for communicating with the SRP authentication server.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">externalRandomA</emphasis>: A true/false flag indicating if the random component of the client public key A should come from the user callback. This can be used to input a strong cryptographic random number coming from a hardware token for example.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">hasAuxChallenge</emphasis>: A true/false flag indicating that a string will be sent to the server as an additional challenge for the server to validate. If the client session supports an encryption cipher then a temporary cipher will be created using the session private key and the challenge object sent as a <literal>javax.crypto.SealedObject</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">multipleSessions</emphasis>: a true/false flag indicating if a given client may have multiple SRP login sessions active simultaneously.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Any other options passed in that do not match one of the previous named options is treated as a JNDI property to use for the environment passed to the <literal>InitialContext</literal> constructor. This is useful if the SRP server interface is not available from the default <literal>InitialContext</literal>.
- </para>
- <para>
- The <literal>SRPLoginModule</literal> needs to be configured along with the standard <literal>ClientLoginModule</literal> to allow the SRP authentication credentials to be used for validation of access to security J2EE components. An example login configuration entry that demonstrates such a setup is:
- </para>
- <programlisting>srp {
- org.jboss.security.srp.jaas.SRPLoginModule required
- srpServerJndiName="SRPServerInterface"
- ;
-
- org.jboss.security.ClientLoginModule required
- password-stacking="useFirstPass"
- ;
-};
-</programlisting>
- <para>
- On the JBoss server side, there are two MBeans that manage the objects that collectively make up the SRP server. The primary service is the <literal>org.jboss.security.srp.SRPService</literal> MBean, and it is responsible for exposing an RMI accessible version of the SRPServerInterface as well as updating the SRP authentication session cache. The configurable SRPService MBean attributes include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">JndiName</emphasis>: The JNDI name from which the SRPServerInterface proxy should be available. This is the location where the <literal>SRPService</literal> binds the serializable dynamic proxy to the <literal>SRPServerInterface</literal>. If not specified it defaults to <literal>srp/SRPServerInterface</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">VerifierSourceJndiName</emphasis>: The JNDI name of the <literal>SRPVerifierSource</literal> implementation that should be used by the <literal>SRPService</literal>. If not set it defaults to <literal>srp/DefaultVerifierSource</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">AuthenticationCacheJndiName</emphasis>: The JNDI name under which the authentication <literal>org.jboss.util.CachePolicy</literal> implementation to be used for caching authentication information is bound. The SRP session cache is made available for use through this binding. If not specified it defaults to <literal>srp/AuthenticationCache</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ServerPort</emphasis>: RMI port for the <literal>SRPRemoteServerInterface</literal>. If not specified it defaults to 10099.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ClientSocketFactory</emphasis>: An optional custom <literal>java.rmi.server.RMIClientSocketFactory</literal> implementation class name used during the export of the <literal>SRPServerInterface</literal>. If not specified the default <literal>RMIClientSocketFactory</literal> is used.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">ServerSocketFactory</emphasis>: An optional custom <literal>java.rmi.server.RMIServerSocketFactory</literal> implementation class name used during the export of the <literal>SRPServerInterface</literal>. If not specified the default <literal>RMIServerSocketFactory</literal> is used.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">AuthenticationCacheTimeout</emphasis>: Specifies the timed cache policy timeout in seconds. If not specified this defaults to 1800 seconds(30 minutes).
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">AuthenticationCacheResolution</emphasis>: Specifies the timed cache policy resolution in seconds. This controls the interval between checks for timeouts. If not specified this defaults to 60 seconds(1 minute).
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">RequireAuxChallenge</emphasis>: Set if the client must supply an auxiliary challenge as part of the verify phase. This gives control over whether the <literal>SRPLoginModule</literal> configuration used by the client must have the <literal>useAuxChallenge</literal> option enabled.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">OverwriteSessions</emphasis>: A flag indicating if a successful user auth for an existing session should overwrite the current session. This controls the behavior of the server SRP session cache when clients have not enabled the multiple session per user mode. The default is false meaning that the second attempt by a user to authentication will succeed, but the resulting SRP session will not overwrite the previous SRP session state.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The one input setting is the <literal>VerifierSourceJndiName</literal> attribute. This is the location of the SRP password information store implementation that must be provided and made available through JNDI. The <literal>org.jboss.security.srp SRPVerifierStoreService</literal> is an example MBean service that binds an implementation of the <literal>SRPVerifierStore</literal> interface that uses a file of serialized objects as the persistent store. Although not realistic for a production environment, it does allow for testing of the SRP protocol and provides an example of the requirements for an <literal>SRPVerifierStore</literal> service. The configurable <literal>SRPVerifierStoreService</literal> MBean attributes include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">JndiName</emphasis>: The JNDI name from which the <literal>SRPVerifierStore</literal> implementation should be available. If not specified it defaults to <literal>srp/DefaultVerifierSource</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">StoreFile</emphasis>: The location of the user password verifier serialized object store file. This can be either a URL or a resource name to be found in the classpath. If not specified it defaults to <literal>SRPVerifierStore.ser</literal>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The <literal>SRPVerifierStoreService</literal> MBean also supports <literal>addUser</literal> and <literal>delUser</literal> operations for addition and deletion of users. The signatures are:
- </para>
- <programlisting>public void addUser(String username, String password) throws IOException;
-public void delUser(String username) throws IOException;
-</programlisting>
- <para>
- An example configuration of these services is presented in <xref linkend="Providing_Password_Information_for_SRP-The_SRPVerifierStore_interface"/>.
- </para>
- <section id="The_Secure_Remote_Password_SRP_Protocol-Providing_Password_Information_for_SRP">
- <title>Providing Password Information for SRP</title>
- <para>
- The default implementation of the <literal>SRPVerifierStore</literal> interface is not likely to be suitable for your production security environment as it requires all password hash information to be available as a file of serialized objects. You need to provide an MBean service that provides an implementation of the <literal>SRPVerifierStore</literal> interface that integrates with your existing security information stores. The <literal>SRPVerifierStore</literal> interface is shown in.
- </para>
- <example id="Providing_Password_Information_for_SRP-The_SRPVerifierStore_interface">
- <title>The SRPVerifierStore interface</title>
- <programlisting>package org.jboss.security.srp;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.security.KeyException;
-
-public interface SRPVerifierStore
-{
- public static class VerifierInfo implements Serializable
- {
- /**
- * The username the information applies to. Perhaps redundant
- * but it makes the object self contained.
- */
- public String username;
-
- /** The SRP password verifier hash */
- public byte[] verifier;
- /** The random password salt originally used to verify the password */
- public byte[] salt;
- /** The SRP algorithm primitive generator */
- public byte[] g;
- /** The algorithm safe-prime modulus */
- public byte[] N;
- }
-
- /**
- * Get the indicated user's password verifier information.
- */
- public VerifierInfo getUserVerifier(String username)
- throws KeyException, IOException;
- /**
- * Set the indicated users' password verifier information. This
- * is equivalent to changing a user's password and should
- * generally invalidate any existing SRP sessions and caches.
- */
- public void setUserVerifier(String username, VerifierInfo info)
- throws IOException;
-
- /**
- * Verify an optional auxiliary challenge sent from the client to
- * the server. The auxChallenge object will have been decrypted
- * if it was sent encrypted from the client. An example of a
- * auxiliary challenge would be the validation of a hardware token
- * (SafeWord, SecureID, iButton) that the server validates to
- * further strengthen the SRP password exchange.
- */
- public void verifyUserChallenge(String username, Object auxChallenge)
- throws SecurityException;
-}
-</programlisting>
- <para>
- The primary function of a <literal>SRPVerifierStore</literal> implementation is to provide access to the <literal>SRPVerifierStore.VerifierInfo</literal> object for a given username. The <literal>getUserVerifier(String)</literal> method is called by the <literal>SRPService</literal> at that start of a user SRP session to obtain the parameters needed by the SRP algorithm. The elements of the <literal>VerifierInfo</literal> objects are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">username</emphasis>: The user's name or id used to login.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">verifier</emphasis>: This is the one-way hash of the password or PIN the user enters as proof of their identity. The <literal>org.jboss.security.Util</literal> class has a <literal>calculateVerifier</literal> method that performs that password hashing algorithm. The output password <literal>H(salt | H(username | ':' | password))</literal> as defined by RFC2945. Here <literal>H</literal> is the SHA secure hash function. The username is converted from a string to a <literal>byte[]</literal> using the UTF-8 encoding.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">salt</emphasis>: This is a random number used to increase the difficulty of a brute force dictionary attack on the verifier password database in the event that the database is compromised. It is a value that should be generated from a cryptographically strong random number algorithm when the user's existing clear-text password is hashed.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">g</emphasis>: The SRP algorithm primitive generator. In general this can be a well known fixed parameter rather than a per-user setting. The <literal>org.jboss.security.srp.SRPConf</literal> utility class provides several settings for g including a good default which can obtained via <literal>SRPConf.getDefaultParams().g()</literal>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">N</emphasis>: The SRP algorithm safe-prime modulus. In general this can be a well known fixed parameter rather than a per-user setting. The <literal>org.jboss.security.srp.SRPConf</literal> utility class provides several settings for <literal>N</literal> including a good default which can obtained via <literal>SRPConf.getDefaultParams().N()</literal>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- So, step 1 of integrating your existing password store is the creation of a hashed version of the password information. If your passwords are already store in an irreversible hashed form, then this can only be done on a per-user basis as part of an upgrade procedure for example. Note that the <literal>setUserVerifier(String, VerifierInfo)</literal> method is not used by the current SRPSerivce and may be implemented as no-op method, or even one that throws an exception stating that the store is read-only.
- </para>
- <para>
- Step 2 is the creation of the custom <literal>SRPVerifierStore</literal> interface implementation that knows how to obtain the <literal>VerifierInfo</literal> from the store you created in step 1. The <literal>verifyUserChallenge(String, Object)</literal> method of the interface is only called if the client <literal>SRPLoginModule</literal> configuration specifies the <literal>hasAuxChallenge</literal> option. This can be used to integrate existing hardware token based schemes like SafeWord or Radius into the SRP algorithm.
- </para>
- <para>
- Step 3 is the creation of an MBean that makes the step 2 implementation of the <literal>SRPVerifierStore</literal> interface available via JNDI, and exposes any configurable parameters you need. In addition to the default <literal>org.jboss.security.srp.SRPVerifierStoreService</literal> example, the SRP example presented later in this chapter provides a Java properties file based <literal>SRPVerifierStore</literal> implementation. Between the two examples you should have enough to integrate your security store.
- </para>
- </example>
- </section>
- <section id="The_Secure_Remote_Password_SRP_Protocol-Inside_of_the_SRP_algorithm">
- <title>Inside of the SRP algorithm</title>
- <para>
- The appeal of the SRP algorithm is that is allows for mutual authentication of client and server using simple text passwords without a secure communication channel. You might be wondering how this is done. If you want the complete details and theory behind the algorithm, refer to the SRP references mentioned in a note earlier. There are six steps that are performed to complete authentication:
- </para>
- <orderedlist>
- <listitem>
- <para>
- The client side <literal>SRPLoginModule</literal> retrieves the SRPServerInterface instance for the remote authentication server from the naming service.
- </para>
- </listitem>
- <listitem>
- <para>
- The client side <literal>SRPLoginModule</literal> next requests the SRP parameters associated with the username attempting the login. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. The <literal>getSRPParameters(username)</literal> call retrieves the SRP parameters for the given username.
- </para>
- </listitem>
- <listitem>
- <para>
- The client side <literal>SRPLoginModule</literal> begins an SRP session by creating an <literal>SRPClientSession</literal> object using the login username, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking the <literal>SRPServerInterface.init</literal> method and passes in the username and client generated random number <literal>A</literal>. The server returns its own random number <literal>B</literal>. This step corresponds to the exchange of public keys.
- </para>
- </listitem>
- <listitem>
- <para>
- The client side <literal>SRPLoginModule</literal> obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the login <literal>Subject</literal>. The server challenge response <literal>M2</literal> from step 4 is verified by invoking the <literal>SRPClientSession.verify</literal> method. If this succeeds, mutual authentication of the client to server, and server to client have been completed. The client side <literal>SRPLoginModule</literal> next creates a challenge <literal>M1</literal> to the server by invoking <literal>SRPClientSession.response</literal> method passing the server random number <literal>B</literal> as an argument. This challenge is sent to the server via the <literal>SRPServerInterface.verify</literal> method and server's response is saved as <literal>M2</literal>. This step corresponds to an exchange of challenges. At this point the server has verified t!
hat the user is who they say they are.
- </para>
- </listitem>
- <listitem>
- <para>
- The client side <literal>SRPLoginModule</literal> saves the login username and <literal>M1</literal> challenge into the <literal>LoginModule</literal> sharedState map. This is used as the Principal name and credentials by the standard JBoss <literal>ClientLoginModule</literal>. The <literal>M1</literal> challenge is used in place of the password as proof of identity on any method invocations on J2EE components. The <literal>M1</literal> challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password.
- </para>
- </listitem>
- <listitem>
- <para>
- At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the <literal>SRPCacheLoginModule</literal>.
- </para>
- </listitem>
- </orderedlist>
- <para>
- Although SRP has many interesting properties, it is still an evolving component in the JBossSX framework and has some limitations of which you should be aware. Issues of note include the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Because of how JBoss detaches the method transport protocol from the component container where authentication is performed, an unauthorized user could snoop the SRP <literal>M1</literal> challenge and effectively use the challenge to make requests as the associated username. Custom interceptors that encrypt the challenge using the SRP session key can be used to prevent this issue.
- </para>
- </listitem>
- <listitem>
- <para>
- The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent J2EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout very long (up to 2,147,483,647 seconds, or approximately 68 years), or handle re-authentication in your code on failure.
- </para>
- </listitem>
- <listitem>
- <para>
- By default there can only be one SRP session for a given username. Because the negotiated SRP session produces a private session key that can be used for encryption/decryption between the client and server, the session is effectively a stateful one. JBoss supports for multiple SRP sessions per user, but you cannot encrypt data with one session key and then decrypt it with another.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- To use end-to-end SRP authentication for J2EE component calls, you need to configure the security domain under which the components are secured to use the <literal>org.jboss.security.srp.jaas.SRPCacheLoginModule</literal>. The <literal>SRPCacheLoginModule</literal> has a single configuration option named <literal>cacheJndiName</literal> that sets the JNDI location of the SRP authentication <literal>CachePolicy</literal> instance. This must correspond to the <literal>AuthenticationCacheJndiName</literal> attribute value of the <literal>SRPService</literal> MBean. The <literal>SRPCacheLoginModule</literal> authenticates user credentials by obtaining the client challenge from the <literal>SRPServerSession</literal> object in the authentication cache and comparing this to the challenge passed as the user credentials. <xref linkend="Inside_of_the_SRP_algorithm-A_sequence_diagram_illustrating_the_interaction_of_the_SRPCacheLoginModule_with_the_SRP_session_cache."/> illustrate!
s the operation of the SRPCacheLoginModule.login method implementation.
- </para>
- <figure id="Inside_of_the_SRP_algorithm-A_sequence_diagram_illustrating_the_interaction_of_the_SRPCacheLoginModule_with_the_SRP_session_cache.">
- <title>A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/j2ee_chap8-14.jpg" align="center"/>
- </imageobject>
- </mediaobject>
- </figure>
- <section id="Inside_of_the_SRP_algorithm-An_SRP_example">
- <title>An SRP example</title>
- <para>
- We have covered quite a bit of material on SRP and now its time to demonstrate SRP in practice with an example. The example demonstrates client side authentication of the user via SRP as well as subsequent secured access to a simple EJB using the SRP session challenge as the user credential. The test code deploys an EJB JAR that includes a SAR for the configuration of the server side login module configuration and SRP services. As in the previous examples we will dynamically install the server side login module configuration using the <literal>SecurityConfig</literal> MBean. In this example we also use a custom implementation of the <literal>SRPVerifierStore</literal> interface that uses an in memory store that is seeded from a Java properties file rather than a serialized object store as used by the <literal>SRPVerifierStoreService</literal>. This custom service is <literal>org.jboss.book.security.ex3.service.PropertiesVerifierStore</literal>. The following shows the !
contents of the JAR that contains the example EJB and SRP services.
- </para>
- <programlisting>[examples]$ jar tf output/security/security-ex3.jar
-META-INF/MANIFEST.MF
-META-INF/ejb-jar.xml
-META-INF/jboss.xml
-org/jboss/book/security/ex3/Echo.class
-org/jboss/book/security/ex3/EchoBean.class
-org/jboss/book/security/ex3/EchoHome.class
-roles.properties
-users.properties
-security-ex3.sar
-</programlisting>
- <para>
- The key SRP related items in this example are the SRP MBean services configuration, and the SRP login module configurations. The <literal>jboss-service.xml</literal> descriptor of the <literal>security-ex3.sar</literal> is given in <xref linkend="An_SRP_example-The_security_ex3.sar_jboss_service.xml_descriptor_for_the_SRP_services"/>, while <xref linkend="An_SRP_example-The_client_side_standard_JAAS_configuration"/> and <xref linkend="An_SRP_example-The_server_side_XMLLoginConfig_configuration"/> give the example client side and server side login module configurations.
- </para>
- <example id="An_SRP_example-The_security_ex3.sar_jboss_service.xml_descriptor_for_the_SRP_services">
- <title>The security-ex3.sar jboss-service.xml descriptor for the SRP services</title>
- <programlisting><server>
- <!-- The custom JAAS login configuration that installs
- a Configuration capable of dynamically updating the
- config settings -->
-
- <mbean code="org.jboss.book.security.service.SecurityConfig"
- name="jboss.docs.security:service=LoginConfig-EX3">
- <attribute name="AuthConfig">META-INF/login-config.xml</attribute>
- <attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute>
- </mbean>
-
- <!-- The SRP service that provides the SRP RMI server and server side
- authentication cache -->
- <mbean code="org.jboss.security.srp.SRPService"
- name="jboss.docs.security:service=SRPService">
- <attribute name="VerifierSourceJndiName">srp-test/security-ex3</attribute>
- <attribute name="JndiName">srp-test/SRPServerInterface</attribute>
- <attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute>
- <attribute name="ServerPort">0</attribute>
- <depends>jboss.docs.security:service=PropertiesVerifierStore</depends>
- </mbean>
-
- <!-- The SRP store handler service that provides the user password verifier
- information -->
- <mbean code="org.jboss.security.ex3.service.PropertiesVerifierStore"
- name="jboss.docs.security:service=PropertiesVerifierStore">
- <attribute name="JndiName">srp-test/security-ex3</attribute>
- </mbean>
-</server>
-</programlisting>
- </example>
- <example id="An_SRP_example-The_client_side_standard_JAAS_configuration">
- <title>The client side standard JAAS configuration</title>
- <programlisting>srp {
- org.jboss.security.srp.jaas.SRPLoginModule required
- srpServerJndiName="srp-test/SRPServerInterface"
- ;
-
- org.jboss.security.ClientLoginModule required
- password-stacking="useFirstPass"
- ;
-};
-</programlisting>
- </example>
- <example id="An_SRP_example-The_server_side_XMLLoginConfig_configuration">
- <title>The server side XMLLoginConfig configuration</title>
- <programlisting><application-policy name="security-ex3">
- <authentication>
- <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
- flag = "required">
- <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
- </login-module>
- <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
- flag = "required">
- <module-option name="password-stacking">useFirstPass</module-option>
- </login-module>
- </authentication>
-</application-policy>
-</programlisting>
- </example>
- <para>
- The example services are the <literal>ServiceConfig</literal> and the <literal>PropertiesVerifierStore</literal> and <literal>SRPService</literal> MBeans. Note that the <literal>JndiName</literal> attribute of the <literal>PropertiesVerifierStore</literal> is equal to the <literal>VerifierSourceJndiName</literal> attribute of the <literal>SRPService</literal>, and that the <literal>SRPService</literal> depends on the <literal>PropertiesVerifierStore</literal>. This is required because the <literal>SRPService</literal> needs an implementation of the <literal>SRPVerifierStore</literal> interface for accessing user password verification information.
- </para>
- <para>
- The client side login module configuration makes use of the <literal>SRPLoginModule</literal> with a <literal>srpServerJndiName</literal> option value that corresponds to the JBoss server component <literal>SRPService</literal> JndiName attribute value(<literal>srp-test/SRPServerInterface</literal>). Also needed is the <literal>ClientLoginModule</literal> configured with the <literal>password-stacking="useFirstPass"</literal> value to propagate the user authentication credentials generated by the <literal>SRPLoginModule</literal> to the EJB invocation layer.
- </para>
- <para>
- There are two issues to note about the server side login module configuration. First, note the <literal>cacheJndiName=srp-test/AuthenticationCache</literal> configuration option tells the <literal>SRPCacheLoginModule</literal> the location of the <literal>CachePolicy</literal> that contains the <literal>SRPServerSession</literal> for users who have authenticated against the <literal>SRPService</literal>. This value corresponds to the <literal>SRPService</literal><literal>AuthenticationCacheJndiName</literal> attribute value. Second, the configuration includes a <literal>UsersRolesLoginModule</literal> with the <literal>password-stacking=useFirstPass</literal> configuration option. It is required to use a second login module with the <literal>SRPCacheLoginModule</literal> because SRP is only an authentication technology. A second login module needs to be configured that accepts the authentication credentials validated by the <literal>SRPCacheLoginModule</literal> to set!
the principal's roles that determines the principal's permissions. The <literal>UsersRolesLoginModule</literal> is augmenting the SRP authentication with properties file based authorization. The user's roles are coming the <literal>roles.properties</literal> file included in the EJB JAR.
- </para>
- <para>
- Now, run the example 3 client by executing the following command from the book examples directory:
- </para>
- <programlisting>[examples]$ ant -Dchap=security -Dex=3 run-example
-...
-run-example3:
- [echo] Waiting for 5 seconds for deploy...
- [java] Logging in using the 'srp' configuration
- [java] Created Echo
- [java] Echo.echo()#1 = This is call 1
- [java] Echo.echo()#2 = This is call 2
-</programlisting>
- <para>
- In the <literal>examples/logs</literal> directory you will find a file called <literal>ex3-trace.log</literal>. This is a detailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key and verification.
- </para>
- <para>
- Note that the client has taken a long time to run relative to the other simple examples. The reason for this is the construction of the client's public key. This involves the creation of a cryptographically strong random number, and this process takes quite a bit of time the first time it occurs. If you were to log out and log in again within the same VM, the process would be much faster. Also note that <literal>Echo.echo()#2</literal> fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the <literal>SRPService</literal> cache expiration. The <literal>SRPService</literal> cache policy timeout has been set to a mere 10 seconds to force this issue. As stated earlier, you need to make the cache timeout very long, or handle re-authentication on failure.
- </para>
- </section>
- </section>
- </section>
- <section id="Security_on_JBoss-Running_JBoss_with_a_Java_2_security_manager">
- <title>Running JBoss with a Java 2 security manager</title>
- <para>
- By default the JBoss server does not start with a Java 2 security manager. If you want to restrict privileges of code using Java 2 permissions you need to configure the JBoss server to run under a security manager. This is done by configuring the Java VM options in the <literal>run.bat</literal> or <literal>run.sh</literal> scripts in the JBoss server distribution bin directory. The two required VM options are as follows:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="bold">java.security.manager</emphasis>: This is used without any value to specify that the default security manager should be used. This is the preferred security manager. You can also pass a value to the <literal>java.security.manager</literal> option to specify a custom security manager implementation. The value must be the fully qualified class name of a subclass of <literal>java.lang.SecurityManager</literal>. This form specifies that the policy file should augment the default security policy as configured by the VM installation.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="bold">java.security.policy</emphasis>: This is used to specify the policy file that will augment the default security policy information for the VM. This option takes two forms: <literal>java.security.policy=policyFileURL</literal> and <literal>java.security.policy==policyFileURL</literal>. The first form specifies that the policy file should augment the default security policy as configured by the VM installation. The second form specifies that only the indicated policy file should be used. The <literal>policyFileURL</literal> value can be any URL for which a protocol handler exists, or a file path specification.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Both the <literal>run.bat</literal> and <literal>run.sh</literal> start scripts reference an JAVA_OPTS variable which you can use to set the security manager properties.
- </para>
- <para>
- Enabling Java 2 security is the easy part. The difficult part of Java 2 security is establishing the allowed permissions. If you look at the <literal>server.policy</literal> file that is contained in the default configuration file set, you'll see that it contains the following permission grant statement:
- </para>
- <programlisting>grant {
- // Allow everything for now
- permission java.security.AllPermission;
-};
-</programlisting>
- <para>
- This effectively disables security permission checking for all code as it says any code can do anything, which is not a reasonable default. What is a reasonable set of permissions is entirely up to you.
- </para>
- <para>
- The current set of JBoss specific <literal>java.lang.RuntimePermissions</literal> that are required include:
- </para>
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry> TargetName </entry>
- <entry> What the permission allows </entry>
- <entry> Risks </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry> org.jboss.security.SecurityAssociation.getPrincipalInfo </entry>
- <entry> Access to the org.jboss.security.SecurityAssociation getPrincipal() and getCredentials() methods. </entry>
- <entry> The ability to see the current thread caller and credentials. </entry>
- </row>
- <row>
- <entry> org.jboss.security.SecurityAssociation.setPrincipalInfo </entry>
- <entry> Access to the org.jboss.security.SecurityAssociation setPrincipal() and setCredentials() methods. </entry>
- <entry> The ability to set the current thread caller and credentials. </entry>
- </row>
- <row>
- <entry> org.jboss.security.SecurityAssociation.setServer </entry>
- <entry> Access to the org.jboss.security.SecurityAssociation setServer method. </entry>
- <entry> The ability to enable or disable multithread storage of the caller principal and credential. </entry>
- </row>
- <row>
- <entry> org.jboss.security.SecurityAssociation.setRunAsRole </entry>
- <entry> Access to the org.jboss.security.SecurityAssociation pushRunAsRole and popRunAsRole methods. </entry>
- <entry> The ability to change the current caller run-as role principal. </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <para>
- To conclude this discussion, here is a little-known tidbit on debugging security policy settings. There are various debugging flag that you can set to determine how the security manager is using your security policy file as well as what policy files are contributing permissions. Running the VM as follows shows the possible debugging flag settings:
- </para>
- <programlisting>[bin]$ java -Djava.security.debug=help
-
-all turn on all debugging
-access print all checkPermission results
-combiner SubjectDomainCombiner debugging
-jar jar verification
-logincontext login context results
-policy loading and granting
-provider security provider debugging
-scl permissions SecureClassLoader assigns
-
-The following can be used with access:
-
-stack include stack trace
-domain dumps all domains in context
-failure before throwing exception, dump stack
- and domain that didn't have permission
-
-Note: Separate multiple options with a comma
-</programlisting>
- <para>
- Running with <literal>-Djava.security.debug=all</literal> provides the most output, but the output volume is torrential. This might be a good place to start if you don't understand a given security failure at all. A less verbose setting that helps debug permission failures is to use <literal>-Djava.security.debug=access,failure</literal>. This is still relatively verbose, but not nearly as bad as the all mode as the security domain information is only displayed on access failures.
- </para>
- </section>
- <section id="Security_on_JBoss-Using_SSL_with_JBoss_using_JSSE">
- <title>Using SSL with JBoss</title>
- <section id="Adding_SSL_to_EJB3">
- <title>Adding SSL to EJB3</title>
- <para>
- By default JBoss EJB3 uses a socket based invoker layer on port 3878. This is set up in <filename> $JBOSS_HOME/server/<replaceable><serverconfig></replaceable>/deploy/ejb3.deployer/META-INF/jboss-service.xml</filename>. In some cases you may wish to use SSL as the protocol. In order to do this you must generate a keystore and then configure your beans to use SSL transport.
- </para>
- <section id="Adding_SSL_to_EJB3_Generating_the_keystore_and_truststore">
- <title>Generating the keystore and truststore</title>
- <para>
- For SSL to work you need to create a public/private key pair, which will be stored in a keystore. Generate this using the <literal>genkey</literal> command that comes with the JDK.
-<programlisting>
- $cd $JBOSS_HOME/server/production/conf/
- $keytool -genkey -alias ejb3-ssl -keypass opensource -keystore localhost.keystore
- Enter keystore password: opensource
- What is your first and last name?
- [Unknown]:
- What is the name of your organizational unit?
- [Unknown]:
- What is the name of your organization?
- [Unknown]:
- What is the name of your City or Locality?
- [Unknown]:
- What is the name of your State or Province?
- [Unknown]:
- What is the two-letter country code for this unit?
- [Unknown]:
- Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
- [no]: yes
-</programlisting>
- where <literal>alias</literal> is the name ("ejb2-ssl") of the key pair within the keystore. <literal>keypass</literal> is the password ("opensource") for the keystore, and <literal>keystore</literal> specifies the location ("localhost.keystore") of the keystore to create/add to.
- </para>
- <para>
- Since you have not signed our certificate through any certification authoritiy, you also need to create a truststore for the client, explicitly saying that you trust the certificate you just created. The first step is to export the certificate using the JDK keytool:
-<programlisting>
- $ keytool -export -alias ejb3-ssl -file mycert.cer -keystore localhost.keystore
- Enter keystore password: opensource
- Certificate stored in file <mycert.cer>
-</programlisting>
- </para>
- <para>
- Then you need to create the truststore if it does not exist and import the certificate into the trueststore:
-<programlisting>
- $ keytool -import -alias ejb3-ssl -file mycert.cer -keystore localhost.truststore
- Enter keystore password: opensource
- Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
- Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
- Serial number: 43bff927
- Valid from: Sat Jan 07 18:23:51 CET 2006 until: Fri Apr 07 19:23:51 CEST 2006
- Certificate fingerprints:
- MD5: CF:DC:71:A8:F4:EA:8F:5A:E9:94:E3:E6:5B:A9:C8:F3
- SHA1: 0E:AD:F3:D6:41:5E:F6:84:9A:D1:54:3D:DE:A9:B2:01:28:F6:7C:26
- Trust this certificate? [no]: yes
- Certificate was added to keystore
-</programlisting>
- </para>
- </section>
- <section>
- <title id="Adding_SSL_to_EJB3_Setting_up_the_SSL_transport">Setting up the SSL transport</title>
- <para>
- The simplest way to define an SSL transport is to define a new Remoting connector using the <literal>sslsocket</literal> protocol as follows. This transport will listen on port 3843:
-<programlisting>
- <mbean code="org.jboss.remoting.transport.Connector"
- xmbean-dd="org/jboss/remoting/transport/Connector.xml"
- name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
- <depends>jboss.aop:service=AspectDeployer</depends>
- <attribute name="InvokerLocator">sslsocket://0.0.0.0:3843</attribute>
- <attribute name="Configuration">
- <handlers>
- <handler subsystem="AOP">
- org.jboss.aspects.remoting.AOPRemotingInvocationHandler
- </handler>
- </handlers>
- </attribute>
- </mbean>
-</programlisting>
- </para>
- <para>
- Now you need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using <literal>javax.net.ssl.keyStore</literal> and <literal>javax.net.ssl.keyStorePassword=opensource</literal> system properties when starting JBoss, as the following example shows:
-<programlisting>
- $cd $JBOSS_HOME/bin
- $ run -Djavax.net.ssl.keyStore=../server/production/conf/localhost.keystore
- -Djavax.net.ssl.keyStorePassword=opensource
-</programlisting>
- </para>
- </section>
- <section id="Adding_SSL_to_EJB3_Configuring_your_beans">
- <title>Configuring your beans to use the SSL transport</title>
- <para>
- By default all the beans will use the default connector on <literal>socket://0.0.0.0:3873</literal>. By using the <literal>@org.jboss.annotation.ejb.RemoteBinding</literal> annotation you can have the bean invokable via SSL.
-<programlisting>
- @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
- @Remote(BusinessInterface.class)
- public class StatefulBean implements BusinessInterface
- {
- ...
- }
-</programlisting>
- </para>
- <para>
- This bean will be bound under the JNDI name <literal>StatefulSSL</literal> and the proxy implementing the remote interface returned to the client will communicate with the server via SSL.
- </para>
- <para>
- You can also enable different types of communication for your beans
-<programlisting>
- @RemoteBindings({
- @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
- @RemoteBinding(jndiBinding="StatefulNormal")
- })
- @Remote(BusinessInterface.class)
- public class StatefulBean implements BusinessInterface
- {
- ...
- }
-</programlisting>
- </para>
- <para>
- Now if you look up <literal>StatefulNormal</literal> the returned proxy implementing the remote interface will communicate with the server via the normal unencrypted socket protocol, and if you look up <literal>StatefulSSL</literal> the returned proxy implementing the remote interface will communicate with the server via SSL.
- </para>
- </section>
- <section id="Adding_SSL_to_EJB3_Setting_up_the_client_to_use_truststore">
- <title>Setting up the client to use the truststore</title>
- <para>
-If not using a certificate signed by a certificate authorization authority, you need to point the client to the truststore using the <literal>javax.net.ssl.trustStore</literal> system property and specify the password using the <literal>javax.net.ssl.trustStorePassword</literal> system property:
-<programlisting>
-java -Djavax.net.ssl.trustStore=${resources}/test/ssl/localhost.truststore
- -Djavax.net.ssl.trustStorePassword=opensource com.acme.RunClient
-</programlisting>
- </para>
- </section>
- </section>
- <section id="Adding_SSL_to_EJB2.1">
- <title>Adding SSL to EJB 2.1 calls</title>
- <section id="Adding_SSL_to_EJB2.1_Generating_the_keystore_and_truststore">
- <title>Generating the keystore and truststore</title>
- <para>
- This is similar to the steps described for Adding SSL to EJB3 calls.
- </para>
- </section>
- <section id="Adding_SSL_to_EJB2.1_Setting_up_the_SSL_transport">
- <title>Setting up the SSL transport</title>
- <para>
-Now you need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using <literal>javax.net.ssl.keyStore</literal> and <literal>javax.net.ssl.keyStorePassword=opensource</literal> system properties when starting JBoss, as the following example shows:
-<programlisting>
- $cd $JBOSS_HOME/bin
- $ run -Djavax.net.ssl.keyStore=../server/production/conf/localhost.keystore
- -Djavax.net.ssl.keyStorePassword=opensource
-</programlisting>
- </para>
- <para>
- If you wish to customize the SSLSocketBuilder you need to add the following to your <literal>$JBOSS_HOME/server/${serverConf}/conf/jboss-service.xml</literal> file.
-<programlisting>
- <!-- This section is for custom (SSL) server socket factory -->
- <mbean code="org.jboss.remoting.security.SSLSocketBuilder"
- name="jboss.remoting:service=SocketBuilder,type=SSL"
- display-name="SSL Server Socket Factory Builder">
- <!-- IMPORTANT - If making ANY customizations, this MUST be set to false. -->
- <!-- Otherwise, will used default settings and the following attributes will be ignored. -->
- <attribute name="UseSSLServerSocketFactory">false</attribute>
- <!-- This is the url string to the key store to use -->
- <attribute name="KeyStoreURL">localhost.keystore</attribute>
- <!-- The password for the key store -->
- <attribute name="KeyStorePassword">sslsocket</attribute>
- <!-- The password for the keys (will use KeystorePassword if this is not set explicitly. -->
- <attribute name="KeyPassword">sslsocket</attribute>
- <!-- The protocol for the SSLContext. Default is TLS. -->
- <attribute name="SecureSocketProtocol">TLS</attribute>
- <!-- The algorithm for the key manager factory. Default is SunX509. -->
- <attribute name="KeyManagementAlgorithm">SunX509</attribute>
- <!-- The type to be used for the key store. -->
- <!-- Defaults to JKS. Some acceptable values are JKS (Java Keystore - Sun's keystore format), -->
- <!-- JCEKS (Java Cryptography Extension keystore - More secure version of JKS), and -->
- <!-- PKCS12 (Public-Key Cryptography Standards #12
- keystore - RSA's Personal Information Exchange Syntax Standard). -->
- <!-- These are not case sensitive. -->
- <attribute name="KeyStoreType">JKS</attribute>
- </mbean>
-</programlisting>
-<programlisting>
-<mbean code="org.jboss.remoting.security.SSLServerSocketFactoryService"
- name="jboss.remoting:service=ServerSocketFactory,type=SSL"
- display-name="SSL Server Socket Factory">
- <depends optional-attribute-name="SSLSocketBuilder"
- proxy-type="attribute">jboss.remoting:service=SocketBuilder,type=SSL</depends>
- </mbean>
-</programlisting>
- </para>
- </section>
- <section id="Adding_SSL_to_EJB2.1_configuring_your_beans">
- <title>Configuring your beans to use the SSL transport</title>
- <para>
- In your <literal>$JBOSS_HOME/server/${serverConf}/conf/jboss-service.xml</literal> file, comment out the following lines:
-<programlisting>
-<mbean code="org.jboss.remoting.transport.Connector"
- name="jboss.remoting:service=Connector,transport=socket"
- display-name="Socket transport Connector">
-
- <!-- Can either just specify the InvokerLocator attribute and not the invoker element in the -->
- <!-- Configuration attribute, or do the full invoker configuration in the in invoker element -->
- <!-- of the Configuration attribute. -->
-
- <!-- Remember that if you do use more than one param on the uri, will have to include as a CDATA, -->
- <!-- otherwise, parser will complain. -->
- <!--
- <attribute name="InvokerLocator">
- <![CDATA[socket://${jboss.bind.address}:4446/?datatype=invocation]]>
- </attribute>
- -->
-
- <attribute name="Configuration">
- <!-- Using the following
- <invoker>
- element instead of the InvokerLocator above because specific attributes needed.
- -->
- <!-- If wanted to use any of the parameters below, can
- just add them as parameters to the url above if wanted use
- the InvokerLocator attribute. -->
- <config>
- <!-- Other than transport type and handler, none of these configurations are required
- (will just use defaults). -->
- <invoker transport="socket">
- <attribute name="dataType" isParam="true">invocation</attribute>
- <attribute name="marshaller"
- isParam="true">org.jboss.invocation.unified.marshall.InvocationMarshaller</attribute>
- <attribute name="unmarshaller"
- isParam="true">org.jboss.invocation.unified.marshall.InvocationUnMarshaller</attribute>
- <!-- This will be port on which the marshall loader port runs on. -->
- <!-- <attribute name="loaderport" isParam="true">4447</attribute> -->
- <!-- The following are specific to socket invoker -->
- <!-- <attribute name="numAcceptThreads">1</attribute>-->
- <!-- <attribute name="maxPoolSize">303</attribute>-->
- <!-- <attribute name="clientMaxPoolSize" isParam="true">304</attribute>-->
- <attribute name="socketTimeout" isParam="true">600000</attribute>
- <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
- <attribute name="serverBindPort">4446</attribute>
- <!-- <attribute name="clientConnectAddress">216.23.33.2</attribute> -->
- <!-- <attribute name="clientConnectPort">7777</attribute> -->
- <attribute name="enableTcpNoDelay" isParam="true">true</attribute>
- <!-- <attribute name="backlog">200</attribute>-->
- <!-- The following is for callback configuration and is independant of invoker type -->
- <!-- <attribute name="callbackMemCeiling">30</attribute>-->
- <!-- indicates callback store by fully qualified class name -->
- <!-- <attribute name="callbackStore">org.jboss.remoting.CallbackStore</attribute>-->
- <!-- indicates callback store by object name -->
- <!--
- <attribute name="callbackStore">
- jboss.remoting:service=CallbackStore,type=Serializable
- </attribute>
- -->
- <!-- config params for callback store. if were declaring callback store via object name, -->
- <!-- could have specified these config params there. -->
- <!-- StoreFilePath indicates to which directory to write the callback objects. -->
- <!-- The default value is the property value of 'jboss.server.data.dir' and
- if this is not set, -->
- <!-- then will be 'data'. Will then append 'remoting' and the callback client's session id. -->
- <!-- An example would be 'data\remoting\5c4o05l-9jijyx-e5b6xyph-1-e5b6xyph-2'. -->
- <!-- <attribute name="StoreFilePath">callback</attribute>-->
- <!-- StoreFileSuffix indicates the file suffix to use
- for the callback objects written to disk. -->
- <!-- The default value for file suffix is 'ser'. -->
- <!-- <attribute name="StoreFileSuffix">cst</attribute>-->
- </invoker>
-
- <!-- At least one handler is required by the connector. If have more than one, must decalre -->
- <!-- different subsystem values. Otherwise, all invocations will be routed to the only one -->
- <!-- that is declared. -->
- <handlers>
- <!-- can also specify handler by fully qualified classname -->
- <handler subsystem="invoker">jboss:service=invoker,type=unified</handler>
- </handlers>
- </config>
- </attribute>
- <depends>jboss.remoting:service=NetworkRegistry</depends>
- </mbean>
-</programlisting>
- and add the following in it's place:
-<programlisting>
- <mbean code="org.jboss.remoting.transport.Connector"
- xmbean-dd="org/jboss/remoting/transport/Connector.xml"
- name="jboss.remoting:service=Connector,transport=sslsocket">
- display-name="SSL Socket transport Connector">
-
- <attribute name="Configuration">
- <config>
- <invoker transport="sslsocket">
- <attribute name="serverSocketFactory">
- jboss.remoting:service=ServerSocketFactory,type=SSL
- </attribute>
- <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
- <attribute name="serverBindPort">3843</attribute>
- </invoker>
- <handlers>
- <handler subsystem="invoker">jboss:service=invoker,type=unified</handler>
- </handlers>
- </config>
- </attribute>
- <!--If you specify the keystore and password in the command line and you're
- not using the custom ServerSocketFactory, you should take out the following line-->
- <depends>jboss.remoting:service=ServerSocketFactory,type=SSL</depends>
- <depends>jboss.remoting:service=NetworkRegistry</depends>
- </mbean>
-</programlisting>
- </para>
- </section>
- <section id="Adding_SSL_to_EJB2.1_Setting_up_the_client_to_use_truststore">
- <title>Setting up the client to use the truststore</title>
- <para>
- This is similar to the steps described for EJB3.
- </para>
- </section>
- </section>
- </section>
- <section id="Security_on_JBoss-Configuring_JBoss_for_use_Behind_a_Firewall">
- <title>Configuring JBoss for use Behind a Firewall</title>
- <para>
- JBoss comes with many socket based services that open listening ports. In this section we list the services that open ports that might need to be configured to work when accessing JBoss behind a firewall. The following table shows the ports, socket type, associated service for the services in the default configuration file set. <xref linkend="Configuring_JBoss_for_use_Behind_a_Firewall-Additional_ports_in_the_all_configuration"/> shows the same information for the additional ports that exist in the all configuration file set.
- </para>
- <table id="Configuring_JBoss_for_use_Behind_a_Firewall-The_ports_found_in_the_default_configuration">
- <title>The ports found in the default configuration</title>
- <tgroup cols="3">
- <colspec colname="c1" colnum="1" colwidth=".25*"/>
- <colspec colname="c2" colnum="2" colwidth=".25*"/>
- <colspec colname="c3" colnum="3" colwidth="1*"/>
- <thead>
- <row>
- <entry> Port </entry>
- <entry> Type </entry>
- <entry> Service </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry> 1098 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.naming.NamingService</literal>
- </entry>
- </row>
- <row>
- <entry> 1099 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.naming.NamingService</literal>
- </entry>
- </row>
- <row>
- <entry> 4444 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.invocation.jrmp.server.JRMPInvoker</literal>
- </entry>
- </row>
- <row>
- <entry> 4445 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.invocation.pooled.server.PooledInvoker</literal>
- </entry>
- </row>
- <row>
- <entry> 8009 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.web.tomcat.tc4.EmbeddedTomcatService</literal>
- </entry>
- </row>
- <row>
- <entry> 8080 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.web.tomcat.tc4.EmbeddedTomcatService</literal>
- </entry>
- </row>
- <row>
- <entry> 8083 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.web.WebService</literal>
- </entry>
- </row>
- <row>
- <entry> 8093 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.mq.il.uil2.UILServerILService</literal>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table id="Configuring_JBoss_for_use_Behind_a_Firewall-Additional_ports_in_the_all_configuration">
- <title>Additional ports in the all configuration</title>
- <tgroup cols="3">
- <colspec colname="c1" colnum="1" colwidth=".25*"/>
- <colspec colname="c2" colnum="2" colwidth=".25*"/>
- <colspec colname="c3" colnum="3" colwidth="1*"/>
- <thead>
- <row>
- <entry> Port </entry>
- <entry> Type </entry>
- <entry> Service </entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry> 1100 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.ha.jndi.HANamingService</literal>
- </entry>
- </row>
- <row>
- <entry> 1101 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.ha.jndi.HANamingService</literal>
- </entry>
- </row>
- <row>
- <entry> 1102 </entry>
- <entry> UDP </entry>
- <entry>
- <literal>org.jboss.ha.jndi.HANamingService</literal>
- </entry>
- </row>
- <row>
- <entry> 1161 </entry>
- <entry> UDP </entry>
- <entry>
- <literal>org.jboss.jmx.adaptor.snmp.agent.SnmpAgentService</literal>
- </entry>
- </row>
- <row>
- <entry> 1162 </entry>
- <entry> UDP </entry>
- <entry>
- <literal>org.jboss.jmx.adaptor.snmp.trapd.TrapdService</literal>
- </entry>
- </row>
- <row>
- <entry> 3528 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.invocation.iiop.IIOPInvoker</literal>
- </entry>
- </row>
- <row>
- <entry> 4447 </entry>
- <entry> TCP </entry>
- <entry>
- <literal>org.jboss.invocation.jrmp.server.JRMPInvokerHA</literal>
- </entry>
- </row>
- <row>
- <entry> 45566<footnote>
- <para>
- Plus two additional anonymous UDP ports, one can be set using the <literal>rcv_port</literal>, and the other cannot be set.
- </para>
- </footnote></entry>
- <entry> UDP </entry>
- <entry>
- <literal>org.jboss.ha.framework.server.ClusterPartition</literal>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- <section id="Security_on_JBoss-How_to_Secure_the_JBoss_Server">
- <title>How to Secure the JBoss Server</title>
- <para>
- JBoss comes with several admin access points that need to be secured or removed to prevent unauthorized access to administrative functions in a deployment. This section describes the various admin services and how to secure them.
- </para>
- <section id="How_to_Secure_the_JBoss_Server-The_JMX_Console">
- <title>The JMX Console</title>
- <para>
- The <literal>jmx-console.war</literal> found in the deploy directory provides an html view into the JMX microkernel. As such, it provides access to arbitrary admin type access like shutting down the server, stopping services, deploying new services, etc. It should either be secured like any other web application, or removed.
- </para>
- </section>
- <section id="How_to_Secure_the_JBoss_Server-The_Web_Console">
- <title>The Web Console</title>
- <para>
- The <literal>web-console.war</literal> found in the <literal>deploy/management</literal> directory is another web application view into the JMX microkernel. This uses a combination of an applet and a HTML view and provides the same level of access to admin functionality as the <literal>jmx-console.war</literal>. As such, it should either be secured or removed. The <literal>web-console.war</literal> contains commented out templates for basic security in its <literal>WEB-INF/web.xml</literal> as well as commented out setup for a security domain in <literal>WEB-INF/jboss-web.xml</literal>.
- </para>
- </section>
- <section id="How_to_Secure_the_JBoss_Server-The_HTTP_Invokers">
- <title>The HTTP Invokers</title>
- <para>
- The <literal>http-invoker.sar</literal> found in the deploy directory is a service that provides RMI/HTTP access for EJBs and the JNDI <literal>Naming</literal> service. This includes a servlet that processes posts of marshalled <literal>org.jboss.invocation.Invocation</literal> objects that represent invocations that should be dispatched onto the <literal>MBeanServer</literal>. Effectively this allows access to MBeans that support the detached invoker operation via HTTP since one could figure out how to format an appropriate HTTP post. To security this access point you would need to secure the <literal>JMXInvokerServlet</literal> servlet found in the <literal>http-invoker.sar/invoker.war/WEB-INF/web.xml</literal> descriptor. There is a secure mapping defined for the <literal>/restricted/JMXInvokerServlet</literal> path by default, one would simply have to remove the other paths and configure the <literal>http-invoker</literal> security domain setup in the <literal>http!
-invoker.sar/invoker.war/WEB-INF/jboss-web.xml</literal> descriptor.
- </para>
- </section>
- <section id="How_to_Secure_the_JBoss_Server-The_JMX_Invoker">
- <title>The JMX Invoker</title>
- <para>
- The <literal>jmx-invoker-adaptor-server.sar</literal> is a service that exposes the JMX MBeanServer interface via an RMI compatible interface using the RMI/JRMP detached invoker service. The only way for this service to be secured currently would be to switch the protocol to RMI/HTTP and secure the <literal>http-invoker.sar</literal> as described in the previous section. In the future this service will be deployed as an XMBean with a security interceptor that supports role based access checks.
- </para>
- </section>
- </section>
-</chapter>
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml (from rev 101059, projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/chap-Security_Configuration_And_Architecture.xml)
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml (rev 0)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/chap-Security_Configuration_And_Architecture.xml 2010-02-22 06:09:11 UTC (rev 101228)
@@ -0,0 +1,3659 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+<chapter id="Security_on_JBoss">
+ <title>Security on JBoss</title>
+ <subtitle>J2EE Security Configuration and Architecture</subtitle>
+ <para>
+ Security is a fundamental part of any enterprise application. You need to be able to restrict who is allowed to access your applications and control what operations application users may perform. The J2EE specifications define a simple role-based security model for EJBs and web components. The JBoss component framework that handles security is the JBossSX extension framework. The JBossSX security extension provides support for both the role-based declarative J2EE security model and integration of custom security via a security proxy layer. The default implementation of the declarative security model is based on Java Authentication and Authorization Service (JAAS) login modules and subjects. The security proxy layer allows custom security that cannot be described using the declarative model to be added to an EJB in a way that is independent of the EJB business object. Before getting into the JBoss security implementation details, we will review EJB and servlet specificatio!
n security models, as well as JAAS to establish the foundation for these details.
+ </para>
+ <section id="Security_on_JBoss-J2EE_Declarative_Security_Overview">
+ <title>J2EE Declarative Security Overview</title>
+ <para>
+ The J2EE security model declarative in that you describe the security roles and permissions in a standard XML descriptor rather than embedding security into your business component. This isolates security from business-level code because security tends to be more a function of where the component is deployed than an inherent aspect of the component's business logic. For example, consider an ATM component that is to be used to access a bank account. The security requirements, roles and permissions will vary independently of how you access the bank account, based on what bank is managing the account, where the ATM is located, and so on.
+ </para>
+ <para>
+ Securing a J2EE application is based on the specification of the application security requirements via the standard J2EE deployment descriptors. You secure access to EJBs and web components in an enterprise application by using the <literal>ejb-jar.xml</literal> and <literal>web.xml</literal> deployment descriptors. The following sections look at the purpose and usage of the various security elements.
+ </para>
+ <section id="J2EE_Declarative_Security_Overview-Security_References">
+ <title>Security References</title>
+ <para>
+ Both EJBs and servlets can declare one or more <literal>security-role-ref</literal> elements as shown in <xref linkend="Security_References-The_security_role_ref_element"/>. This element declares that a component is using the <literal>role-name</literal> value as an argument to the <literal>isCallerInRole(String)</literal> method. By using the <literal>isCallerInRole</literal> method, a component can verify whether the caller is in a role that has been declared with a <literal>security-role-ref/role-name</literal> element. The <literal>role-name</literal> element value must link to a <literal>security-role</literal> element through the <literal>role-link</literal> element. The typical use of <literal>isCallerInRole</literal> is to perform a security check that cannot be defined by using the role-based <literal>method-permissions</literal> elements.
+ </para>
+ <figure id="Security_References-The_security_role_ref_element">
+ <title>The security-role-ref element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_security_role_ref.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ <xref linkend="Security_References-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage."/> shows the use of <literal>security-role-ref</literal> in an <literal>ejb-jar.xml</literal>.
+ </para>
+ <example id="Security_References-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage.">
+ <title>An ejb-jar.xml descriptor fragment that illustrates the security-role-ref element usage.</title>
+ <programlisting><!-- A sample ejb-jar.xml fragment -->
+<ejb-jar>
+ <enterprise-beans>
+ <session>
+ <ejb-name>ASessionBean</ejb-name>
+ ...
+ <security-role-ref>
+ <role-name>TheRoleICheck</role-name>
+ <role-link>TheApplicationRole</role-link>
+ </security-role-ref>
+ </session>
+ </enterprise-beans>
+ ...
+</ejb-jar>
+</programlisting>
+ </example>
+ <para>
+ <xref linkend="Security_References-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage."/> shows the use of <literal>security-role-ref</literal> in a <literal>web.xml</literal>.
+ </para>
+ <example id="Security_References-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_ref_element_usage.">
+ <title>An example web.xml descriptor fragment that illustrates the security-role-ref element usage.</title>
+ <programlisting><web-app>
+ <servlet>
+ <servlet-name>AServlet</servlet-name>
+ ...
+ <security-role-ref>
+ <role-name>TheServletRole</role-name>
+ <role-link>TheApplicationRole</role-link>
+ </security-role-ref>
+ </servlet>
+ ...
+</web-app>
+</programlisting>
+ </example>
+ </section>
+ <section id="J2EE_Declarative_Security_Overview-Security_Identity">
+ <title>Security Identity</title>
+ <para>
+ An EJB has the capability to specify what identity an EJB should use when it invokes methods on other components using the <literal>security-identity</literal> element, shown in <xref linkend="Security_Identity-The_security_identity_element"/>
+ </para>
+ <figure id="Security_Identity-The_security_identity_element">
+ <title>The security-identity element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_security_identity.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ The invocation identity can be that of the current caller, or it can be a specific role. The application assembler uses the <literal>security-identity</literal> element with a <literal>use-caller-identity</literal> child element to indicate that the current caller's identity should be propagated as the security identity for method invocations made by the EJB. Propagation of the caller's identity is the default used in the absence of an explicit <literal>security-identity</literal> element declaration.
+ </para>
+ <para>
+ Alternatively, the application assembler can use the <literal>run-as/role-name</literal> child element to specify that a specific security role given by the <literal>role-name</literal> value should be used as the security identity for method invocations made by the EJB. Note that this does not change the caller's identity as seen by the <literal>EJBContext.getCallerPrincipal()</literal> method. Rather, the caller's security roles are set to the single role specified by the <literal>run-as/role-name</literal> element value. One use case for the <literal>run-as</literal> element is to prevent external clients from accessing internal EJBs. You accomplish this by assigning the internal EJB <literal>method-permission</literal> elements that restrict access to a role never assigned to an external client. EJBs that need to use internal EJB are then configured with a <literal>run-as/role-name</literal> equal to the restricted role. The following descriptor fragment t!
hat illustrates <literal>security-identity</literal> element usage.
+ </para>
+ <programlisting><!-- A sample ejb-jar.xml fragment -->
+<ejb-jar>
+ <enterprise-beans>
+ <session>
+ <ejb-name>ASessionBean</ejb-name>
+ <!-- ... -->
+ <security-identity>
+ <use-caller-identity/>
+ </security-identity>
+ </session>
+ <session>
+ <ejb-name>RunAsBean</ejb-name>
+ <!-- ... -->
+ <security-identity>
+ <run-as>
+ <description>A private internal role</description>
+ <role-name>InternalRole</role-name>
+ </run-as>
+ </security-identity>
+ </session>
+ </enterprise-beans>
+ <!-- ... -->
+</ejb-jar>
+</programlisting>
+ <para>
+ When you use <literal>run-as</literal> to assign a specific role to outgoing calls, JBoss associates a principal named <literal>anonymous</literal>. If you want another principal to be associated with the call, you need to associate a <literal>run-as-principal</literal> with the bean in the <literal>jboss.xml</literal> file. The following fragment associates a principal named <literal>internal</literal> with <literal>RunAsBean</literal> from the prior example.
+ </para>
+ <programlisting><session>
+ <ejb-name>RunAsBean</ejb-name>
+ <security-identity>
+ <run-as-principal>internal</run-as-principal>
+ </security-identity>
+</session>
+</programlisting>
+ <para>
+ The <literal>run-as</literal> element is also available in servlet definitions in a <literal>web.xml</literal> file. The following example shows how to assign the role <literal>InternalRole</literal> to a servlet:
+ </para>
+ <programlisting><servlet>
+ <servlet-name>AServlet</servlet-name>
+ <!-- ... -->
+ <run-as>
+ <role-name>InternalRole</role-name>
+ </run-as>
+</servlet>
+</programlisting>
+ <para>
+ Calls from this servlet will be associated with the anonymous <literal>principal</literal>. The <literal>run-as-principal</literal> element is available in the <literal>jboss-web.xml</literal> file to assign a specific principal to go along with the <literal>run-as</literal> role. The following fragment shows how to associate a principal named <literal>internal</literal> to the servlet in the prior example.
+ </para>
+ <programlisting><servlet>
+ <servlet-name>AServlet</servlet-name>
+ <run-as-principal>internal</run-as-principal>
+</servlet>
+</programlisting>
+ </section>
+ <section id="J2EE_Declarative_Security_Overview-Security_roles">
+ <title>Security roles</title>
+ <para>
+ The security role name referenced by either the <literal>security-role-ref</literal> or <literal>security-identity</literal> element needs to map to one of the application's declared roles. An application assembler defines logical security roles by declaring <literal>security-role</literal> elements. The <literal>role-name</literal> value is a logical application role name like Administrator, Architect, SalesManager, etc.
+ </para>
+ <para>
+ The J2EE specifications note that it is important to keep in mind that the security roles in the deployment descriptor are used to define the logical security view of an application. Roles defined in the J2EE deployment descriptors should not be confused with the user groups, users, principals, and other concepts that exist in the target enterprise's operational environment. The deployment descriptor roles are application constructs with application domain-specific names. For example, a banking application might use role names such as BankManager, Teller, or Customer.
+ </para>
+ <figure id="Security_roles-The_security_role_element">
+ <title>The security-role element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_security_role.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ In JBoss, a <literal>security-role</literal> element is only used to map <literal>security-role-ref/role-name</literal> values to the logical role that the component role references. The user's assigned roles are a dynamic function of the application's security manager, as you will see when we discuss the JBossSX implementation details. JBoss does not require the definition of <literal>security-role</literal> elements in order to declare method permissions. However, the specification of <literal>security-role</literal> elements is still a recommended practice to ensure portability across application servers and for deployment descriptor maintenance. <xref linkend="Security_roles-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage."/> shows the usage of the <literal>security-role</literal> in an <literal>ejb-jar.xml</literal> file.
+ </para>
+ <example id="Security_roles-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage.">
+ <title>An ejb-jar.xml descriptor fragment that illustrates the security-role element usage.</title>
+ <programlisting><!-- A sample ejb-jar.xml fragment -->
+<ejb-jar>
+ <!-- ... -->
+ <assembly-descriptor>
+ <security-role>
+ <description>The single application role</description>
+ <role-name>TheApplicationRole</role-name>
+ </security-role>
+ </assembly-descriptor>
+</ejb-jar>
+</programlisting>
+ </example>
+ <para>
+ <xref linkend="Security_roles-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage."/> shows the usage of the <literal>security-role</literal> in an <literal>web.xml</literal> file.
+ </para>
+ <example id="Security_roles-An_example_web.xml_descriptor_fragment_that_illustrates_the_security_role_element_usage.">
+ <title>An example web.xml descriptor fragment that illustrates the security-role element usage.</title>
+ <programlisting><!-- A sample web.xml fragment -->
+<web-app>
+ <!-- ... -->
+ <security-role>
+ <description>The single application role</description>
+ <role-name>TheApplicationRole</role-name>
+ </security-role>
+</web-app>
+</programlisting>
+ </example>
+ </section>
+ <section id="J2EE_Declarative_Security_Overview-EJB_method_permissions">
+ <title>EJB method permissions</title>
+ <para>
+ An application assembler can set the roles that are allowed to invoke an EJB's home and remote interface methods through method-permission element declarations.
+ </para>
+ <figure id="EJB_method_permissions-The_method_permissions_element">
+ <title>The method-permissions element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_method_permission.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ Each <literal>method-permission</literal> element contains one or more role-name child elements that define the logical roles that are allowed to access the EJB methods as identified by method child elements. You can also specify an <literal>unchecked</literal> element instead of the <literal>role-name</literal> element to declare that any authenticated user can access the methods identified by method child elements. In addition, you can declare that no one should have access to a method that has the <literal>exclude-list</literal> element. If an EJB has methods that have not been declared as accessible by a role using a <literal>method-permission</literal> element, the EJB methods default to being excluded from use. This is equivalent to defaulting the methods into the <literal>exclude-list</literal>.
+ </para>
+ <figure id="EJB_method_permissions-The_method_element">
+ <title>The method element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_method.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ There are three supported styles of method element declarations.
+ </para>
+ <para>
+ The first is used for referring to all the home and component interface methods of the named enterprise bean:
+ </para>
+ <programlisting><method>
+ <ejb-name>EJBNAME</ejb-name>
+ <method-name>*</method-name>
+</method>
+</programlisting>
+ <para>
+ The second style is used for referring to a specified method of the home or component interface of the named enterprise bean:
+ </para>
+ <programlisting><method>
+ <ejb-name>EJBNAME</ejb-name>
+ <method-name>METHOD</method-name>
+ </method>
+</programlisting>
+ <para>
+ If there are multiple methods with the same overloaded name, this style refers to all of the overloaded methods.
+ </para>
+ <para>
+ The third style is used to refer to a specified method within a set of methods with an overloaded name:
+ </para>
+ <programlisting><method>
+ <ejb-name>EJBNAME</ejb-name>
+ <method-name>METHOD</method-name>
+ <method-params>
+ <method-param>PARAMETER_1</method-param>
+ <!-- ... -->
+ <method-param>PARAMETER_N</method-param>
+ </method-params>
+</method>
+</programlisting>
+ <para>
+ The method must be defined in the specified enterprise bean's home or remote interface. The method-param element values are the fully qualified name of the corresponding method parameter type. If there are multiple methods with the same overloaded signature, the permission applies to all of the matching overloaded methods.
+ </para>
+ <para>
+ The optional <literal>method-intf</literal> element can be used to differentiate methods with the same name and signature that are defined in both the home and remote interfaces of an enterprise bean.
+ </para>
+ <para>
+ <xref linkend="EJB_method_permissions-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_method_permission_element_usage."/> provides complete examples of the <literal>method-permission</literal> element usage.
+ </para>
+ <example id="EJB_method_permissions-An_ejb_jar.xml_descriptor_fragment_that_illustrates_the_method_permission_element_usage.">
+ <title>An ejb-jar.xml descriptor fragment that illustrates the method-permission element usage.</title>
+ <programlisting><ejb-jar>
+ <assembly-descriptor>
+ <method-permission>
+ <description>The employee and temp-employee roles may access any
+ method of the EmployeeService bean </description>
+ <role-name>employee</role-name>
+ <role-name>temp-employee</role-name>
+ <method>
+ <ejb-name>EmployeeService</ejb-name>
+ <method-name>*</method-name>
+ </method>
+ </method-permission>
+ <method-permission>
+ <description>The employee role may access the findByPrimaryKey,
+ getEmployeeInfo, and the updateEmployeeInfo(String) method of
+ the AardvarkPayroll bean </description>
+ <role-name>employee</role-name>
+ <method>
+ <ejb-name>AardvarkPayroll</ejb-name>
+ <method-name>findByPrimaryKey</method-name>
+ </method>
+ <method>
+ <ejb-name>AardvarkPayroll</ejb-name>
+ <method-name>getEmployeeInfo</method-name>
+ </method>
+ <method>
+ <ejb-name>AardvarkPayroll</ejb-name>
+ <method-name>updateEmployeeInfo</method-name>
+ <method-params>
+ <method-param>java.lang.String</method-param>
+ </method-params>
+ </method>
+ </method-permission>
+ <method-permission>
+ <description>The admin role may access any method of the
+ EmployeeServiceAdmin bean </description>
+ <role-name>admin</role-name>
+ <method>
+ <ejb-name>EmployeeServiceAdmin</ejb-name>
+ <method-name>*</method-name>
+ </method>
+ </method-permission>
+ <method-permission>
+ <description>Any authenticated user may access any method of the
+ EmployeeServiceHelp bean</description>
+ <unchecked/>
+ <method>
+ <ejb-name>EmployeeServiceHelp</ejb-name>
+ <method-name>*</method-name>
+ </method>
+ </method-permission>
+ <exclude-list>
+ <description>No fireTheCTO methods of the EmployeeFiring bean may be
+ used in this deployment</description>
+ <method>
+ <ejb-name>EmployeeFiring</ejb-name>
+ <method-name>fireTheCTO</method-name>
+ </method>
+ </exclude-list>
+ </assembly-descriptor>
+</ejb-jar>
+</programlisting>
+ </example>
+ </section>
+ <section id="J2EE_Declarative_Security_Overview-Web_Content_Security_Constraints">
+ <title>Web Content Security Constraints</title>
+ <para>
+ In a web application, security is defined by the roles that are allowed access to content by a URL pattern that identifies the protected content. This set of information is declared by using the <literal>web.xml</literal><literal>security-constraint</literal> element.
+ </para>
+ <figure id="Web_Content_Security_Constraints-The_security_constraint_element">
+ <title>The security-constraint element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/webapp_security_constraint.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ The content to be secured is declared using one or more <literal>web-resource-collection</literal> elements. Each <literal>web-resource-collection</literal> element contains an optional series of <literal>url-pattern</literal> elements followed by an optional series of <literal>http-method</literal> elements. The <literal>url-pattern</literal> element value specifies a URL pattern against which a request URL must match for the request to correspond to an attempt to access secured content. The <literal>http-method</literal> element value specifies a type of HTTP request to allow.
+ </para>
+ <para>
+ The optional <literal>user-data-constraint</literal> element specifies the requirements for the transport layer of the client to server connection. The requirement may be for content integrity (preventing data tampering in the communication process) or for confidentiality (preventing reading while in transit). The transport-guarantee element value specifies the degree to which communication between the client and server should be protected. Its values are <literal>NONE</literal>, <literal>INTEGRAL</literal>, and <literal>CONFIDENTIAL</literal>. A value of <literal>NONE</literal> means that the application does not require any transport guarantees. A value of <literal>INTEGRAL</literal> means that the application requires the data sent between the client and server to be sent in such a way that it can't be changed in transit. A value of <literal>CONFIDENTIAL</literal> means that the application requires the data to be transmitted in a fashion that prevents other ent!
ities from observing the contents of the transmission. In most cases, the presence of the <literal>INTEGRAL</literal> or <literal>CONFIDENTIAL</literal> flag indicates that the use of SSL is required.
+ </para>
+ <para>
+ The optional <literal>login-config</literal> element is used to configure the authentication method that should be used, the realm name that should be used for rhw application, and the attributes that are needed by the form login mechanism.
+ </para>
+ <figure id="Web_Content_Security_Constraints-The_login_config_element">
+ <title>The login-config element</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/webapp_login_config.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ The <literal>auth-method</literal> child element specifies the authentication mechanism for the web application. As a prerequisite to gaining access to any web resources that are protected by an authorization constraint, a user must have authenticated using the configured mechanism. Legal <literal>auth-method</literal> values are <literal>BASIC</literal>, <literal>DIGEST</literal>, <literal>FORM</literal>, and <literal>CLIENT-CERT</literal>. The <literal>realm-name</literal> child element specifies the realm name to use in HTTP basic and digest authorization. The <literal>form-login-config</literal> child element specifies the log in as well as error pages that should be used in form-based login. If the <literal>auth-method</literal> value is not <literal>FORM</literal>, then <literal>form-login-config</literal> and its child elements are ignored.
+ </para>
+ <para>
+ As an example, the <literal>web.xml</literal> descriptor fragment given in <xref linkend="Web_Content_Security_Constraints-_A_web.xml_descriptor_fragment_which_illustrates_the_use_of_the_security_constraint_and_related_elements."/> indicates that any URL lying under the web application's <literal>/restricted</literal> path requires an <literal>AuthorizedUser</literal> role. There is no required transport guarantee and the authentication method used for obtaining the user identity is BASIC HTTP authentication.
+ </para>
+ <example id="Web_Content_Security_Constraints-_A_web.xml_descriptor_fragment_which_illustrates_the_use_of_the_security_constraint_and_related_elements.">
+ <title> A web.xml descriptor fragment which illustrates the use of the security-constraint and related elements.</title>
+ <programlisting><web-app>
+ <!-- ... -->
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Secure Content</web-resource-name>
+ <url-pattern>/restricted/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>AuthorizedUser</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>NONE</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+ <!-- ... -->
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>The Restricted Zone</realm-name>
+ </login-config>
+ <!-- ... -->
+ <security-role>
+ <description>The role required to access restricted content </description>
+ <role-name>AuthorizedUser</role-name>
+ </security-role>
+</web-app>
+</programlisting>
+ </example>
+ </section>
+ <section id="J2EE_Declarative_Security_Overview-Enabling_Declarative_Security_in_JBoss">
+ <title>Enabling Declarative Security in JBoss</title>
+ <para>
+ The J2EE security elements that have been covered so far describe the security requirements only from the application's perspective. Because J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The J2EE specifications omit these application server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model using JBoss server specific deployment descriptors. The details behind the security configuration are discussed in <xref linkend="Security_on_JBoss-The_JBoss_Security_Model"/>.
+ </para>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-An_Introduction_to_JAAS">
+ <title>An Introduction to JAAS</title>
+ <para>
+ The JBossSX framework is based on the JAAS API. It is important that you understand the basic elements of the JAAS API to understand the implementation details of JBossSX. The following sections provide an introduction to JAAS to prepare you for the JBossSX architecture discussion later in this chapter.
+ </para>
+ <section id="An_Introduction_to_JAAS-What_is_JAAS">
+ <title>What is JAAS?</title>
+ <para>
+ The JAAS 1.0 API consists of a set of Java packages designed for user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with JDK 1.4+. Because the JBossSX framework uses only the authentication capabilities of JAAS to implement the declarative role-based J2EE security model, this introduction focuses on only that topic.
+ </para>
+ <para>
+ JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can be achieved without changing the JBossSX security manager implementation. All that needs to change is the configuration of the authentication stack that JAAS uses.
+ </para>
+ <section id="What_is_JAAS-The_JAAS_Core_Classes">
+ <title>The JAAS Core Classes</title>
+ <para>
+ The JAAS core classes can be broken down into three categories: common, authentication, and authorization. The following list presents only the common and authentication classes because these are the specific classes used to implement the functionality of JBossSX covered in this chapter.
+ </para>
+ <para>
+ The are the common classes:
+ </para>
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>Subject</literal> (<literal>javax.security.auth.Subject</literal>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Principal</literal> (<literal>java.security.Principal</literal>)
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ These are the authentication classes:
+ </para>
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>Callback</literal> (<literal>javax.security.auth.callback.Callback</literal>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>CallbackHandler</literal> (<literal>javax.security.auth.callback.CallbackHandler</literal>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Configuration</literal> (<literal>javax.security.auth.login.Configuration</literal>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LoginContext</literal> (<literal>javax.security.auth.login.LoginContext</literal>)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LoginModule</literal> (<literal>javax.security.auth.spi.LoginModule</literal>)
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section id="The_JAAS_Core_Classes-The_Subject_and_Principal_Classes">
+ <title>The Subject and Principal Classes</title>
+ <para>
+ To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term subject to represent a request's source. The <literal>Subject</literal> class is the central class in JAAS. A <literal>Subject</literal> represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 <literal>java.security.Principal</literal> interface to represent a principal, which is essentially just a typed name.
+ </para>
+ <para>
+ During the authentication process, a subject is populated with associated identities, or principals. A subject may have many principals. For example, a person may have a name principal (John Doe), a social security number principal (123-45-6789), and a username principal (johnd), all of which help distinguish the subject from other subjects. To retrieve the principals associated with a subject, two methods are available:
+ </para>
+ <programlisting>public Set getPrincipals() {...}
+public Set getPrincipals(Class c) {...}
+</programlisting>
+ <para>
+ The first method returns all principals contained in the subject. The second method returns only those principals that are instances of class <literal>c</literal> or one of its subclasses. An empty set is returned if the subject has no matching principals. Note that the <literal>java.security.acl.Group</literal> interface is a subinterface of <literal>java.security.Principal</literal>, so an instance in the principals set may represent a logical grouping of other principals or groups of principals.
+ </para>
+ </section>
+ <section id="The_JAAS_Core_Classes-Authentication_of_a_Subject">
+ <title>Authentication of a Subject</title>
+ <para>
+ Authentication of a subject requires a JAAS login. The login procedure consists of the following steps:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ An application instantiates a <literal>LoginContext</literal> and passes in the name of the login configuration and a <literal>CallbackHandler</literal> to populate the <literal>Callback</literal> objects, as required by the configuration <literal>LoginModule</literal>s.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>LoginContext</literal> consults a <literal>Configuration</literal> to load all the <literal>LoginModules</literal> included in the named login configuration. If no such named configuration exists the <literal>other</literal> configuration is used as a default.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The application invokes the <literal>LoginContext.login</literal> method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The login method invokes all the loaded <literal>LoginModule</literal>s. As each <literal>LoginModule</literal> attempts to authenticate the subject, it invokes the handle method on the associated <literal>CallbackHandler</literal> to obtain the information required for the authentication process. The required information is passed to the handle method in the form of an array of <literal>Callback</literal> objects. Upon success, the <literal>LoginModule</literal>s associate relevant principals and credentials with the subject.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>LoginContext</literal> returns the authentication status to the application. Success is represented by a return from the login method. Failure is represented through a LoginException being thrown by the login method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If authentication succeeds, the application retrieves the authenticated subject using the <literal>LoginContext.getSubject</literal> method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ After the scope of the subject authentication is complete, all principals and related information associated with the subject by the login method can be removed by invoking the <literal>LoginContext.logout</literal> method.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ The <literal>LoginContext</literal> class provides the basic methods for authenticating subjects and offers a way to develop an application that is independent of the underlying authentication technology. The <literal>LoginContext</literal> consults a <literal>Configuration</literal> to determine the authentication services configured for a particular application. <literal>LoginModule</literal> classes represent the authentication services. Therefore, you can plug different login modules into an application without changing the application itself. The following code shows the steps required by an application to authenticate a subject.
+ </para>
+ <programlisting>CallbackHandler handler = new MyHandler();
+LoginContext lc = new LoginContext("some-config", handler);
+
+try {
+ lc.login();
+ Subject subject = lc.getSubject();
+} catch(LoginException e) {
+ System.out.println("authentication failed");
+ e.printStackTrace();
+}
+
+// Perform work as authenticated Subject
+// ...
+
+// Scope of work complete, logout to remove authentication info
+try {
+ lc.logout();
+} catch(LoginException e) {
+ System.out.println("logout failed");
+ e.printStackTrace();
+}
+
+// A sample MyHandler class
+class MyHandler
+ implements CallbackHandler
+{
+ public void handle(Callback[] callbacks) throws
+ IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ NameCallback nc = (NameCallback)callbacks[i];
+ nc.setName(username);
+ } else if (callbacks[i] instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback)callbacks[i];
+ pc.setPassword(password);
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i],
+ "Unrecognized Callback");
+ }
+ }
+ }
+}
+</programlisting>
+ <para>
+ Developers integrate with an authentication technology by creating an implementation of the <literal>LoginModule</literal> interface. This allows an administrator to plug different authentication technologies into an application. You can chain together multiple <literal>LoginModule</literal>s to allow for more than one authentication technology to participate in the authentication process. For example, one <literal>LoginModule</literal> may perform username/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators.
+ </para>
+ <para>
+ The life cycle of a <literal>LoginModule</literal> is driven by the <literal>LoginContext</literal> object against which the client creates and issues the login method. The process consists of two phases. The steps of the process are as follows:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The <literal>LoginContext</literal> creates each configured <literal>LoginModule</literal> using its public no-arg constructor.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Each <literal>LoginModule</literal> is initialized with a call to its initialize method. The <literal>Subject</literal> argument is guaranteed to be non-null. The signature of the initialize method is: <literal>public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The <literal>login</literal> method is called to start the authentication process. For example, a method implementation might prompt the user for a username and password and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices, or simply extract user information from the underlying operating system. The validation of user identity by each <literal>LoginModule</literal> is considered phase 1 of JAAS authentication. The signature of the <literal>login</literal> method is <literal>boolean login() throws LoginException</literal>. A <literal>LoginException</literal> indicates failure. A return value of true indicates that the method succeeded, whereas a return valueof false indicates that the login module should be ignored.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the <literal>LoginContext</literal>'s overall authentication succeeds, <literal>commit</literal> is invoked on each <literal>LoginModule</literal>. If phase 1 succeeds for a <literal>LoginModule</literal>, then the commit method continues with phase 2 and associates the relevant principals, public credentials, and/or private credentials with the subject. If phase 1 fails for a <literal>LoginModule</literal>, then <literal>commit</literal> removes any previously stored authentication state, such as usernames or passwords. The signature of the <literal>commit</literal> method is: <literal>boolean commit() throws LoginException</literal>. Failure to complete the commit phase is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the <literal>LoginContext</literal>'s overall authentication fails, then the <literal>abort</literal> method is invoked on each <literal>LoginModule</literal>. The <literal>abort</literal> method removes or destroys any authentication state created by the login or initialize methods. The signature of the <literal>abort</literal> method is <literal>boolean abort() throws LoginException</literal>. Failure to complete the <literal>abort</literal> phase is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ To remove the authentication state after a successful login, the application invokes <literal>logout</literal> on the <literal>LoginContext</literal>. This in turn results in a <literal>logout</literal> method invocation on each <literal>LoginModule</literal>. The <literal>logout</literal> method removes the principals and credentials originally associated with the subject during the <literal>commit</literal> operation. Credentials should be destroyed upon removal. The signature of the <literal>logout</literal> method is: <literal>boolean logout() throws LoginException</literal>. Failure to complete the logout process is indicated by throwing a <literal>LoginException</literal>. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ When a <literal>LoginModule</literal> must communicate with the user to obtain authentication information, it uses a <literal>CallbackHandler</literal> object. Applications implement the <literal>CallbackHandler</literal> interface and pass it to the LoginContext, which forwards it directly to the underlying login modules. Login modules use the <literal>CallbackHandler</literal> both to gather input from users, such as a password or smart card PIN, and to supply information to users, such as status information. By allowing the application to specify the <literal>CallbackHandler</literal>, underlying <literal>LoginModule</literal>s remain independent from the different ways applications interact with users. For example, a <literal>CallbackHandler</literal>'s implementation for a GUI application might display a window to solicit user input. On the other hand, a <literal>callbackhandler</literal>'s implementation for a non-GUI environment, such as an applicatio!
n server, might simply obtain credential information by using an application server API. The <literal>callbackhandler</literal> interface has one method to implement:
+ </para>
+ <programlisting>void handle(Callback[] callbacks)
+ throws java.io.IOException,
+ UnsupportedCallbackException;
+</programlisting>
+ <para>
+ The <literal>Callback</literal> interface is the last authentication class we will look at. This is a tagging interface for which several default implementations are provided, including the <literal>NameCallback</literal> and <literal>PasswordCallback</literal> used in an earlier example. A <literal>LoginModule</literal> uses a <literal>Callback</literal> to request information required by the authentication mechanism. <literal>LoginModule</literal>s pass an array of <literal>Callback</literal>s directly to the <literal>CallbackHandler.handle</literal> method during the authentication's login phase. If a <literal>callbackhandler</literal> does not understand how to use a <literal>Callback</literal> object passed into the handle method, it throws an <literal>UnsupportedCallbackException</literal> to abort the login call.
+ </para>
+ </section>
+ </section>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-The_JBoss_Security_Model">
+ <title>The JBoss Security Model</title>
+ <para>
+ Similar to the rest of the JBoss architecture, security at the lowest level is defined as a set of interfaces for which alternate implementations may be provided. Three basic interfaces define the JBoss server security layer: <literal>org.jboss.security.AuthenticationManager</literal>, <literal>org.jboss.security.RealmMapping</literal>, and <literal>org.jboss.security.SecurityProxy</literal>. <xref linkend="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements."/> shows a class diagram of the security interfaces and their relationship to the EJB container architecture.
+ </para>
+ <figure id="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements.">
+ <title>The key security model interfaces and their relationship to the JBoss server EJB container elements.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-6.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ The light blue classes represent the security interfaces while the yellow classes represent the EJB container layer. The two interfaces required for the implementation of the J2EE security model are <literal>org.jboss.security.AuthenticationManager</literal> and <literal>org.jboss.security.RealmMapping</literal>. The roles of the security interfaces presented in <xref linkend="The_JBoss_Security_Model-The_key_security_model_interfaces_and_their_relationship_to_the_JBoss_server_EJB_container_elements."/> are summarized in the following list.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><classname>AuthenticationManager</classname>: This interface is responsible for validating credentials associated with principals. Principals are identities, such as usernames, employee numbers, and social security numbers. Credentials are proof of the identity, such as passwords, session keys, and digital signatures. The <literal>isValid</literal> method is invoked to determine whether a user identity and associated credentials as known in the operational environment are valid proof of the user's identity.
+ </para>
+ </listitem>
+ <listitem>
+ <para><classname>RealmMapping</classname>: This interface is responsible for principal mapping and role mapping. The <literal>getPrincipal</literal> method takes a user identity as known in the operational environment and returns the application domain identity. The <literal>doesUserHaveRole</literal> method validates that the user identity in the operation environment has been assigned the indicated role from the application domain.
+ </para>
+ </listitem>
+ <listitem>
+ <para><classname>SecurityProxy</classname>: This interface describes the requirements for a custom <literal>SecurityProxyInterceptor</literal> plugin. A <literal>SecurityProxy</literal> allows for the externalization of custom security checks on a per-method basis for both the EJB home and remote interface methods.
+ </para>
+ </listitem>
+ <listitem>
+ <para><classname>SubjectSecurityManager</classname>: This is a subinterface of <literal>AuthenticationManager</literal> that adds accessor methods for obtaining the security domain name of the security manager and the current thread's authenticated <literal>Subject</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para><classname>SecurityDomain</classname>: This is an extension of the <literal>AuthenticationManager</literal>, <literal>RealmMapping</literal>, and <literal>SubjectSecurityManager</literal> interfaces. <classname>SecurityDomain</classname> is the recommended way to implement security in components, because of the advantages the JAAS Subject offers, and the increased support offered to to ASP-style application and resource deployments. A <literal>java.security.KeyStore</literal>, and the JSSE <literal>com.sun.net.ssl.KeyManagerFactory</literal> and <literal>com.sun.net.ssl.TrustManagerFactory</literal> interfaces are included in the class.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Note that the <literal>AuthenticationManager</literal>, <literal>RealmMapping</literal> and <literal>SecurityProxy</literal> interfaces have no association to JAAS related classes. Although the JBossSX framework is heavily dependent on JAAS, the basic security interfaces required for implementation of the J2EE security model are not. The JBossSX framework is simply an implementation of the basic security plug-in interfaces that are based on JAAS. </para>
+ <para>The component diagram presented in <xref linkend="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer."/> illustrates this fact. The implication of this plug-in architecture is that you are free to replace the JAAS-based JBossSX implementation classes with your own custom security manager implementation that does not make use of JAAS, if you so desire. You'll see how to do this when you look at the JBossSX MBeans available for the configuration of JBossSX in <xref linkend="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer."/>.
+ </para>
+ <figure id="The_JBoss_Security_Model-The_relationship_between_the_JBossSX_framework_implementation_classes_and_the_JBoss_server_EJB_container_layer.">
+ <title>The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-7.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <section id="The_JBoss_Security_Model-Enabling_Declarative_Security_in_JBoss_Revisited">
+ <title>Enabling Declarative Security in JBoss Revisited</title>
+ <para>
+ Earlier in this chapter, the discussion of the J2EE standard security model ended with a requirement for the use of JBoss server-specific deployment descriptor to enable security. The details of this configuration are presented here. <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_security_element_subsets_of_the_JBoss_server_jboss.xml_and_jboss_web.xml_deployment_descriptors."/> shows the JBoss-specific EJB and web application deployment descriptor's security-related elements.
+ </para>
+ <figure id="Enabling_Declarative_Security_in_JBoss_Revisited-The_security_element_subsets_of_the_JBoss_server_jboss.xml_and_jboss_web.xml_deployment_descriptors.">
+ <title>The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-8.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>The value of a <literal>security-domain</literal> element specifies the JNDI name of the security manager interface implementation that JBoss uses for the EJB and web containers. This is an object that implements both of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces. When specified as a top-level element it defines what security domain in effect for all EJBs in the deployment unit. This is the typical usage because mixing security managers within a deployment unit complicates inter-component operation and administration.
+ </para>
+ <para>To specify the security domain for an individual EJB, you specify the <literal>security-domain</literal> at the container configuration level. This will override any top-level security-domain element.
+ </para>
+ <para>The <literal>unauthenticated-principal</literal> element specifies the name to use for the <literal>Principal</literal> object returned by the <literal>EJBContext.getUserPrincipal</literal> method when an unauthenticated user invokes an EJB. Note that this conveys no special permissions to an unauthenticated caller. Its primary purpose is to allow unsecured servlets and JSP pages to invoke unsecured EJBs and allow the target EJB to obtain a non-null <literal>Principal</literal> for the caller using the <literal>getUserPrincipal</literal> method. This is a J2EE specification requirement.
+ </para>
+ <para>The <literal>security-proxy</literal> element identifies a custom security proxy implementation that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. This may be an implementation of the <literal>org.jboss.security.SecurityProxy</literal> interface, or just an object that implements methods in the home, remote, local home or local interfaces of the EJB to secure without implementing any common interface. If the given class does not implement the <literal>SecurityProxy</literal> interface, the instance must be wrapped in a <literal>SecurityProxy</literal> implementation that delegates the method invocations to the object. The <literal>org.jboss.security.SubjectSecurityProxy</literal> is an example <literal>SecurityProxy</literal> implementation used by the default JBossSX installation.
+ </para>
+ <para>
+ Take a look at a simple example of a custom <literal>SecurityProxy</literal> in the context of a trivial stateless session bean. The custom <literal>SecurityProxy</literal> validates that no one invokes the bean's <literal>echo</literal> method with a four-letter word as its argument. This is a check that is not possible with role-based security; you cannot define a <literal>FourLetterEchoInvoker</literal> role because the security context is the method argument, not a property of the caller. The code for the custom <literal>SecurityProxy</literal> is given in <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_example_1_custom_EchoSecurityProxy_implementation_that_enforces_the_echo_argument_based_security_constraint."/>, and the full source code is available in the <literal>src/main/org/jboss/book/security/ex1</literal> directory of the book examples.
+ </para>
+ <example id="Enabling_Declarative_Security_in_JBoss_Revisited-The_example_1_custom_EchoSecurityProxy_implementation_that_enforces_the_echo_argument_based_security_constraint.">
+ <title>The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint.</title>
+ <programlisting>package org.jboss.book.security.ex1;
+
+import java.lang.reflect.Method;
+import javax.ejb.EJBContext;
+
+import org.apache.log4j.Category;
+
+import org.jboss.security.SecurityProxy;
+
+/** A simple example of a custom SecurityProxy implementation
+ * that demonstrates method argument based security checks.
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 1.4 $
+ */
+public class EchoSecurityProxy implements SecurityProxy
+{
+ Category log = Category.getInstance(EchoSecurityProxy.class);
+ Method echo;
+
+ public void init(Class beanHome, Class beanRemote,
+ Object securityMgr)
+ throws InstantiationException
+ {
+ log.debug("init, beanHome="+beanHome
+ + ", beanRemote="+beanRemote
+ + ", securityMgr="+securityMgr);
+ // Get the echo method for equality testing in invoke
+ try {
+ Class[] params = {String.class};
+ echo = beanRemote.getDeclaredMethod("echo", params);
+ } catch(Exception e) {
+ String msg = "Failed to finde an echo(String) method";
+ log.error(msg, e);
+ throw new InstantiationException(msg);
+ }
+ }
+
+ public void setEJBContext(EJBContext ctx)
+ {
+ log.debug("setEJBContext, ctx="+ctx);
+ }
+
+ public void invokeHome(Method m, Object[] args)
+ throws SecurityException
+ {
+ // We don't validate access to home methods
+ }
+
+ public void invoke(Method m, Object[] args, Object bean)
+ throws SecurityException
+ {
+ log.debug("invoke, m="+m);
+ // Check for the echo method
+ if (m.equals(echo)) {
+ // Validate that the msg arg is not 4 letter word
+ String arg = (String) args[0];
+ if (arg == null || arg.length() == 4)
+ throw new SecurityException("No 4 letter words");
+ }
+ // We are not responsible for doing the invoke
+ }
+}
+
+</programlisting>
+ </example>
+ <para>
+ The <literal>EchoSecurityProxy</literal> checks that the method to be invoked on the bean instance corresponds to the <literal>echo(String)</literal> method loaded the init method. If there is a match, the method argument is obtained and its length compared against 4 or null. Either case results in a <literal>SecurityException</literal> being thrown. Certainly this is a contrived example, but only in its application. It is a common requirement that applications must perform security checks based on the value of method arguments. The point of the example is to demonstrate how custom security beyond the scope of the standard declarative security model can be introduced independent of the bean implementation. This allows the specification and coding of the security requirements to be delegated to security experts. Since the security proxy layer can be done independent of the bean implementation, security can be changed to match the deployment environment requirements.
+ </para>
+ <para>
+ The associated <literal>jboss.xml</literal> descriptor that installs the <literal>EchoSecurityProxy</literal> as the custom proxy for the <literal>EchoBean</literal> is given in <xref linkend="Enabling_Declarative_Security_in_JBoss_Revisited-The_jboss.xml_descriptor_which_configures_the_EchoSecurityProxy_as_the_custom_security_proxy_for_the_EchoBean."/>.
+ </para>
+ <example id="Enabling_Declarative_Security_in_JBoss_Revisited-The_jboss.xml_descriptor_which_configures_the_EchoSecurityProxy_as_the_custom_security_proxy_for_the_EchoBean.">
+ <title>The jboss.xml descriptor, which configures the EchoSecurityProxy as the custom security proxy for the EchoBean.</title>
+ <programlisting><jboss>
+ <security-domain>java:/jaas/other</security-domain>
+
+ <enterprise-beans>
+ <session>
+ <ejb-name>EchoBean</ejb-name>
+ <security-proxy>org.jboss.book.security.ex1.EchoSecurityProxy</security-proxy>
+ </session>
+ </enterprise-beans>
+</jboss>
+</programlisting>
+ </example>
+ <para>
+ Now test the custom proxy by running a client that attempts to invoke the <literal>EchoBean.echo</literal> method with the arguments <literal>Hello</literal> and <literal>Four</literal> as illustrated in this fragment:
+ </para>
+ <programlisting>public class ExClient
+{
+ public static void main(String args[])
+ throws Exception
+ {
+ Logger log = Logger.getLogger("ExClient");
+ log.info("Looking up EchoBean");
+
+ InitialContext iniCtx = new InitialContext();
+ Object ref = iniCtx.lookup("EchoBean");
+ EchoHome home = (EchoHome) ref;
+ Echo echo = home.create();
+
+ log.info("Created Echo");
+ log.info("Echo.echo('Hello') = "+echo.echo("Hello"));
+ log.info("Echo.echo('Four') = "+echo.echo("Four"));
+ }
+}
+</programlisting>
+ <para>
+ The first call should succeed, while the second should fail due to the fact that <literal>Four</literal> is a four-letter word. Run the client as follows using Ant from the examples directory:
+ </para>
+ <programlisting>[examples]$ ant -Dchap=security -Dex=1 run-example
+run-example1:
+...
+ [echo] Waiting for 5 seconds for deploy...
+ [java] [INFO,ExClient] Looking up EchoBean
+ [java] [INFO,ExClient] Created Echo
+ [java] [INFO,ExClient] Echo.echo('Hello') = Hello
+ [java] Exception in thread "main" java.rmi.AccessException: SecurityException; nested exception is:
+ [java] java.lang.SecurityException: No 4 letter words
+...
+ [java] Caused by: java.lang.SecurityException: No 4 letter words
+...
+</programlisting>
+ <para>
+ The result is that the <literal>echo('Hello')</literal> method call succeeds as expected and the <literal>echo('Four')</literal> method call results in a rather messy looking exception, which is also expected. The above output has been truncated to fit in the book. The key part to the exception is that the <literal>SecurityException("No 4 letter words")</literal> generated by the <literal>EchoSecurityProxy</literal> was thrown to abort the attempted method invocation as desired.
+ </para>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-The_JBoss_Security_Extension_Architecture">
+ <title>The JBoss Security Extension Architecture</title>
+ <para>
+ The preceding discussion of the general JBoss security layer has stated that the JBossSX security extension framework is an implementation of the security layer interfaces. This is the primary purpose of the JBossSX framework. The details of the implementation are interesting in that it offers a great deal of customization for integration into existing security infrastructures. A security infrastructure can be anything from a database or LDAP server to a sophisticated security software suite. The integration flexibility is achieved using the pluggable authentication model available in the JAAS framework.
+ </para>
+ <para>
+ The heart of the JBossSX framework is <literal>org.jboss.security.plugins.JaasSecurityManager</literal>. This is the default implementation of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces. <xref linkend="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager."/> shows how the <literal>JaasSecurityManager</literal> integrates into the EJB and web container layers based on the <literal>security-domain</literal> element of the corresponding component deployment descriptor.
+ </para>
+ <figure id="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager.">
+ <title>The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-9.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ <xref linkend="The_JBoss_Security_Extension_Architecture-The_relationship_between_the_security_domain_component_deployment_descriptor_value_the_component_container_and_the_JaasSecurityManager."/> depicts an enterprise application that contains both EJBs and web content secured under the security domain <literal>jwdomain</literal>. The EJB and web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the <literal>security-domain</literal> element value in the <literal>jboss.xml</literal> and <literal>jboss-web.xml</literal> descriptors is used to obtain the security manager instance associated with the container. The security interceptor then uses the security manager to perform its role. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container.
+ </para>
+ <para>
+ The JBossSX <literal>JaasSecurityManager</literal> implementation performs security checks based on the information associated with the <literal>Subject</literal> instance that results from executing the JAAS login modules configured under the name matching the <literal>security-domain</literal> element value. We will drill into the <literal>JaasSecurityManager</literal> implementation and its use of JAAS in the following section.
+ </para>
+ <section id="The_JBoss_Security_Extension_Architecture-How_the_JaasSecurityManager_Uses_JAAS">
+ <title>How the JaasSecurityManager Uses JAAS</title>
+ <para>
+ The <literal>JaasSecurityManager</literal> uses the JAAS packages to implement the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interface behavior. In particular, its behavior derives from the execution of the login module instances that are configured under the name that matches the security domain to which the <literal>JaasSecurityManager</literal> has been assigned. The login modules implement the security domain's principal authentication and role-mapping behavior. Thus, you can use the <literal>JaasSecurityManager</literal> across different security domains simply by plugging in different login module configurations for the domains.
+ </para>
+ <para>
+ To illustrate the details of the <literal>JaasSecurityManager</literal>'s usage of the JAAS authentication process, you will walk through a client invocation of an EJB home method invocation. The prerequisite setting is that the EJB has been deployed in the JBoss server and its home interface methods have been secured using <literal>method-permission</literal> elements in the <literal>ejb-jar.xml</literal> descriptor, and it has been assigned a security domain named <literal>jwdomain</literal> using the <literal>jboss.xml</literal> descriptor <literal>security-domain</literal> element.
+ </para>
+ <figure id="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation.">
+ <title>An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/authsteps.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ <xref linkend="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation."/> provides a view of the client to server communication we will discuss. The numbered steps shown are:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ The client first has to perform a JAAS login to establish the principal and credentials for authentication, and this is labeled <emphasis>Client Side Login</emphasis> in the figure. This is how clients establish their login identities in JBoss. Support for presenting the login information via JNDI <literal>InitialContext</literal> properties is provided via an alternate configuration. A JAAS login entails creating a <literal>LoginContext</literal> instance and passing the name of the configuration to use. The configuration name is <literal>other</literal>. This one-time login associates the login principal and credentials with all subsequent EJB method invocations. Note that the process might not authenticate the user. The nature of the client-side login depends on the login module configuration that the client uses. In this example, the <literal>other</literal> client-side login configuration entry is set up to use the <literal>ClientLoginModule</literal> module (an !
<literal>org.jboss.security.ClientLoginModule</literal>). This is the default client side module that simply binds the username and password to the JBoss EJB invocation layer for later authentication on the server. The identity of the client is not authenticated on the client.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Later, the client obtains the EJB home interface and attempts to create a bean. This event is labeled as <emphasis>Home Method Invocation</emphasis>. This results in a home interface method invocation being sent to the JBoss server. The invocation includes the method arguments passed by the client along with the user identity and credentials from the client-side JAAS login performed in step 1.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ On the server side, the security interceptor first requires authentication of the user invoking the call, which, as on the client side, involves a JAAS login.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The security domain under which the EJB is secured determines the choice of login modules. The security domain name is used as the login configuration entry name passed to the <literal>LoginContext</literal> constructor. The EJB security domain is <literal>jwdomain</literal>. If the JAAS login authenticates the user, a JAAS <literal>Subject</literal> is created that contains the following in its <literal>PrincipalsSet</literal>:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A <literal>java.security.Principal</literal> that corresponds to the client identity as known in the deployment security environment.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A <literal>java.security.acl.Group</literal> named <literal>Roles</literal> that contains the role names from the application domain to which the user has been assigned. <literal>org.jboss.security.SimplePrincipal</literal> objects are used to represent the role names; <literal>SimplePrincipal</literal> is a simple string-based implementation of <literal>Principal</literal>. These roles are used to validate the roles assigned to methods in <literal>ejb-jar.xml</literal> and the <literal>EJBContext.isCallerInRole(String)</literal> method implementation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ An optional <literal>java.security.acl.Group</literal> named <literal>CallerPrincipal</literal>, which contains a single <literal>org.jboss.security.SimplePrincipal</literal> that corresponds to the identity of the application domain's caller. The <literal>CallerPrincipal</literal> sole group member will be the value returned by the <literal>EJBContext.getCallerPrincipal()</literal> method. The purpose of this mapping is to allow a <literal>Principal</literal> as known in the operational security environment to map to a <literal>Principal</literal> with a name known to the application. In the absence of a <literal>CallerPrincipal</literal> mapping the deployment security environment principal is used as the <literal>getCallerPrincipal</literal> method value. That is, the operational principal is the same as the application domain principal.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>
+ The final step of the security interceptor check is to verify that the authenticated user has permission to invoke the requested method This is labeled as <emphasis>Server Side Authorization</emphasis> in <xref linkend="How_the_JaasSecurityManager_Uses_JAAS-An_illustration_of_the_steps_involved_in_the_authentication_and_authorization_of_a_secured_EJB_home_method_invocation."/>. Performing the authorization this entails the following steps:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Obtain the names of the roles allowed to access the EJB method from the EJB container. The role names are determined by <literal>ejb-jar.xml</literal> descriptor role-name elements of all <literal>method-permission</literal> elements containing the invoked method.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If no roles have been assigned, or the method is specified in an <literal>exclude-list</literal> element, then access to the method is denied. Otherwise, the <literal>doesUserHaveRole</literal> method is invoked on the security manager by the security interceptor to see if the caller has one of the assigned role names. This method iterates through the role names and checks if the authenticated user's Subject <literal>Roles</literal> group contains a <literal>SimplePrincipal</literal> with the assigned role name. Access is allowed if any role name is a member of the <literal>Roles</literal> group. Access is denied if none of the role names are members.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the EJB was configured with a custom security proxy, the method invocation is delegated to it. If the security proxy wants to deny access to the caller, it will throw a <literal>java.lang.SecurityException</literal>. If no <literal>SecurityException</literal> is thrown, access to the EJB method is allowed and the method invocation passes to the next container interceptor. Note that the <literal>SecurityProxyInterceptor</literal> handles this check and this interceptor is not shown.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </orderedlist>
+ <para>
+ Every secured EJB method invocation, or secured web content access, requires the authentication and authorization of the caller because security information is handled as a stateless attribute of the request that must be presented and validated on each request. This can be an expensive operation if the JAAS login involves client-to-server communication. Because of this, the <literal>JaasSecurityManager</literal> supports the notion of an authentication cache that is used to store principal and credential information from previous successful logins. You can specify the authentication cache instance to use as part of the <literal>JaasSecurityManager</literal> configuration as you will see when the associated MBean service is discussed in following section. In the absence of any user-defined cache, a default cache that maintains credential information for a configurable period of time is used.
+ </para>
+ </section>
+ <section id="The_JBoss_Security_Extension_Architecture-The_JaasSecurityManagerService_MBean">
+ <title>The JaasSecurityManagerService MBean</title>
+ <para>
+ The <literal>JaasSecurityManagerService</literal> MBean service manages security managers. Although its name begins with <emphasis>Jaas</emphasis>, the security managers it handles need not use JAAS in their implementation. The name arose from the fact that the default security manager implementation is the <literal>JaasSecurityManager</literal>. The primary role of the <literal>JaasSecurityManagerService</literal> is to externalize the security manager implementation. You can change the security manager implementation by providing an alternate implementation of the <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interfaces.
+ </para>
+ <para>
+ The second fundamental role of the <literal>JaasSecurityManagerService</literal> is to provide a JNDI <literal>javax.naming.spi.ObjectFactory</literal> implementation to allow for simple code-free management of the JNDI name to security manager implementation mapping. It has been mentioned that security is enabled by specifying the JNDI name of the security manager implementation via the <literal>security-domain</literal> deployment descriptor element. When you specify a JNDI name, there has to be an object-binding there to use. To simplify the setup of the JNDI name to security manager bindings, the <literal>JaasSecurityManagerService</literal> manages the association of security manager instances to names by binding a next naming system reference with itself as the JNDI ObjectFactory under the name <literal>java:/jaas</literal>. This allows one to use a naming convention of the form <literal>java:/jaas/XYZ</literal> as the value for the <literal>security-domain</liter!
al> element, and the security manager instance for the <literal>XYZ</literal> security domain will be created as needed for you. The security manager for the domain <literal>XYZ</literal> is created on the first lookup against the <literal>java:/jaas/XYZ</literal> binding by creating an instance of the class specified by the <literal>SecurityManagerClassName</literal> attribute using a constructor that takes the name of the security domain. For example, consider the following container security configuration snippet:
+ </para>
+ <programlisting><jboss>
+ <!-- Configure all containers to be secured under the "hades" security domain -->
+ <security-domain>java:/jaas/hades</security-domain>
+ <!-- ... -->
+</jboss>
+</programlisting>
+ <para>
+ Any lookup of the name <literal>java:/jaas/hades</literal> will return a security manager instance that has been associated with the security domain named <literal>hades</literal>. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the <literal>JaasSecurityManagerService</literal><literal>SecurityManagerClassName</literal> attribute.
+ </para>
+ <para>
+ The <literal>JaasSecurityManagerService</literal> MBean is configured by default for use in the standard JBoss distribution, and you can often use the default configuration as is. The configurable attributes of the <literal>JaasSecurityManagerService</literal> include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">SecurityManagerClassName</emphasis>: The name of the class that provides the security manager implementation. The implementation must support both the <literal>org.jboss.security.AuthenticationManager</literal> and <literal>org.jboss.security.RealmMapping</literal> interfaces. If not specified this defaults to the JAAS-based <literal>org.jboss.security.plugins.JaasSecurityManager</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">CallbackHandlerClassName</emphasis>: The name of the class that provides the <literal>javax.security.auth.callback.CallbackHandler</literal> implementation used by the <literal>JaasSecurityManager</literal>. You can override the handler used by the <literal>JaasSecurityManager</literal> if the default implementation (<literal>org.jboss.security.auth.callback.SecurityAssociationHandler</literal>) does not meet your needs. This is a rather deep configuration that generally should not be set unless you know what you are doing.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">SecurityProxyFactoryClassName</emphasis>: The name of the class that provides the <literal>org.jboss.security.SecurityProxyFactory</literal> implementation. If not specified this defaults to <literal>org.jboss.security.SubjectSecurityProxyFactory</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">AuthenticationCacheJndiName</emphasis>: Specifies the location of the security credential cache policy. This is first treated as an <literal>ObjectFactory</literal> location capable of returning <literal>CachePolicy</literal> instances on a per-security-domain basis. This is done by appending the name of the security domain to this name when looking up the <literal>CachePolicy</literal> for a domain. If this fails, the location is treated as a single <literal>CachePolicy</literal> for all security domains. As a default, a timed cache policy is used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">DefaultCacheTimeout</emphasis>: Specifies the default timed cache policy timeout in seconds. The default value is 1800 seconds (30 minutes). The value you use for the timeout is a tradeoff between frequent authentication operations and how long credential information may be out of sync with respect to the security information store. If you want to disable caching of security credentials, set this to 0 to force authentication to occur every time. This has no affect if the <literal>AuthenticationCacheJndiName</literal> has been changed from the default value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">DefaultCacheResolution</emphasis>: Specifies the default timed cache policy resolution in seconds. This controls the interval at which the cache current timestamp is updated and should be less than the <literal>DefaultCacheTimeout</literal> in order for the timeout to be meaningful. The default resolution is 60 seconds(1 minute). This has no affect if the <literal>AuthenticationCacheJndiName</literal> has been changed from the default value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">DefaultUnauthenticatedPrincipal</emphasis>: Specifies the principal to use for unauthenticated users. This setting makes it possible to set default permissions for users who have not been authenticated.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>JaasSecurityManagerService</literal> also supports a number of useful operations. These include flushing any security domain authentication cache at runtime, getting the list of active users in a security domain authentication cache, and any of the security manager interface methods.
+ </para>
+ <para>
+ Flushing a security domain authentication cache can be used to drop all cached credentials when the underlying store has been updated and you want the store state to be used immediately. The MBean operation signature is: <literal>public void flushAuthenticationCache(String securityDomain)</literal>.
+ </para>
+ <para>
+ This can be invoked programmatically using the following code snippet:
+ </para>
+ <programlisting>MBeanServer server = ...;
+String jaasMgrName = "jboss.security:service=JaasSecurityManager";
+ObjectName jaasMgr = new ObjectName(jaasMgrName);
+Object[] params = {domainName};
+String[] signature = {"java.lang.String"};
+server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);
+</programlisting>
+ <para>
+ Getting the list of active users provides a snapshot of the <literal>Principals</literal> keys in a security domain authentication cache that are not expired. The MBean operation signature is: <literal>public List getAuthenticationCachePrincipals(String securityDomain)</literal>.
+ </para>
+ <para>
+ This can be invoked programmatically using the following code snippet:
+ </para>
+ <programlisting>MBeanServer server = ...;
+String jaasMgrName = "jboss.security:service=JaasSecurityManager";
+ObjectName jaasMgr = new ObjectName(jaasMgrName);
+Object[] params = {domainName};
+String[] signature = {"java.lang.String"};
+List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals",
+ params, signature);
+</programlisting>
+ <para>
+ The security manager has a few additional access methods.
+ </para>
+ <programlisting>public boolean isValid(String securityDomain, Principal principal, Object credential);
+public Principal getPrincipal(String securityDomain, Principal principal);
+public boolean doesUserHaveRole(String securityDomain, Principal principal,
+ Object credential, Set roles);
+public Set getUserRoles(String securityDomain, Principal principal, Object credential);
+</programlisting>
+ <para>
+ They provide access to the corresponding <literal>AuthenticationManager</literal> and <literal>RealmMapping</literal> interface method of the associated security domain named by the <literal>securityDomain</literal> argument.
+ </para>
+ </section>
+ <section id="The_JBoss_Security_Extension_Architecture-The_JaasSecurityDomain_MBean">
+ <title>The JaasSecurityDomain MBean</title>
+ <para>
+ The <literal>org.jboss.security.plugins.JaasSecurityDomain</literal> is an extension of <literal>JaasSecurityManager</literal> that adds the notion of a <literal>KeyStore</literal>, a JSSE <literal>KeyManagerFactory</literal> and a <literal>TrustManagerFactory</literal> for supporting SSL and other cryptographic use cases. The additional configurable attributes of the <literal>JaasSecurityDomain</literal> include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">KeyStoreType</emphasis>: The type of the <literal>KeyStore</literal> implementation. This is the type argument passed to the <literal>java.security.KeyStore.getInstance(String type)</literal> factory method. The default is <literal>JKS</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">KeyStoreURL</emphasis>: A URL to the location of the <literal>KeyStore</literal> database. This is used to obtain an <literal>InputStream</literal> to initialize the <literal>KeyStore</literal>. If the string is not a value URL, it is treated as a file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">KeyStorePass</emphasis>: The password associated with the <literal>KeyStore</literal> database contents. The <literal>KeyStorePass</literal> is also used in combination with the <literal>Salt</literal> and <literal>IterationCount</literal> attributes to create a PBE secret key used with the encode/decode operations. The <literal>KeyStorePass</literal> attribute value format is one of the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The plaintext password for the <literal>KeyStore</literal> The <literal>toCharArray()</literal> value of the string is used without any manipulation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A command to execute to obtain the plaintext password. The format is <literal>{EXT}...</literal> where the <literal>...</literal> is the exact command line that will be passed to the <literal>Runtime.exec(String)</literal> method to execute a platform-specific command. The first line of the command output is used as the password.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A class to create to obtain the plaintext password. The format is <literal>{CLASS}classname[:ctorarg]</literal> where the <literal>[:ctorarg]</literal> is an optional string that will be passed to the constructor when instantiating the <literal>classname</literal>. The password is obtained from classname by invoking a <literal>toCharArray()</literal> method if found, otherwise, the <literal>toString()</literal> method is used.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">Salt</emphasis>: The <literal>PBEParameterSpec</literal> salt value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">IterationCount</emphasis>: The <literal>PBEParameterSpec</literal> iteration count value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">TrustStoreType</emphasis>: The type of the <literal>TrustStore</literal> implementation. This is the type argument passed to the <literal>java.security.KeyStore.getInstance(String type)</literal> factory method. The default is <literal>JKS</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">TrustStoreURL</emphasis>: A URL to the location of the <literal>TrustStore</literal> database. This is used to obtain an <literal>InputStream</literal> to initialize the <literal>KeyStore</literal>. If the string is not a value URL, it is treated as a file.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">TrustStorePass</emphasis>: The password associated with the trust store database contents. The <literal>TrustStorePass</literal> is a simple password and doesn't have the same configuration options as the <literal>KeyStorePass</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ManagerServiceName</emphasis>: Sets the JMX object name string of the security manager service MBean. This is used to register the defaults to register the <literal>JaasSecurityDomain</literal> as a the security manager under <literal>java:/jaas/<domain></literal> where <literal><domain></literal> is the name passed to the MBean constructor. The name defaults to <literal>jboss.security:service=JaasSecurityManager</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-Defining_Security_Domains">
+ <title>Configuring Security Domains</title>
+ <para>The standard way of configuring security domains for authentication and authorization in JBoss is to use the XML login configuration file. The login configuration policy defines a set of named security domains that each define a stack of login modules that will be called upon to authenticate and authorize users.
+ </para>
+ <para>
+ The XML configuration file conforms to the DTD given by <xref linkend="Defining_Security_Domains-The_XMLLoginConfig_DTD"/>. This DTD can be found in <literal>docs/dtd/security_config.dtd</literal>.
+ </para>
+ <figure id="Defining_Security_Domains-The_XMLLoginConfig_DTD">
+ <title>The XMLLoginConfig DTD</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/security_config_policy.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/security_config_login_module.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ The following example shows a simple configuration named jmx-console that is backed by a single login module. The login module is configured by a simple set of name/value configuration pairs that have meaning to the login module in question. We'll see what these options mean later, for now we'll just be concerned with the structure of the configuration file.
+ </para>
+ <programlisting><application-policy name="jmx-console">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
+ <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
+ <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ <para>
+ The <literal>name</literal> attribute of the <literal>application-policy</literal> is the login configuration name. Applications policy elements will be bound by that name in JNDI under the the <literal>java:/jaas</literal> context. Applications will link to security domains through this JNDI name in their deployment descriptors. (See the <literal>security-domain</literal> elements in <literal>jboss.xml</literal>, <literal>jboss-web.xml</literal> and <literal>jboss-service.xml</literal> files for examples)
+ </para>
+ <para>
+ The <literal>code</literal> attribute of the <literal>login-module</literal> element specifies the class name of the login module implementation. The <literal>required</literal> flag attribute controls the overall behavior of the authentication stack. The allowed values and meanings are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">required</emphasis>: The login module is required to succeed for the authentication to be successful. If any required module fails, the authentication will fail. The remaining login modules in the stack will be called regardless of the outcome of the authentication.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">requisite</emphasis>: The login module is required to succeed. If it succeeds, authentication continues down the login stack. If it fails, control immediately returns to the application.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">sufficient</emphasis>: The login module is not required to succeed. If it does succeed, control immediately returns to the application. If it fails, authentication continues down the login stack.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">optional</emphasis>: The login module is not required to succeed. Authentication still continues to proceed down the login stack regardless of whether the login module succeeds or fails.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following example shows the definition of a security domain that uses multiple login modules. Since both modules are marked as sufficient, only one of them need to succeed for login to proceed.
+ </para>
+ <programlisting><application-policy name="todo">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
+ flag="sufficient">
+ <!-- LDAP configuration -->
+ </login-module>
+ <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
+ flag="sufficient">
+ <!-- database configuration -->
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ <para>
+ Each login module has its own set of configuration options. These are set as name/value pairs using the <literal>module-option</literal> elements. We'll cover module options in more depth when we look at the individual login modules available in JBoss AS.
+ </para>
+ <section id="JBoss-Security-Configuring_Microcontainer_Security_Domains">
+ <title>Configuring Microcontainer Security Domains</title>
+<!--Added this section from http://server.dzone.com/articles/security-features-jboss-510--> <para>Historically, the Enterprise Application Platform used the static <filename>login-config.xml</filename> file to configure the security domain. Extra functionality was provided with the introduction of the DynamicLoginConfig security service. This functionality allowed you to specify a Java Authentication and Authorisation Service (JAAS) as part of an application deployment, rather than having to include the configuration information in <filename>login-config.xml</filename>.</para>
+ <para>The Enterprise Application Platform now provides these security requirements through the use of the JBoss Microcontainer and EJBs. </para>
+ <para>In a security-conscious system, JavaEE components such as Web or Enterprise Java Bean (EJB) components require a Security Domain to manage the authentication, authorization, auditing, and mapping functionality. </para>
+ <para>The latest security implementation allows you to create a logically-named deployment descriptor file and specify the security domains within the file. The deployment descriptor can be deployed directly in the deploy folder, or packaged as part of the application JAR or WAR file.</para>
+ <procedure>
+ <title>Security Domain Deployment Descriptor</title>
+ <para>Follow this procedure to configure a security domain deployment descriptor with two domains named web-test and ejb-test.</para>
+ <step>
+ <title>Create deployment descriptor</title>
+ <para>You must create a deployment descriptor file to contain the security domain configuration.</para>
+ <para>The filename takes the format <filename><replaceable>[domain_name]</replaceable>-jboss-beans.xml</filename>. The <replaceable>domain_name</replaceable> is arbitrary, however you should choose a name that is meaningful to the application. </para>
+ <para>The file must contain the standard XML declaration, and a correctly configured <sgmltag><deployment></sgmltag> element.</para>
+ <programlisting role="XML" language="XML"><?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+
+</deployment></programlisting>
+ </step>
+ <step>
+ <title>Define application policies</title>
+ <para>Within the <sgmltag><deployment></sgmltag> element, the individual application policies are defined. Each policy specifies the login module to use, and any required options. </para>
+ <para>In the example below, two application policies are specified. Each policy uses the same login module, and module parameters.</para>
+ <note>
+ <para>Other login modules are available for use with the Enterprise Application Platform. For more information about the available login modules, refer to <xref linkend="Defining_Security_Domains-Using_JBoss_Login_Modules"/></para>
+ </note>
+ <programlisting language="XML" lang="XML"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/jboss-beans.xml_sample" parse="text"/></programlisting>
+ </step>
+ <step>
+ <title>Deploy or package the deployment descriptor</title>
+ <para>Move the deployment descriptor file to the <filename>deploy</filename> directory of the required server profile in your installation. </para>
+ <para>Alternatively, package the deployment descriptor in the <filename>META-INF</filename> directory of the EJB Jar, or the Web application (WAR).</para>
+ </step>
+ </procedure>
+<!--TODO: Thought I should mention this here, but technically the link provided in the Note links forward, instead of backwards. I wanted to mention the Login Modules here just in case readers didn't want to go old-school and use the login-config.xml method.--> </section>
+ <section>
+ <title>Configuring Authorization Stacks</title>
+ <para>If a security domain does not define an authorization module, the default <parameter>jboss-web-policy</parameter> and <parameter>jboss-ejb-policy</parameter> authorization configured in <filename>security-policies-jboss-beans.xml</filename> is used. If you specify an JAAS authorization module, or create a custom deployment descriptor file with valid authorization configuration, these settings override the default settings in <filename>security-policies-jboss-beans.xml</filename>. </para>
+ <para>Overriding the default authorization for EJB or Web components is implemented using Java Authorization Contract for Containers (JACC), Extensible Access Control Markup Language (XACML), or custom authorization methods. Configuring this functionality allows access control stacks to be pluggable for a particular component, overriding the default authorization contained in <filename>jboss.xml</filename> (for EJBs) and <filename>jboss-web.xml</filename> (for WAR).</para>
+ <formalpara>
+ <title>Setting authorization for all EJB and WEB components</title>
+ <para>You can override authorization for all EJBs and Web components, or for a particular component.</para>
+ </formalpara>
+ <procedure id="proc-Set_Auth_Policies_For_All_EJB_WAR_Components">
+ <title>Set authorization policies for all EJB and WAR components</title>
+ <para>This procedure describes how to define JACC Authorization control for all EJB and WAR components. The example defines application policy modules for three components: <filename>jboss-web-policy</filename>, <filename>jboss-ejb-policy</filename>, and <filename>jacc-test</filename>.</para>
+ <step>
+ <title>Open the security policy bean</title>
+ <para>Navigate to <filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/deploy/security</filename></para>
+ <para>Open the <filename>security-policies-jboss-beans.xml</filename> file. </para>
+ <para>By default, the security-policies-jboss-beans.xml file contains the configuration in <xref linkend="exam-security_policies_default_configuration"/></para>
+ <example id="exam-security_policies_default_configuration">
+ <title>security-policies default configuration</title>
+ <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-jboss-beans_default.xml_sample" parse="text"/></programlisting>
+ </example>
+ </step>
+ <step>
+ <title>Change the application-policy definitions</title>
+ <para>To set a single authorization policy for each component using JACC, amend each <sgmltag><policy-module></sgmltag> <parameter>code</parameter> attribute with the name of the JACC auuthorization module.</para>
+ <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-jboss-beans_all_ejb_war.xml_sample" parse="text"/></programlisting>
+ </step>
+ <step>
+ <title>Restart server</title>
+ <para>You have now configured the <filename>security-policy-jboss-beans.xml</filename> file with JACC authorization enabled for each application policy.</para>
+ <para>Restart the server to ensure the new security policy takes effect.</para>
+ </step>
+ </procedure>
+ <formalpara>
+ <title>Setting authorization for specific EJB and WEB components</title>
+ <para>If applications require more granular security policies, you can declare multiple authorization security policies for each application policy. New security domains can inherit base settings from another application policy, and override specific settings such as the authorization policy module. </para>
+ </formalpara>
+ <procedure id="proc-Set_Auth_Policies_For_Specific_Domains">
+ <title>Set authorization policies for specific security domains </title>
+ <para>This procedure describes how to inherit settings from other application policy definitions, and specify different authorization policies per security domain. </para>
+ <para>In this procedure, two security domains are defined. The <parameter>test-domain</parameter> security domain uses the UsersRolesLoginModule login module and uses JACC authorization. The <parameter>test-domain-inherited</parameter> security domain inherits the login module information from <parameter>test-domain</parameter>, and specifies XACML authorization must be used.</para>
+ <step>
+ <title>Open the security policy </title>
+ <para>You can specify the security domain settings in the <filename>login-config.xml</filename> file, or create a deployment descriptor file containing the settings. Choose the deployment descriptor if you want to package the security domain settings with your application.</para>
+ <stepalternatives performance="required">
+ <step performance="optional">
+ <title>Locate and open login-config.xml</title>
+ <para>Navigate to the <filename>login-config.xml</filename> file for the server profile you are using and open the file for editing. For example: </para>
+ <para><filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/conf/login.config.xml</filename></para>
+ </step>
+ <step performance="optional">
+ <title>Create a jboss-beans.xml descriptor</title>
+ <para>Create a <filename><replaceable>[prefix]</replaceable>-jboss-beans.xml</filename> descriptor, replacing <replaceable>[prefix]</replaceable> with a meaningful name (for example, <filename>test-war-jboss-beans.xml</filename>)</para>
+ <para>Save this file in the deploy directory of the server profile you are configuring. For example:</para>
+ <para><filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/deploy/test-war-jboss-beans.xml</filename></para>
+ </step>
+ </stepalternatives>
+ </step>
+ <step>
+ <title>Specify the test-domain security domain</title>
+ <para>In the target file chosen in step 1, specify the <parameter>test-domain</parameter> security domain. This domain contains the authentication information, including the <sgmltag><login-module></sgmltag> definition, and the JACC authorization policy module definition.</para>
+ <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/authorization-policy-specific-security-domain-1.xml_sample" parse="text"/></programlisting>
+ </step>
+ <step>
+ <title>Append the test-domain-inherited security domain</title>
+ <para>Append the <parameter>test-domain-inherited</parameter> application policy definition after the <parameter>test-domain</parameter> application policy. Set the <parameter>extends</parameter> attribute to <literal>other</literal>, so the login module information is inherited. Specify the XACML authorization module in the <sgmltag><policy.module></sgmltag> element.</para>
+ <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/authorization-policy-specific-security-domain-2.xml_sample" parse="text"/></programlisting>
+ </step>
+ <step>
+ <title>Restart server</title>
+ <para>You have now configured the target file with two security domains that use different authorization methods.</para>
+ <para>Restart the server to ensure the new security policy takes effect.</para>
+ </step>
+ </procedure>
+ <formalpara>
+ <title>Setting authorization module delegates</title>
+ <para><xref linkend="proc-Set_Auth_Policies_For_All_EJB_WAR_Components"/> and <xref linkend="proc-Set_Auth_Policies_For_Specific_Domains"/> describe simplistic examples that show how authentication and authorization can be configured in security domains. </para>
+ </formalpara>
+ <para>Because authorization relates to the type of component (not the layer) you want to protect, you can use delegation within a deployment descriptor to specify different authorization policies to the standard authentication in your implementation. </para>
+ <para>The delegates must be a subclass of <classname>AuthorizationModuleDelegate</classname>. <xref linkend="exam-security-AuthorizationModuleDelegate_Class"/> describes the base <classname>AuthorizationModuleDelegate</classname> interface. </para>
+ <para> </para>
+ <example id="exam-security-AuthorizationModuleDelegate_Class">
+ <title>AuthorizationModuleDelegate class</title>
+ <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-authorization_delegate_example.java" parse="text"/></programlisting>
+ </example>
+ <para>Some examples of authorization delegation are included for reference. <xref linkend="exam-security-EJBJACCPolicyModuleDelegate_Module"/> describes an authorization module responsible for authorization decisions for the EJB layer. <xref linkend="exam-security-WebJACCPolicyModuleDelegate_Module"/> describes a JACC-based authorization module helper that controls web layer authorization decisions.</para>
+ <example id="exam-security-EJBJACCPolicyModuleDelegate_Module">
+ <title>EJBJACCPolicyModuleDelegate.java</title>
+ <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-EJBJACCPolicyModuleDelegate.java" parse="text"/></programlisting>
+ </example>
+ <example id="exam-security-WebJACCPolicyModuleDelegate_Module">
+ <title>WebJACCPolicyModuleDelegate.java</title>
+ <programlisting role="JAVA" language="Java"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/security-policies-WebJACCPolicyModuleDelegate.java" parse="text"/></programlisting>
+ </example>
+ </section>
+ <section id="sect-Configure_Security_Auditing">
+ <title>Configuring Security Event Auditing</title>
+ <para>Certain government organizations mandate auditing in enterprise applications to ensure the software components of an implementation are traceable, and operating within their design parameters. Additionally, variants of government regulations and standards require audit controls in addition to standard application auditing.</para>
+ <para>System administrators can enable security event auditing to constantly monitor the operation of the security domain, and deployed Web and EJB applications. </para>
+ <important>
+ <title>Event Auditing, and Server Performance</title>
+ <para>Security event auditing may introduce a performance impact on implementations that manage high event volumes. Auditing is deactivated by default, and should be configured to be available on-demand.</para>
+ </important>
+ <para>Activating security event auditing differs between Web and EJB components. <xref linkend="proc-Enabling_Sec_Audit_Feature"/> describes the minimum steps to enable the audit service for EJBs in your implementation . <xref linkend="proc-Enable_Sec_Audit_Web"/> describes how to enable security event auditing for Web containers.</para>
+ <important>
+ <title>Event data security for Web components </title>
+ <para>Web container event auditing can expose sensitive user information. Administrators must ensure appropriate data protection procedures are implemented when configuring security auditing for Web container events.</para>
+ </important>
+ <procedure id="proc-Enabling_Sec_Audit_Feature">
+ <title>Enable the security audit feature</title>
+ <step>
+ <title>Open the log4j configuration file</title>
+ <para>Navigate to <filename><replaceable>[install_directory]</replaceable>/jboss-as/server/all/conf/</filename></para>
+ <para>Open the <filename>jboss-log4j.xml</filename> file using a text editor. </para>
+ </step>
+ <step>
+ <title>Uncomment the security audit category</title>
+ <para>By default, the Security Audit Provider category definition in the <filename>jboss-log4j.xml</filename> file is commented out. Uncomment the category definition shown in <xref linkend="exam-log4j_Security_Audit_Provider_Category"/>.</para>
+ <example id="exam-log4j_Security_Audit_Provider_Category">
+ <title>log4j Security Audit Provider category</title>
+ <programlisting role="XML" language="XML"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample" parse="text"/></programlisting>
+ </example>
+ </step>
+ <step>
+ <title>Uncomment the audit appender</title>
+ <para>By default, the AUDIT appender definition in the <filename>jboss-log4j.xml</filename> file is commented out. Uncomment the appender definition shown in <xref linkend="exam-log4j_Security_Audit_Provider_Category"/>.</para>
+ <example id="exam-log4j_Security_Audit_AUDIT_Appender">
+ <title>log4j Security Audit Provider category</title>
+ <programlisting role="XML" language="XML"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample" parse="text"/></programlisting>
+ </example>
+ </step>
+ <step>
+ <title>Save and restart server </title>
+ <para>You have now activated the auditing service for your implementation, as configured in the <filename>jboss-log4j.xml</filename> file.</para>
+ <para>Restart the server to ensure the new security policy takes effect.</para>
+ </step>
+ <step>
+ <title>Verify security auditing is functioning correctly</title>
+ <para>Once the audit service is configured and deployed, audit log entries will verify the audit service and EJB invocation success.</para>
+ <para>The <filename>audit.log</filename> file is located in <filename>[install_directory]/jboss-as/server/<replaceable>$PROFILES</replaceable>/log/</filename> directory. </para>
+ <para>A successful EJB invocation would look similar to the following <filename>audit.log</filename> output.</para>
+ <example>
+ <title>Successful EJB Invocation log entry</title>
+ <programlisting>2008-12-05 16:08:26,719 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-2:) [Success]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518; Resource:=[org.jboss.security.authorization.resources.EJBResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518}:method=public abstract org.jboss.test.security.interfaces.RunAsServiceRemote org.jboss.test.security.interfaces.RunAsServiceRemoteHome.create() throws java.rmi.RemoteException,javax.ejb.CreateException:ejbMethodInterface=Home:ejbName=RunAs:ejbPrincipal=jduke:MethodRoles=Roles(identitySubstitutionCaller,):securityRoleReferences=null:callerSubject=Subject:
+ Principal: [roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser]
+ Principal: Roles(members:extraRunAsRole,identitySubstitutionCaller)
+:callerRunAs=[roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser]:callerRunAs=[roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser]:ejbRestrictionEnforcement=false:ejbVersion=null];Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;Exception:=;</programlisting>
+ </example>
+ <para>An unsuccessful EJB invocation would look similar to the following <filename>audit.log</filename> output.</para>
+ <example>
+ <title>Unsuccessful EJB Invocation log entry</title>
+ <programlisting>[Error]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518;Resource:=[org.jboss.security.authorization.resources.EJBResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518}:method=public java.security.Principal org.jboss.test.security.ejb3.SimpleStatelessSessionBean.invokeUnavailableMethod():ejbMethodInterface=Remote:ejbName=SimpleStatelessSessionBean:ejbPrincipal=UserA:MethodRoles=Roles(<NOBODY>,):securityRoleReferences=null:callerSubject=Subject:
+ Principal: UserA
+ Principal: Roles(members:RegularUser,Administrator)
+:callerRunAs=null:callerRunAs=null:ejbRestrictionEnforcement=false:ejbVersion=null];Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;Exception:=Authorization Failed: ;</programlisting>
+ </example>
+ </step>
+ </procedure>
+ <procedure id="proc-Enable_Sec_Audit_Web">
+ <title>Enable security auditing for Web containers</title>
+ <step>
+ <title>Enable EJB security auditing</title>
+ <para>You must enable security as described in <xref linkend="proc-Enabling_Sec_Audit_Feature"/>.</para>
+ </step>
+ <step>
+ <title>Activate auditing in the server realm</title>
+ <para>Web container auditing must first be activated in the server realm of the <filename>server.xml</filename> file.</para>
+ <para>The <filename>server.xml</filename> file is located in the <filename><replaceable>[install_directory]</replaceable>/jboss-as/server/<replaceable>$PROFILES</replaceable>/deploy/jbossweb.sar/</filename> directory.</para>
+ <para>The <sgmltag><Realm></sgmltag> element must have the <parameter>enableAudit="<literal>true</literal>"</parameter> attribute set, as per <xref linkend="exam-server_xml_audit_activation"/>.</para>
+ <example>
+ <title id="exam-server_xml_audit_activation">server.xml audit activation</title>
+ <programlisting><Realm className="org.jboss.web.tomcat.security.JBossWebRealm" certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly"
+enableAudit="<literal>true</literal>"/></programlisting>
+ </example>
+ </step>
+ <step>
+ <title>Specify auditing levels system property</title>
+ <para>The auditing levels for Web applications must be specified using a system property in the <filename>run.bat</filename>, <filename>run.conf</filename> scripts. Alternatively, you can specify the system property in the <filename>/deploy/properties-service.xml</filename> file.</para>
+ <para>EXAMPLES TO GO IN HERE</para>
+ </step>
+ <step>
+ <title>Verify security auditing is functioning correctly</title>
+ <para>Once the system property is specified in the files, audit log entries will verify Web invocation success.</para>
+ <para>The <filename>audit.log</filename> file is located in <filename>[install_directory]/jboss-as/server/<replaceable>$PROFILES</replaceable>/log/</filename> directory. </para>
+ <para>A successful Web invocation would look similar to the following <filename>audit.log</filename> output.</para>
+ <example>
+ <title>Successful Web Invocation log entry</title>
+ <programlisting>2008-12-05 16:08:38,997 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-17:) [Success]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518;Resource:=[org.jboss.security.authorization.resources.WebResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration at 76ed4518,securityConstraints=[Lorg.apache.catalina.deploy.SecurityConstraint;@6feeae6, resourcePermissionCheck=true},canonicalRequestURI=/restricted/get-only/x,request=[/web-constraints:cookies=null:headers=user-agent=Jakarta Commons-HttpClient/3.0,authorization=host=localhost:8080,][parameters=],CodeSource=null];securityConstraints=SecurityConstraint[RestrictedAccess - Get Only];Source=org.jboss.security.plugins.javaee.WebAuthorizationHelper;resourcePermissionCheck=true;Exception:=;</programlisting>
+ </example>
+ <para>An unsuccessful EJB invocation would look similar to the following <filename>audit.log</filename> output.</para>
+ <example>
+ <title>Unsuccessful Web Invocation log entry</title>
+ <programlisting>2008-12-05 16:08:41,561 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-4:) [Failure]principal=anil;Source=org.jboss.web.tomcat.security.JBossWebRealm;request=[/jaspi-web-basic:cookies=null:headers=user-agent=Jakarta Commons-HttpClient/3.0,authorization=host=localhost:8080,][parameters=][attributes=];2008-12-05 16:07:30,129 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (WorkerThread#1[127.0.0.1:55055]:)</programlisting>
+ </example>
+ </step>
+ </procedure>
+ <para/>
+ </section>
+ <section id="Defining_Security_Domains-Loading_Security_Domains">
+ <title>Loading Security Domains</title>
+ <para>
+ Authentication security domains are configured statically in the <literal>conf/login-config.xml</literal> file, or deployed using <filename>jboss-beans.xml</filename> deployment descriptors (refer to . For static domains, the <literal>XMLLoginConfig</literal> MBean is responsible for loading security configurations from this configurations from a local configuration file. The MBean is defined as shown below.
+ </para>
+ <programlisting><mbean code="org.jboss.security.auth.login.XMLLoginConfig"
+ name="jboss.security:service=XMLLoginConfig">
+ <attribute name="ConfigResource">login-config.xml</attribute>
+</mbean>
+</programlisting>
+ <para>
+ The MBean supports the following attributes:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">ConfigURL</emphasis>: specifies the URL of the XML login configuration file that should be loaded by this MBean on startup. This must be a valid URL string representation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ConfigResource</emphasis>: specifies the resource name of the XML login configuration file that should be loaded by this MBean on startup. The name is treated as a classpath resource for which a URL is located using the thread context class loader.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ValidateDTD</emphasis>: a flag indicating if the XML configuration should be validated against its DTD. This defaults to true.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The MBean also supports the following operations that allow one to dynamically extend the login configurations at runtime. Note that any operation that attempts to alter login configuration requires a <literal>javax.security.auth.AuthPermission("refreshLoginConfiguration")</literal> when running with a security manager. The <literal>org.jboss.book.security.service.SecurityConfig</literal> service demonstrates how this can be used to add/remove a deployment specific security configuration dynamically.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>void addAppConfig(String appName, AppConfigurationEntry[] entries)</literal>: this adds the given login module configuration stack to the current configuration under the given <literal>appName</literal>. This replaces any existing entry under that name.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>void removeAppConfig(String appName)</literal>: this removes the login module configuration registered under the given <literal>appName</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String[] loadConfig(URL configURL) throws Exception</literal>: this loads one or more login configurations from a URL representing either an XML or legacy Sun login configuration file. Note that all login configurations must be added or none will be added. It returns the names of the login configurations that were added.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>void removeConfigs(String[] appNames)</literal>: this removes the login configurations specified <literal>appNames</literal> array.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String displayAppConfig(String appName)</literal>: this operation displays a simple string format of the named configuration if it exists.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>SecurityConfig</literal> MBean is responsible for selecting the <literal>javax.security.auth.login.Configuration</literal> to be used. The default configuration simply references the <literal>XMLLoginConfig</literal> MBean.
+ </para>
+ <programlisting> <mbean code="org.jboss.security.plugins.SecurityConfig"
+ name="jboss.security:service=SecurityConfig">
+ <attribute name="LoginConfig">jboss.security:service=XMLLoginConfig</attribute>
+ </mbean>
+</programlisting>
+ <para>
+ There is one configurable attribute:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">LoginConfig</emphasis>: Specifies the JMX <literal>ObjectName</literal> string of the MBean that provides the default JAAS login configuration. When the <literal>SecurityConfig</literal> is started, this MBean is queried for its <literal>javax.security.auth.login.Configuration</literal> by calling its <literal>getConfiguration(Configuration currentConfig)</literal> operation. If the <literal>LoginConfig</literal> attribute is not specified then the default Sun <literal>Configuration</literal> implementation described in the <literal>Configuration</literal> class JavaDocs is used.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In addition to allowing for a custom JAAS login configuration implementation, this service allows configurations to be chained together in a stack at runtime. This allows one to push a login configuration onto the stack and latter pop it. This is a feature used by the security unit tests to install custom login configurations into a default JBoss installation. Pushing a new configuration is done using:
+ </para>
+ <programlisting>public void pushLoginConfig(String objectName) throws
+ JMException, MalformedObjectNameException;
+</programlisting>
+ <para>
+ The <literal>objectName</literal> parameters specifies an MBean similar to the <literal>LoginConfig</literal> attribute. The current login configuration may be removed using:
+ </para>
+ <programlisting>public void popLoginConfig() throws JMException;</programlisting>
+ </section>
+ <section id="Defining_Security_Domains-The_DynamicLoginConfig_service">
+ <title>The DynamicLoginConfig service</title>
+ <para>
+ Security domains defined in the <literal>login-config.xml</literal> file are essentially static. They are read when JBoss starts up, but there is no easy way to add a new security domain or change the definition for an existing one. The <literal>DynamicLoginConfig</literal> service allows you to dynamically deploy security domains. This allows you to specify JAAS login configuration as part of a deployment (or just as a standalone service) rather than having to edit the static <literal>login-config.xml</literal> file.
+ </para>
+ <para>
+ The service supports the following attributes:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">AuthConfig</emphasis>: The resource path to the JAAS login configuration file to use. This defaults to <literal>login-config.xml</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">LoginConfigService</emphasis>: the <literal>XMLLoginConfig</literal> service name to use for loading. This service must support a <literal>String loadConfig(URL)</literal> operation to load the configurations.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">SecurityManagerService</emphasis>: The <literal>SecurityManagerService</literal> name used to flush the registered security domains. This service must support a <literal>flushAuthenticationCache(String)</literal> operation to flush the case for the argument security domain. Setting this triggers the flush of the authentication caches when the service is stopped.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Here is an example MBean definition using the <literal>DynamicLoginConfig</literal> service.
+ </para>
+ <programlisting><server>
+ <mbean code="org.jboss.security.auth.login.DynamicLoginConfig" name="...">
+ <attribute name="AuthConfig">login-config.xml</attribute>
+
+ <!-- The service which supports dynamic processing of login-config.xml
+ configurations.
+ -->
+ <depends optional-attribute-name="LoginConfigService">
+ jboss.security:service=XMLLoginConfig </depends>
+
+ <!-- Optionally specify the security mgr service to use when
+ this service is stopped to flush the auth caches of the domains
+ registered by this service.
+ -->
+ <depends optional-attribute-name="SecurityManagerService">
+ jboss.security:service=JaasSecurityManager </depends>
+ </mbean>
+</server>
+</programlisting>
+ <para>
+ This will load the specified <literal>AuthConfig</literal> resource using the specified <literal>LoginConfigService</literal> MBean by invoking <literal>loadConfig</literal> with the appropriate resource URL. When the service is stopped the configurations are removed. The resource specified may be either an XML file, or a Sun JAAS login configuration.
+ </para>
+ </section>
+ <section id="Defining_Security_Domains-Using_JBoss_Login_Modules">
+ <title>Using JBoss Login Modules</title>
+ <para>
+ JBoss includes several bundled login modules suitable for most user management needs. JBoss can read user information from a relational database, an LDAP server or flat files. In addition to these core login modules, JBoss provides several other login modules that provide user information for very customized needs in JBoss. Before we explore the individual login modules, let's take a look at a few login module configuration options that are common to multiple modules.
+ </para>
+ <section id="Using_JBoss_Login_Modules-Password_Stacking">
+ <title>Password Stacking</title>
+ <para>
+ Multiple login modules can be chained together in a stack, with each login module providing both the authentication and authorization components. This works for many use cases, but sometimes authentication and authorization are split across multiple user management stores. A previous example showed how to combine LDAP and a relational database, allowing a user to be authenticated by either system. However, consider the case where users are managed in a central LDAP server but application-specific roles are stored in the application's relational database. The password-stacking module option captures this relationship.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">password-stacking</emphasis>: When <literal>password-stacking</literal> option is set to <literal>useFirstPass</literal>, this module first looks for a shared username and password under the property names <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively in the login module shared state map. If found these are used as the principal name and password. If not found the principal name and password are set by this login module and stored under the property names <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ To use password stacking, each login module should set <literal>password-stacking</literal> to <literal>useFirstPass</literal>. If a previous module configured for password stacking has authenticated the user, all the other stacking modules will consider the user authenticated and only attempt to provide a set of roles for the authorization step.
+ </para>
+ <para>
+ The following listing shows how password stacking could be used:
+ </para>
+ <programlisting><application-policy name="todo">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
+ flag="required">
+ <!-- LDAP configuration -->
+ <module-option name="password-stacking">useFirstPass</module-option>
+ </login-module>
+ <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
+ flag="required">
+ <!-- database configuration -->
+ <module-option name="password-stacking">useFirstPass</module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ <para>
+ When using password stacking, it is usually appropriate to set all modules to be required to make sure that all modules are considered and have chance to contribute roles to the authorization process.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-Password_Hashing">
+ <title>Password Hashing</title>
+ <para>
+ Most of the login modules need to compare a client-supplied password to a password stored in a user management system. These modules generally work with plain text passwords, but can also be configured to support hashed passwords to prevent plain text passwords from being stored on the server side.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">hashAlgorithm</emphasis>: The name of the <literal>java.security.MessageDigest</literal> algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. Typical values are <literal>MD5</literal> and <literal>SHA</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">hashEncoding</emphasis>: The string format for the hashed pass and must be either <literal>base64</literal>, <literal>hex</literal> or <literal>rfc2617</literal>. The default is <literal>base64</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">hashCharset</emphasis>: The encoding used to convert the clear text password to a byte array. The platform default encoding is the default.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">hashUserPassword</emphasis>: This indicates that the hashing algorithm should be applied to the password the user submits. The hashed user password will be compared against the value in the login module, which is expected to be a hash of the password. The default is true.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">hashStorePassword</emphasis>: This indicates that the hashing algorithm should be applied to the password stored on the server side. This is used for digest authentication where the user submits a hash of the user password along with a request-specific tokens from the server to be comare. JBoss uses the hash algorithm (for digest, this would be <literal>rfc2617</literal>) to compute a server-side hash that should match the hashed value sent from the client.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The following is an login module configuration that assigns unauthenticated users the principal name <literal>nobody</literal> and contains based64-encoded, MD5 hashes of the passwords in a <literal>usersb64.properties</literal> file.
+ </para>
+ <programlisting><policy>
+ <application-policy name="testUsersRoles">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
+ flag="required">
+ <module-option name="hashAlgorithm">MD5</module-option>
+ <module-option name="hashEncoding">base64</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+</policy>
+</programlisting>
+ <para>
+ If you need to generate passwords in code, <literal>the org.jboss.security.Util</literal> class provides a static helper method that will hash a password using a given encoding.
+ </para>
+ <programlisting>String hashedPassword = Util.createPasswordHash("MD5",
+ Util.BASE64_ENCODING,
+ null,
+ null,
+ "password");
+</programlisting>
+ <para>
+ OpenSSL provides an alternative way to quickly generate hashed passwords.
+ </para>
+ <programlisting>echo -n password | openssl dgst -md5 -binary | openssl base64</programlisting>
+ <para>
+ In both cases, the text password should hash to "X03MO1qnZdYdgyfeuILPmQ==". This is the value that would need to be stored in the user store.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-Unauthenticated_Identity">
+ <title>Unauthenticated Identity</title>
+ <para>
+ Not all requests come in authenticated. The unauthenticated identity is a login module configuration option that assigns a specific identity (guest, for example) to requests that are made with no associated authentication information. This can be used to allow unprotected servlets to invoke methods on EJBs that do not require a specific role. Such a principal has no associated roles and so can only access either unsecured EJBs or EJB methods that are associated with the unchecked permission constraint.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">unauthenticatedIdentity</emphasis>: This defines the principal name that should be assigned to requests that contain no authentication information.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="Using_JBoss_Login_Modules-UsersRolesLoginModule">
+ <title>UsersRolesLoginModule</title>
+ <para>
+ The <literal>UsersRolesLoginModule</literal> is a simple login module that supports multiple users and user roles loaded from Java properties files. The username-to-password mapping file is called <literal>users.properties</literal> and the username-to-roles mapping file is called <literal>roles.properties</literal>. The properties files are loaded during initialization using the initialize method thread context class loader. This means that these files can be placed into the J2EE deployment JAR, the JBoss configuration directory, or any directory on the JBoss server or system classpath. The primary purpose of this login module is to easily test the security settings of multiple users and roles using properties files deployed with the application.
+ </para>
+ <para>
+ The <literal>users.properties</literal> file uses a <literal>username=password</literal> format with each user entry on a separate line as show here:
+ </para>
+ <programlisting>username1=password1
+username2=password2
+...
+</programlisting>
+ <para>
+ The <literal>roles.properties</literal> file uses as <literal>username=role1,role2,...</literal> format with an optional group name value. For example:
+ </para>
+ <programlisting>username1=role1,role2,...
+username1.RoleGroup1=role3,role4,...
+username2=role1,role3,...
+</programlisting>
+ <para>
+ The <literal>username.XXX</literal> form of property name is used to assign the username roles to a particular named group of roles where the <literal>XXX</literal> portion of the property name is the group name. The <literal>username=...</literal> form is an abbreviation for <literal>username.Roles=...</literal>, where the <literal>Roles</literal> group name is the standard name the <literal>JaasSecurityManager</literal> expects to contain the roles which define the users permissions.
+ </para>
+ <para>
+ The following would be equivalent definitions for the <literal>jduke</literal> username:
+ </para>
+ <programlisting>jduke=TheDuke,AnimatedCharacter
+jduke.Roles=TheDuke,AnimatedCharacter
+</programlisting>
+ <para>
+ The supported login module configuration options include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">usersProperties</emphasis>: The name of the properties resource containing the username to password mappings. This defaults to <literal>users.properties</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">rolesProperties</emphasis>: The name of the properties resource containing the username to roles mappings. This defaults to <literal>roles.properties</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ This login module supports password stacking, password hashing and unauthenticated identity.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-LdapLoginModule">
+ <title>LdapLoginModule</title>
+ <para>
+ The <literal>LdapLoginModule</literal> is a <literal>LoginModule</literal> implementation that authenticates against an LDAP server. You would use the <literal>LdapLoginModule</literal> if your username and credentials are stored in an LDAP server that is accessible using a JNDI LDAP provider.
+ </para>
+ <para>
+ The LDAP connectivity information is provided as configuration options that are passed through to the environment object used to create JNDI initial context. The standard LDAP JNDI properties used include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.factory.initial</emphasis>: The classname of the <literal>InitialContextFactory</literal> implementation. This defaults to the Sun LDAP provider implementation <literal>com.sun.jndi.ldap.LdapCtxFactory</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.provider.url</emphasis>: The LDAP URL for the LDAP server
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.security.authentication</emphasis>: The security level to use. This defaults to <literal>simple</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.security.protocol</emphasis>: The transport protocol to use for secure access, such as, SSL.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.security.principal</emphasis>: The principal for authenticating the caller to the service. This is built from other properties as described below.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.naming.security.credentials</emphasis>: The value of the property depends on the authentication scheme. For example, it could be a hashed password, clear-text password, key, certificate, and so on.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The supported login module configuration options include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">principalDNPrefix</emphasis>: A prefix to add to the username to form the user distinguished name. See <literal>principalDNSuffix</literal> for more info.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">principalDNSuffix</emphasis>: A suffix to add to the username when forming the user distinguished name. This is useful if you prompt a user for a username and you don't want the user to have to enter the fully distinguished name. Using this property and <literal>principalDNSuffix</literal> the <literal>userDN</literal> will be formed as <literal>principalDNPrefix + username + principalDNSuffix</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">useObjectCredential</emphasis>: A true/false value that indicates that the credential should be obtained as an opaque <literal>Object</literal> using the <literal>org.jboss.security.auth.callback.ObjectCallback</literal> type of <literal>Callback</literal> rather than as a <literal>char[]</literal> password using a JAAS <literal>PasswordCallback</literal>. This allows for passing non-<literal>char[]</literal> credential information to the LDAP server.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">rolesCtxDN</emphasis>: The fixed distinguished name to the context to search for user roles.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">userRolesCtxDNAttributeName</emphasis>: The name of an attribute in the user object that contains the distinguished name to the context to search for user roles. This differs from <literal>rolesCtxDN</literal> in that the context to search for a user's roles can be unique for each user.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">roleAttributeID</emphasis>: The name of the attribute that contains the user roles. If not specified this defaults to <literal>roles</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">roleAttributeIsDN</emphasis>: A flag indicating whether the <literal>roleAttributeID</literal> contains the fully distinguished name of a role object, or the role name. If false, the role name is taken from the value of <literal>roleAttributeID</literal>. If true, the role attribute represents the distinguished name of a role object. The role name is taken from the value of the <literal>roleNameAttributeId</literal> attribute of the context name by the distinguished name. In certain directory schemas (e.g., MS ActiveDirectory), role attributes in the user object are stored as DNs to role objects instead of as simple names, in which case, this property should be set to true. The default is false.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">roleNameAttributeID</emphasis>: The name of the attribute of the context pointed to by the <literal>roleCtxDN</literal> distinguished name value which contains the role name. If the <literal>roleAttributeIsDN</literal> property is set to true, this property is used to find the role object's name attribute. The default is <literal>group</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">uidAttributeID</emphasis>: The name of the attribute in the object containing the user roles that corresponds to the userid. This is used to locate the user roles. If not specified this defaults to <literal>uid</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">matchOnUserDN</emphasis>: A true/false flag indicating if the search for user roles should match on the user's fully distinguished name. If false, just the username is used as the match value against the <literal>uidAttributeName</literal> attribute. If true, the full <literal>userDN</literal> is used as the match value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">unauthenticatedIdentity</emphasis>: The principal name that should be assigned to requests that contain no authentication information. This behavior is inherited from the <literal>UsernamePasswordLoginModule</literal> superclass.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">allowEmptyPasswords</emphasis>: A flag indicating if empty (length 0) passwords should be passed to the LDAP server. An empty password is treated as an anonymous login by some LDAP servers and this may not be a desirable feature. Set this to false to reject empty passwords or true to have the LDAP server validate the empty password. The default is true.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The authentication of a user is performed by connecting to the LDAP server based on the login module configuration options. Connecting to the LDAP server is done by creating an <literal>InitialLdapContext</literal> with an environment composed of the LDAP JNDI properties described previously in this section. The <literal>Context.SECURITY_PRINCIPAL</literal> is set to the distinguished name of the user as obtained by the callback handler in combination with the <literal>principalDNPrefix</literal> and <literal>principalDNSuffix</literal> option values, and the <literal>Context.SECURITY_CREDENTIALS</literal> property is either set to the <literal>String</literal> password or the <literal>Object</literal> credential depending on the <literal>useObjectCredential</literal> option.
+ </para>
+ <para>
+ Once authentication has succeeded by virtue of being able to create an <literal>InitialLdapContext</literal> instance, the user's roles are queried by performing a search on the <literal>rolesCtxDN</literal> location with search attributes set to the <literal>roleAttributeName</literal> and <literal>uidAttributeName</literal> option values. The roles names are obtaining by invoking the <literal>toString</literal> method on the role attributes in the search result set.
+ </para>
+ <para>
+ The following is a sample <literal>login-config.xml</literal> entry.
+ </para>
+ <programlisting>
+ <application-policy name="testLDAP">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.LdapLoginModule"
+ flag="required">
+ <module-option name="java.naming.factory.initial">
+ com.sun.jndi.ldap.LdapCtxFactory
+ </module-option>
+ <module-option name="java.naming.provider.url">
+ ldap://ldaphost.jboss.org:1389/
+ </module-option>
+ <module-option name="java.naming.security.authentication">
+ simple
+ </module-option>
+ <module-option name="principalDNPrefix">uid=</module-option>
+ <module-option name="principalDNSuffix">
+ ,ou=People,dc=jboss,dc=org
+ </module-option>
+
+ <module-option name="rolesCtxDN">
+ ou=Roles,dc=jboss,dc=org
+ </module-option>
+ <module-option name="uidAttributeID">member</module-option>
+ <module-option name="matchOnUserDN">true</module-option>
+
+ <module-option name="roleAttributeID">cn</module-option>
+ <module-option name="roleAttributeIsDN">false </module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+</programlisting>
+ <para>
+ An LDIF file representing the structure of the directory this data operates against is shown below.
+ </para>
+ <programlisting>dn: dc=jboss,dc=org
+objectclass: top
+objectclass: dcObject
+objectclass: organization
+dc: jboss
+o: JBoss
+
+dn: ou=People,dc=jboss,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: People
+
+dn: uid=jduke,ou=People,dc=jboss,dc=org
+objectclass: top
+objectclass: uidObject
+objectclass: person
+uid: jduke
+cn: Java Duke
+sn: Duke
+userPassword: theduke
+
+dn: ou=Roles,dc=jboss,dc=org
+objectclass: top
+objectclass: organizationalUnit
+ou: Roles
+
+dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org
+objectclass: top
+objectclass: groupOfNames
+cn: JBossAdmin
+member: uid=jduke,ou=People,dc=jboss,dc=org
+description: the JBossAdmin group
+</programlisting>
+ <para>
+ Looking back at the <literal>testLDAP</literal> login module configuration, the <literal>java.naming.factory.initial</literal>, <literal>java.naming.factory.url</literal> and <literal>java.naming.security</literal> options indicate the Sun LDAP JNDI provider implementation will be used, the LDAP server is located on host <literal>ldaphost.jboss.org</literal> on port 1389, and that the LDAP simple authentication method will be use to connect to the LDAP server.
+ </para>
+ <para>
+ The login module attempts to connect to the LDAP server using a DN representing the user it is trying to authenticate. This DN is constructed from the <literal>principalDNPrefix</literal>, passed in, the username of the user and the <literal>principalDNSuffix</literal> as described above. In this example, the username <literal>jduke</literal> would map to <literal>uid=jduke,ou=People,dc=jboss,dc=org</literal>. We've assumed the LDAP server authenticates users using the <literal>userPassword</literal> attribute of the user's entry (<literal>theduke</literal> in this example). This is the way most LDAP servers work, however, if your LDAP server handles authentication differently you will need to set the authentication credentials in a way that makes sense for your server.
+ </para>
+ <para>
+ Once authentication succeeds, the roles on which authorization will be based are retrieved by performing a subtree search of the <literal>rolesCtxDN</literal> for entries whose <literal>uidAttributeID</literal> match the user. If <literal>matchOnUserDN</literal> is true the search will be based on the full DN of the user. Otherwise the search will be based on the actual user name entered. In this example, the search is under <literal>ou=Roles,dc=jboss,dc=org</literal> for any entries that have a <literal>member</literal> attribute equal to <literal>uid=jduke,ou=People,dc=jboss,dc=org</literal>. The search would locate <literal>cn=JBossAdmin</literal> under the roles entry.
+ </para>
+ <para>
+ The search returns the attribute specified in the <literal>roleAttributeID</literal> option. In this example, the attribute is <literal>cn</literal>. The value returned would be <literal>JBossAdmin</literal>, so the jduke user is assigned to the <literal>JBossAdmin</literal> role.
+ </para>
+ <para>
+ It's often the case that a local LDAP server provides identity and authentication services but is unable to use the authorization services. This is because application roles don't always map well onto LDAP groups, and LDAP administrators are often hesitant to allow external application-specific data in central LDAP servers. For this reason, the LDAP authentication module is often paired with another login module, such as the database login module, that can provide roles more suitable to the application being developed.
+ </para>
+ <para>
+ This login module also supports unauthenticated identity and password stacking.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-DatabaseServerLoginModule">
+ <title>DatabaseServerLoginModule</title>
+ <para>
+ The <literal>DatabaseServerLoginModule</literal> is a JDBC based login module that supports authentication and role mapping. You would use this login module if you have your username, password and role information relational database. The <literal>DatabaseServerLoginModule</literal> is based on two logical tables:
+ </para>
+ <programlisting>Table Principals(PrincipalID text, Password text)
+Table Roles(PrincipalID text, Role text, RoleGroup text)
+</programlisting>
+ <para>
+ The <literal>Principals</literal> table associates the user <literal>PrincipalID</literal> with the valid password and the <literal>Roles</literal> table associates the user <literal>PrincipalID</literal> with its role sets. The roles used for user permissions must be contained in rows with a <literal>RoleGroup</literal> column value of <literal>Roles</literal>. The tables are logical in that you can specify the SQL query that the login module uses. All that is required is that the <literal>java.sql.ResultSet</literal> has the same logical structure as the <literal>Principals</literal> and <literal>Roles</literal> tables described previously. The actual names of the tables and columns are not relevant as the results are accessed based on the column index. To clarify this notion, consider a database with two tables, <literal>Principals</literal> and <literal>Roles</literal>, as already declared. The following statements build the tables to contain a <literal>PrincipalID!
</literal><literal>java</literal> with a <literal>Password</literal> of <literal>echoman</literal> in the <literal>Principals</literal> table, a <literal>PrincipalID</literal><literal>java</literal> with a role named <literal>Echo</literal> in the <literal>Roles</literal><literal>RoleGroup</literal> in the <literal>Roles</literal> table, and a <literal>PrincipalID</literal><literal>java</literal> with a role named <literal>caller_java</literal> in the <literal>CallerPrincipal</literal><literal>RoleGroup</literal> in the <literal>Roles</literal> table:
+ </para>
+ <programlisting>INSERT INTO Principals VALUES('java', 'echoman')
+INSERT INTO Roles VALUES('java', 'Echo', 'Roles')
+INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
+</programlisting>
+ <para>
+ The supported login module configuration options include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">dsJndiName</emphasis>: The JNDI name for the <literal>DataSource</literal> of the database containing the logical <literal>Principals</literal> and <literal>Roles</literal> tables. If not specified this defaults to <literal>java:/DefaultDS</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">principalsQuery</emphasis>: The prepared statement query equivalent to: <literal>select Password from Principals where PrincipalID=?</literal>. If not specified this is the exact prepared statement that will be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">rolesQuery</emphasis>: The prepared statement query equivalent to: <literal>select Role, RoleGroup from Roles where PrincipalID=?</literal>. If not specified this is the exact prepared statement that will be used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ignorePasswordCase</emphasis>: A boolean flag indicating if the password comparison should ignore case. This can be useful for hashed password encoding where the case of the hashed password is not significant.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">principalClass</emphasis>: An option that specifies a <literal>Principal</literal> implementation class. This must support a constructor taking a string argument for the principal name.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ As an example <literal>DatabaseServerLoginModule</literal> configuration, consider a custom table schema like the following:
+ </para>
+ <programlisting>CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64))
+CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32))
+</programlisting>
+ <para>
+ A corresponding <literal>login-config.xml</literal> entry would be:
+ </para>
+ <programlisting><policy>
+ <application-policy name="testDB">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule"
+ flag="required">
+ <module-option name="dsJndiName">java:/MyDatabaseDS</module-option>
+ <module-option name="principalsQuery">
+ select passwd from Users username where username=?</module-option>
+ <module-option name="rolesQuery">
+ select userRoles, 'Roles' from UserRoles where username=?</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+</policy>
+</programlisting>
+ <para>
+ This module supports password stacking, password hashing and unathenticated identity.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-BaseCertLoginModule">
+ <title>BaseCertLoginModule</title>
+ <para>
+ This is a login module which authenticates users based on X509 certificates. A typical use case for this login module is <literal>CLIENT-CERT</literal> authentication in the web tier. This login module only performs authentication. You need to combine it with another login module capable of acquiring the authorization roles to completely define access to a secured web or EJB component. Two subclasses of this login module, <literal>CertRolesLoginModule</literal> and <literal>DatabaseCertLoginModule</literal> extend the behavior to obtain the authorization roles from either a properties file or database.
+ </para>
+ <para>
+ The <literal>BaseCertLoginModule</literal> needs a <literal>KeyStore</literal> to perform user validation. This is obtained through a <literal>org.jboss.security.SecurityDomain</literal> implementation. Typically, the <literal>SecurityDomain</literal> implementation is configured using the <literal>org.jboss.security.plugins.JaasSecurityDomain</literal> MBean as shown in this <literal>jboss-service.xml</literal> configuration fragment:
+ </para>
+ <programlisting><mbean code="org.jboss.security.plugins.JaasSecurityDomain"
+ name="jboss.ch8:service=SecurityDomain">
+ <constructor>
+ <arg type="java.lang.String" value="jmx-console"/>
+ </constructor>
+ <attribute name="KeyStoreURL">resource:localhost.keystore</attribute>
+ <attribute name="KeyStorePass">unit-tests-server</attribute>
+</mbean>
+</programlisting>
+ <para>
+ This creates a security domain with the name <literal>jmx-console</literal> whose <literal>SecurityDomain</literal> implementation is available via JNDI under the name <literal>java:/jaas/jmx-console</literal> following the JBossSX security domain naming pattern. To secure a web application such as the <literal>jmx-console.war</literal> using client certs and role based authorization, one would first modify the <literal>web.xml</literal> to declare the resources to be secured, along with the allowed roles and security domain to be used for authentication and authorization.
+ </para>
+ <programlisting><?xml version="1.0"?>
+<!DOCTYPE web-app PUBLIC
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+ ...
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>HtmlAdaptor</web-resource-name>
+ <description>An example security config that only allows users with
+ the role JBossAdmin to access the HTML JMX console web
+ application </description>
+ <url-pattern>/*</url-pattern>
+ <http-method>GET</http-method>
+ <http-method>POST</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>JBossAdmin</role-name>
+ </auth-constraint>
+ </security-constraint>
+ <login-config>
+ <auth-method>CLIENT-CERT</auth-method>
+ <realm-name>JBoss JMX Console</realm-name>
+ </login-config>
+ <security-role>
+ <role-name>JBossAdmin</role-name>
+ </security-role>
+</web-app>
+</programlisting>
+ <para>
+ Next we, need to specify the JBoss security domain in <literal>jboss-web.xml</literal>:
+ </para>
+ <programlisting><jboss-web>
+ <security-domain>java:/jaas/jmx-console</security-domain>
+</jboss-web>
+</programlisting>
+ <para>
+ Finally, you need to define the login module configuration for the jmx-console security domain you just specified. This is done in the <literal>conf/login-config.xml</literal> file.
+ </para>
+ <programlisting><application-policy name="jmx-console">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule"
+ flag="required">
+ <module-option name="password-stacking">useFirstPass</module-option>
+ <module-option name="securityDomain">java:/jaas/jmx-console</module-option>
+ </login-module>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
+ flag="required">
+ <module-option name="password-stacking">useFirstPass</module-option>
+ <module-option name="usersProperties">jmx-console-users.properties</module-option>
+ <module-option name="rolesProperties">jmx-console-roles.properties</module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ <para>
+ Here the <literal>BaseCertLoginModule</literal> is used for authentication of the client cert, and the <literal>UsersRolesLoginModule</literal> is only used for authorization due to the <literal>password-stacking=useFirstPass</literal> option. Both the <literal>localhost.keystore</literal> and the <literal>jmx-console-roles.properties</literal> need an entry that maps to the principal associated with the client cert. By default, the principal is created using the client certificate distinguished name. Consider the following certificate:
+ </para>
+ <programlisting>[starksm at banshee9100 conf]$ keytool -printcert -file unit-tests-client.export
+Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US
+Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin
+ at jboss.com, OU=QA, O=JBoss Inc.
+Serial number: 100103
+Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005
+Certificate fingerprints:
+ MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB
+ SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58
+</programlisting>
+ <para>
+ The <literal>localhost.keystore</literal> would need this cert stored with an alias of <literal>CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US</literal> and the <literal>jmx-console-roles.properties</literal> would also need an entry for the same entry. Since the DN contains many characters that are normally treated as delimiters, you will need to escape the problem characters using a backslash ('<literal>\</literal>') as shown here:
+ </para>
+ <programlisting># A sample roles.properties file for use with the UsersRolesLoginModule
+CN\=unit-tests-client,\ OU\=JBoss\ Inc.,\ O\=JBoss\ Inc.,\ ST\=Washington,\ C\=US=JBossAdmin
+admin=JBossAdmin
+</programlisting>
+ </section>
+ <section id="Using_JBoss_Login_Modules-IdentityLoginModule">
+ <title>IdentityLoginModule</title>
+ <para>
+ The <literal>IdentityLoginModule</literal> is a simple login module that associates a hard-coded user name a to any subject authenticated against the module. It creates a <literal>SimplePrincipal</literal> instance using the name specified by the <literal>principal</literal> option. This login module is useful when you need to provide a fixed identity to a service and in development environments when you want to test the security associated with a given principal and associated roles.
+ </para>
+ <para>
+ The supported login module configuration options include:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">principal</emphasis>: This is the name to use for the <literal>SimplePrincipal</literal> all users are authenticated as. The principal name defaults to <literal>guest</literal> if no principal option is specified.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">roles</emphasis>: This is a comma-delimited list of roles that will be assigned to the user.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ A sample XMLLoginConfig configuration entry that would authenticate all users as the principal named <literal>jduke</literal> and assign role names of <literal>TheDuke</literal>, and <literal>AnimatedCharacter</literal> is:
+ </para>
+ <programlisting><policy>
+ <application-policy name="testIdentity">
+ <authentication>
+ <login-module code="org.jboss.security.auth.spi.IdentityLoginModule"
+ flag="required">
+ <module-option name="principal">jduke</module-option>
+ <module-option name="roles">TheDuke,AnimatedCharater</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+</policy>
+</programlisting>
+ <para>
+ This module supports password stacking.
+ </para>
+ </section>
+ <section id="Using_JBoss_Login_Modules-RunAsLoginModule">
+ <title>RunAsLoginModule</title>
+ <para>
+ JBoss has a helper login module called <literal>RunAsLoginModule</literal> that pushes a run as role for the duration of the login phase of authentication, and pops the run as role in either the commit or abort phase. The purpose of this login module is to provide a role for other login modules that need to access secured resources in order to perform their authentication. An example would be a login module that accesses an secured EJB. This login module must be configured ahead of the login module(s) that need a run as role established.
+ </para>
+ <para>
+ The only login module configuration option is:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">roleName</emphasis>: the name of the role to use as the run as role during login phase. If not specified a default of <literal>nobody</literal> is used.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="Using_JBoss_Login_Modules-ClientLoginModule">
+ <title>ClientLoginModule</title>
+ <para>
+ The <literal>ClientLoginModule</literal> is an implementation of <literal>LoginModule</literal> for use by JBoss clients for the establishment of the caller identity and credentials. This simply sets the <literal>org.jboss.security.SecurityAssociation.principal</literal> to the value of the <literal>NameCallback</literal> filled in by the <literal>callbackhandler</literal>, and the <literal>org.jboss.security.SecurityAssociation.credential</literal> to the value of the <literal>PasswordCallback</literal> filled in by the <literal>callbackhandler</literal>. This is the only supported mechanism for a client to establish the current thread's caller. Both stand-alone client applications and server environments, acting as JBoss EJB clients where the security environment has not been configured to use JBossSX transparently, need to use the <literal>ClientLoginModule</literal>. Of course, you could always set the <literal>org.jboss.security.SecurityAssociation</literal> !
information directly, but this is considered an internal API that is subject to change without notice.
+ </para>
+ <para>
+ Note that this login module does not perform any authentication. It merely copies the login information provided to it into the JBoss server EJB invocation layer for subsequent authentication on the server. If you need to perform client-side authentication of users you would need to configure another login module in addition to the <literal>ClientLoginModule</literal>.
+ </para>
+ <para>
+ The supported login module configuration options include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">multi-threaded</emphasis>: When the multi-threaded option is set to true, each login thread has its own principal and credential storage. This is useful in client environments where multiple user identities are active in separate threads. When true, each separate thread must perform its own login. When set to false the login identity and credentials are global variables that apply to all threads in the VM. The default for this option is false.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">password-stacking</emphasis>: When <literal>password-stacking</literal> option is set to <literal>useFirstPass</literal>, this module first looks for a shared username and password using <literal>javax.security.auth.login.name</literal> and <literal>javax.security.auth.login.password</literal> respectively in the login module shared state map. This allows a module configured prior to this one to establish a valid username and password that should be passed to JBoss. You would use this option if you want to perform client-side authentication of clients using some other login module such as the <literal>LdapLoginModule</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">restore-login-identity</emphasis>: When <literal>restore-login-identity</literal> is true, the <literal>SecurityAssociation</literal> principal and credential seen on entry to the <literal>login()</literal> method are saved and restored on either abort or logout. When false (the default), the abort and logout simply clear the <literal>SecurityAssociation</literal>. A <literal>restore-login-identity</literal> of true is needed if one need to change identities and then restore the original caller identity.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ A sample login configuration for <literal>ClientLoginModule</literal> is the default configuration entry found in the JBoss distribution <literal>client/auth.conf</literal> file. The configuration is:
+ </para>
+ <programlisting>other {
+ // Put your login modules that work without jBoss here
+
+ // jBoss LoginModule
+ org.jboss.security.ClientLoginModule required;
+
+ // Put your login modules that need jBoss here
+};
+</programlisting>
+ </section>
+ </section>
+ <section id="Defining_Security_Domains-Writing_Custom_Login_Modules">
+ <title>Writing Custom Login Modules</title>
+ <para>
+ If the login modules bundled with the JBossSX framework do not work with your security environment, you can write your own custom login module implementation that does. Recall from the section on the <literal>JaasSecurityManager</literal> architecture that the <literal>JaasSecurityManager</literal> expected a particular usage pattern of the <literal>Subject</literal> principals set. You need to understand the JAAS Subject class's information storage features and the expected usage of these features to be able to write a login module that works with the <literal>JaasSecurityManager</literal>. This section examines this requirement and introduces two abstract base <literal>LoginModule</literal> implementations that can help you implement your own custom login modules.
+ </para>
+ <para>
+ You can obtain security information associated with a <literal>Subject</literal> in six ways in JBoss using the following methods:
+ </para>
+ <programlisting>java.util.Set getPrincipals()
+java.util.Set getPrincipals(java.lang.Class c)
+java.util.Set getPrivateCredentials()
+java.util.Set getPrivateCredentials(java.lang.Class c)
+java.util.Set getPublicCredentials()
+java.util.Set getPublicCredentials(java.lang.Class c)
+</programlisting>
+ <para>
+ For <literal>Subject</literal> identities and roles, JBossSX has selected the most natural choice: the principals sets obtained via <literal>getPrincipals()</literal> and <literal>getPrincipals(java.lang.Class)</literal>. The usage pattern is as follows:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ User identities (username, social security number, employee ID, and so on) are stored as <literal>java.security.Principal</literal> objects in the <literal>Subject</literal><literal>Principals</literal> set. The <literal>Principal</literal> implementation that represents the user identity must base comparisons and equality on the name of the principal. A suitable implementation is available as the <literal>org.jboss.security.SimplePrincipal</literal> class. Other <literal>Principal</literal> instances may be added to the <literal>Subject</literal><literal>Principals</literal> set as needed.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The assigned user roles are also stored in the <literal>Principals</literal> set, but they are grouped in named role sets using <literal>java.security.acl.Group</literal> instances. The <literal>Group</literal> interface defines a collection of <literal>Principal</literal>s and/or <literal>Group</literal>s, and is a subinterface of <literal>java.security.Principal</literal>. Any number of role sets can be assigned to a <literal>Subject</literal>. Currently, the JBossSX framework uses two well-known role sets with the names <literal>Roles</literal> and <literal>CallerPrincipal</literal>. The <literal>Roles</literal> Group is the collection of <literal>Principal</literal>s for the named roles as known in the application domain under which the <literal>Subject</literal> has been authenticated. This role set is used by methods like the <literal>EJBContext.isCallerInRole(String)</literal>, which EJBs can use to see if the current caller belongs to the named application dom!
ain role. The security interceptor logic that performs method permission checks also uses this role set. The <literal>CallerPrincipal</literal><literal>Group</literal> consists of the single <literal>Principal</literal> identity assigned to the user in the application domain. The <literal>EJBContext.getCallerPrincipal() </literal>method uses the <literal>CallerPrincipal</literal> to allow the application domain to map from the operation environment identity to a user identity suitable for the application. If a <literal>Subject</literal> does not have a <literal>CallerPrincipal</literal><literal>Group</literal>, the application identity is the same as operational environment identity.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <section id="Writing_Custom_Login_Modules-Support_for_the_Subject_Usage_Pattern">
+ <title>Support for the Subject Usage Pattern</title>
+ <para>
+ To simplify correct implementation of the <literal>Subject</literal> usage patterns described in the preceding section, JBossSX includes two abstract login modules that handle the population of the authenticated <literal>Subject</literal> with a template pattern that enforces correct <literal>Subject</literal> usage. The most generic of the two is the <literal>org.jboss.security.auth.spi.AbstractServerLoginModule</literal> class. It provides a concrete implementation of the <literal>javax.security.auth.spi.LoginModule</literal> interface and offers abstract methods for the key tasks specific to an operation environment security infrastructure. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses.
+ </para>
+ <programlisting>package org.jboss.security.auth.spi;
+/**
+ * This class implements the common functionality required for a JAAS
+ * server-side LoginModule and implements the JBossSX standard
+ * Subject usage pattern of storing identities and roles. Subclass
+ * this module to create your own custom LoginModule and override the
+ * login(), getRoleSets(), and getIdentity() methods.
+ */
+public abstract class AbstractServerLoginModule
+ implements javax.security.auth.spi.LoginModule
+{
+ protected Subject subject;
+ protected CallbackHandler callbackHandler;
+ protected Map sharedState;
+ protected Map options;
+ protected Logger log;
+
+ /** Flag indicating if the shared credential should be used */
+ protected boolean useFirstPass;
+ /**
+ * Flag indicating if the login phase succeeded. Subclasses that
+ * override the login method must set this to true on successful
+ * completion of login
+ */
+ protected boolean loginOk;
+
+ // ...
+ /**
+ * Initialize the login module. This stores the subject,
+ * callbackHandler and sharedState and options for the login
+ * session. Subclasses should override if they need to process
+ * their own options. A call to super.initialize(...) must be
+ * made in the case of an override.
+ *
+ * <p>
+ * The options are checked for the <em>password-stacking</em> parameter.
+ * If this is set to "useFirstPass", the login identity will be taken from the
+ * <code>javax.security.auth.login.name</code> value of the sharedState map,
+ * and the proof of identity from the
+ * <code>javax.security.auth.login.password</code> value of the sharedState map.
+ *
+ * @param subject the Subject to update after a successful login.
+ * @param callbackHandler the CallbackHandler that will be used to obtain the
+ * the user identity and credentials.
+ * @param sharedState a Map shared between all configured login module instances
+ * @param options the parameters passed to the login module.
+ */
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map sharedState,
+ Map options)
+ {
+ // ...
+ }
+
+
+ /**
+ * Looks for javax.security.auth.login.name and
+ * javax.security.auth.login.password values in the sharedState
+ * map if the useFirstPass option was true and returns true if
+ * they exist. If they do not or are null this method returns
+ * false.
+ * Note that subclasses that override the login method
+ * must set the loginOk var to true if the login succeeds in
+ * order for the commit phase to populate the Subject. This
+ * implementation sets loginOk to true if the login() method
+ * returns true, otherwise, it sets loginOk to false.
+ */
+ public boolean login()
+ throws LoginException
+ {
+ // ...
+ }
+
+ /**
+ * Overridden by subclasses to return the Principal that
+ * corresponds to the user primary identity.
+ */
+ abstract protected Principal getIdentity();
+
+ /**
+ * Overridden by subclasses to return the Groups that correspond
+ * to the role sets assigned to the user. Subclasses should
+ * create at least a Group named "Roles" that contains the roles
+ * assigned to the user. A second common group is
+ * "CallerPrincipal," which provides the application identity of
+ * the user rather than the security domain identity.
+ *
+ * @return Group[] containing the sets of roles
+ */
+ abstract protected Group[] getRoleSets() throws LoginException;
+}
+</programlisting>
+ <para>
+ You'll need to pay attention to the <literal>loginOk</literal> instance variable. This must be set to true if the login succeeds, false otherwise by any subclasses that override the login method. Failure to set this variable correctly will result in the commit method either not updating the subject when it should, or updating the subject when it should not. Tracking the outcome of the login phase was added to allow login modules to be chained together with control flags that do not require that the login module succeed in order for the overall login to succeed.
+ </para>
+ <para>
+ The second abstract base login module suitable for custom login modules is the <literal>org.jboss.security.auth.spi.UsernamePasswordLoginModule</literal>. This login module further simplifies custom login module implementation by enforcing a string-based username as the user identity and a <literal>char[]</literal> password as the authentication credentials. It also supports the mapping of anonymous users (indicated by a null username and password) to a principal with no roles. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses.
+ </para>
+ <programlisting>package org.jboss.security.auth.spi;
+
+/**
+ * An abstract subclass of AbstractServerLoginModule that imposes a
+ * an identity == String username, credentials == String password
+ * view on the login process. Subclasses override the
+ * getUsersPassword() and getUsersRoles() methods to return the
+ * expected password and roles for the user.
+ */
+public abstract class UsernamePasswordLoginModule
+ extends AbstractServerLoginModule
+{
+ /** The login identity */
+ private Principal identity;
+ /** The proof of login identity */
+ private char[] credential;
+ /** The principal to use when a null username and password are seen */
+ private Principal unauthenticatedIdentity;
+
+ /**
+ * The message digest algorithm used to hash passwords. If null then
+ * plain passwords will be used. */
+ private String hashAlgorithm = null;
+
+ /**
+ * The name of the charset/encoding to use when converting the
+ * password String to a byte array. Default is the platform's
+ * default encoding.
+ */
+ private String hashCharset = null;
+
+ /** The string encoding format to use. Defaults to base64. */
+ private String hashEncoding = null;
+
+ // ...
+
+ /**
+ * Override the superclass method to look for an
+ * unauthenticatedIdentity property. This method first invokes
+ * the super version.
+ *
+ * @param options,
+ * @option unauthenticatedIdentity: the name of the principal to
+ * assign and authenticate when a null username and password are
+ * seen.
+ */
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map sharedState,
+ Map options)
+ {
+ super.initialize(subject, callbackHandler, sharedState,
+ options);
+ // Check for unauthenticatedIdentity option.
+ Object option = options.get("unauthenticatedIdentity");
+ String name = (String) option;
+ if (name != null) {
+ unauthenticatedIdentity = new SimplePrincipal(name);
+ }
+ }
+
+ // ...
+
+ /**
+ * A hook that allows subclasses to change the validation of the
+ * input password against the expected password. This version
+ * checks that neither inputPassword or expectedPassword are null
+ * and that inputPassword.equals(expectedPassword) is true;
+ *
+ * @return true if the inputPassword is valid, false otherwise.
+ */
+ protected boolean validatePassword(String inputPassword,
+ String expectedPassword)
+ {
+ if (inputPassword == null || expectedPassword == null) {
+ return false;
+ }
+ return inputPassword.equals(expectedPassword);
+ }
+
+ /**
+ * Get the expected password for the current username available
+ * via the getUsername() method. This is called from within the
+ * login() method after the CallbackHandler has returned the
+ * username and candidate password.
+ *
+ * @return the valid password String
+ */
+ abstract protected String getUsersPassword()
+ throws LoginException;
+}
+</programlisting>
+ <para>
+ The choice of subclassing the <literal>AbstractServerLoginModule</literal> versus <literal>UsernamePasswordLoginModule</literal> is simply based on whether a string-based username and credentials are usable for the authentication technology you are writing the login module for. If the string-based semantic is valid, then subclass <literal>UsernamePasswordLoginModule</literal>, otherwise subclass <literal>AbstractServerLoginModule</literal>.
+ </para>
+ <para>
+ The steps you are required to perform when writing a custom login module are summarized in the following depending on which base login module class you choose. When writing a custom login module that integrates with your security infrastructure, you should start by subclassing <literal>AbstractServerLoginModule</literal> or <literal>UsernamePasswordLoginModule</literal> to ensure that your login module provides the authenticated <literal>Principal</literal> information in the form expected by the JBossSX security manager.
+ </para>
+ <para>
+ When subclassing the <literal>AbstractServerLoginModule</literal>, you need to override the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>void initialize(Subject, CallbackHandler, Map, Map)</literal>: if you have custom options to parse.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>boolean login()</literal>: to perform the authentication activity. Be sure to set the <literal>loginOk</literal> instance variable to true if login succeeds, false if it fails.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Principal getIdentity()</literal>: to return the <literal>Principal</literal> object for the user authenticated by the <literal>log()</literal> step.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Group[] getRoleSets()</literal>: to return at least one <literal>Group</literal> named <literal>Roles</literal> that contains the roles assigned to the <literal>Principal</literal> authenticated during <literal>login()</literal>. A second common <literal>Group</literal> is named <literal>CallerPrincipal</literal> and provides the user's application identity rather than the security domain identity.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ When subclassing the <literal>UsernamePasswordLoginModule</literal>, you need to override the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>void initialize(Subject, CallbackHandler, Map, Map)</literal>: if you have custom options to parse.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Group[] getRoleSets()</literal>: to return at least one <literal>Group</literal> named <literal>Roles</literal> that contains the roles assigned to the <literal>Principal</literal> authenticated during <literal>login()</literal>. A second common <literal>Group</literal> is named <literal>CallerPrincipal</literal> and provides the user's application identity rather than the security domain identity.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>String getUsersPassword()</literal>: to return the expected password for the current username available via the <literal>getUsername()</literal> method. The <literal>getUsersPassword()</literal> method is called from within <literal>login()</literal> after the <literal>callbackhandler</literal> returns the username and candidate password.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="Writing_Custom_Login_Modules-A_Custom_LoginModule_Example">
+ <title>A Custom LoginModule Example</title>
+ <para>
+ In this section we will develop a custom login module example. It will extend the <literal>UsernamePasswordLoginModule</literal> and obtains a user's password and role names from a JNDI lookup. The idea is that there is a JNDI context that will return a user's password if you perform a lookup on the context using a name of the form <literal>password/<username></literal> where <literal><username></literal> is the current user being authenticated. Similarly, a lookup of the form <literal>roles/<username></literal> returns the requested user's roles.
+ </para>
+ <para>
+ The source code for the example is located in the <literal>src/main/org/jboss/book/security/ex2</literal> directory of the book examples. <xref linkend="A_Custom_LoginModule_Example-_A_JndiUserAndPass_custom_login_module"/> shows the source code for the <literal>JndiUserAndPass</literal> custom login module. Note that because this extends the JBoss <literal>UsernamePasswordLoginModule</literal>, all the <literal>JndiUserAndPass</literal> does is obtain the user's password and roles from the JNDI store. The <literal>JndiUserAndPass</literal> does not concern itself with the JAAS <literal>LoginModule</literal> operations.
+ </para>
+ <example id="A_Custom_LoginModule_Example-_A_JndiUserAndPass_custom_login_module">
+ <title> A JndiUserAndPass custom login module</title>
+ <programlisting>package org.jboss.book.security.ex2;
+
+import java.security.acl.Group;
+import java.util.Map;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.security.SimpleGroup;
+import org.jboss.security.SimplePrincipal;
+import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
+
+/**
+ * An example custom login module that obtains passwords and roles
+ * for a user from a JNDI lookup.
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 1.4 $
+*/
+public class JndiUserAndPass
+ extends UsernamePasswordLoginModule
+{
+ /** The JNDI name to the context that handles the password/username lookup */
+ private String userPathPrefix;
+ /** The JNDI name to the context that handles the roles/ username lookup */
+ private String rolesPathPrefix;
+
+ /**
+ * Override to obtain the userPathPrefix and rolesPathPrefix options.
+ */
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map sharedState, Map options)
+ {
+ super.initialize(subject, callbackHandler, sharedState, options);
+ userPathPrefix = (String) options.get("userPathPrefix");
+ rolesPathPrefix = (String) options.get("rolesPathPrefix");
+ }
+
+ /**
+ * Get the roles the current user belongs to by querying the
+ * rolesPathPrefix + '/' + super.getUsername() JNDI location.
+ */
+ protected Group[] getRoleSets() throws LoginException
+ {
+ try {
+ InitialContext ctx = new InitialContext();
+ String rolesPath = rolesPathPrefix + '/' + super.getUsername();
+
+ String[] roles = (String[]) ctx.lookup(rolesPath);
+ Group[] groups = {new SimpleGroup("Roles")};
+ log.info("Getting roles for user="+super.getUsername());
+ for(int r = 0; r < roles.length; r ++) {
+ SimplePrincipal role = new SimplePrincipal(roles[r]);
+ log.info("Found role="+roles[r]);
+ groups[0].addMember(role);
+ }
+ return groups;
+ } catch(NamingException e) {
+ log.error("Failed to obtain groups for
+ user="+super.getUsername(), e);
+ throw new LoginException(e.toString(true));
+ }
+ }
+
+ /**
+ * Get the password of the current user by querying the
+ * userPathPrefix + '/' + super.getUsername() JNDI location.
+ */
+ protected String getUsersPassword()
+ throws LoginException
+ {
+ try {
+ InitialContext ctx = new InitialContext();
+ String userPath = userPathPrefix + '/' + super.getUsername();
+ log.info("Getting password for user="+super.getUsername());
+ String passwd = (String) ctx.lookup(userPath);
+ log.info("Found password="+passwd);
+ return passwd;
+ } catch(NamingException e) {
+ log.error("Failed to obtain password for
+ user="+super.getUsername(), e);
+ throw new LoginException(e.toString(true));
+ }
+ }
+}
+</programlisting>
+ </example>
+ <para>
+ The details of the JNDI store are found in the <literal>org.jboss.book.security.ex2.service.JndiStore</literal> MBean. This service binds an <literal>ObjectFactory</literal> that returns a <literal>javax.naming.Context</literal> proxy into JNDI. The proxy handles lookup operations done against it by checking the prefix of the lookup name against <literal>password</literal> and <literal>roles</literal>. When the name begins with <literal>password</literal>, a user's password is being requested. When the name begins with <literal>roles</literal> the user's roles are being requested. The example implementation always returns a password of <literal>theduke</literal> and an array of roles names equal to <literal>{"TheDuke", "Echo"}</literal> regardless of what the username is. You can experiment with other implementations as you wish.
+ </para>
+ <para>
+ The example code includes a simple session bean for testing the custom login module. To build, deploy and run the example, execute the following command in the examples directory.
+ </para>
+ <programlisting>[examples]$ ant -Dchap=security -Dex=2 run-example
+...
+run-example2:
+ [echo] Waiting for 5 seconds for deploy...
+ [java] [INFO,ExClient] Login with username=jduke, password=theduke
+ [java] [INFO,ExClient] Looking up EchoBean2
+ [java] [INFO,ExClient] Created Echo
+ [java] [INFO,ExClient] Echo.echo('Hello') = Hello
+</programlisting>
+ <para>
+ The choice of using the <literal>JndiUserAndPass</literal> custom login module for the server side authentication of the user is determined by the login configuration for the example security domain. The EJB JAR <literal>META-INF/jboss.xml</literal> descriptor sets the security domain
+ </para>
+ <programlisting><?xml version="1.0"?>
+<jboss>
+ <security-domain>java:/jaas/security-ex2</security-domain>
+</jboss>
+</programlisting>
+ <para>
+ The SAR <literal>META-INF/login-config.xml</literal> descriptor defines the login module configuration.
+ </para>
+ <programlisting><application-policy name = "security-ex2">
+ <authentication>
+ <login-module code="org.jboss.book.security.ex2.JndiUserAndPass"
+ flag="required">
+ <module-option name = "userPathPrefix">/security/store/password</module-option>
+ <module-option name = "rolesPathPrefix">/security/store/roles</module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ </section>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-The_Secure_Remote_Password_SRP_Protocol">
+ <title>The Secure Remote Password (SRP) Protocol</title>
+ <para>
+ The SRP protocol is an implementation of a public key exchange handshake described in the Internet standards working group request for comments 2945(RFC2945). The RFC2945 abstract states:
+ </para>
+ <para>
+ This document describes a cryptographically strong network authentication mechanism known as the Secure Remote Password (SRP) protocol. This mechanism is suitable for negotiating secure connections using a user-supplied password, while eliminating the security problems traditionally associated with reusable passwords. This system also performs a secure key exchange in the process of authentication, allowing security layers (privacy and/or integrity protection) to be enabled during the session. Trusted key servers and certificate infrastructures are not required, and clients are not required to store or manage any long-term keys. SRP offers both security and deployment advantages over existing challenge-response techniques, making it an ideal drop-in replacement where secure password authentication is needed.
+ </para>
+ <para>
+ Note: The complete RFC2945 specification can be obtained from <ulink url="http://www.rfc-editor.org/rfc.html"/>. Additional information on the SRP algorithm and its history can be found at <ulink url="http://www-cs-students.stanford.edu/~tjw/srp/"/>.
+ </para>
+ <para>
+ SRP is similar in concept and security to other public key exchange algorithms, such as Diffie-Hellman and RSA. SRP is based on simple string passwords in a way that does not require a clear text password to exist on the server. This is in contrast to other public key-based algorithms that require client certificates and the corresponding certificate management infrastructure.
+ </para>
+ <para>
+ Algorithms like Diffie-Hellman and RSA are known as public key exchange algorithms. The concept of public key algorithms is that you have two keys, one public that is available to everyone, and one that is private and known only to you. When someone wants to send encrypted information to you, then encrpyt the information using your public key. Only you are able to decrypt the information using your private key. Contrast this with the more traditional shared password based encryption schemes that require the sender and receiver to know the shared password. Public key algorithms eliminate the need to share passwords.
+ </para>
+ <para>
+ The JBossSX framework includes an implementation of SRP that consists of the following elements:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ An implementation of the SRP handshake protocol that is independent of any particular client/server protocol
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ An RMI implementation of the handshake protocol as the default client/server SRP implementation
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A client side JAAS <literal>LoginModule</literal> implementation that uses the RMI implementation for use in authenticating clients in a secure fashion
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A JMX MBean for managing the RMI server implementation. The MBean allows the RMI server implementation to be plugged into a JMX framework and externalizes the configuration of the verification information store. It also establishes an authentication cache that is bound into the JBoss server JNDI namespace.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A server side JAAS <literal>LoginModule</literal> implementation that uses the authentication cache managed by the SRP JMX MBean.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ <xref linkend="The_Secure_Remote_Password_SRP_Protocol-The_JBossSX_components_of_the_SRP_client_server_framework."/> gives a diagram of the key components involved in the JBossSX implementation of the SRP client/server framework.
+ </para>
+ <figure id="The_Secure_Remote_Password_SRP_Protocol-The_JBossSX_components_of_the_SRP_client_server_framework.">
+ <title>The JBossSX components of the SRP client-server framework.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-13.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <para>
+ On the client side, SRP shows up as a custom JAAS <literal>LoginModule</literal> implementation that communicates to the authentication server through an <literal>org.jboss.security.srp.SRPServerInterface</literal> proxy. A client enables authentication using SRP by creating a login configuration entry that includes the <literal>org.jboss.security.srp.jaas.SRPLoginModule</literal>. This module supports the following configuration options:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">principalClassName</emphasis>: This option is no longer supported. The principal class is now always <literal>org.jboss.security.srp.jaas.SRPPrincipal</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">srpServerJndiName</emphasis>: The JNDI name of the <literal>SRPServerInterface</literal> object to use for communicating with the SRP authentication server. If both <literal>srpServerJndiName</literal> and <literal>srpServerRmiUrl</literal> options are specified, the <literal>srpServerJndiName</literal> is tried before <literal>srpServerRmiUrl</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">srpServerRmiUrl</emphasis>: The RMI protocol URL string for the location of the <literal>SRPServerInterface</literal> proxy to use for communicating with the SRP authentication server.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">externalRandomA</emphasis>: A true/false flag indicating if the random component of the client public key A should come from the user callback. This can be used to input a strong cryptographic random number coming from a hardware token for example.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">hasAuxChallenge</emphasis>: A true/false flag indicating that a string will be sent to the server as an additional challenge for the server to validate. If the client session supports an encryption cipher then a temporary cipher will be created using the session private key and the challenge object sent as a <literal>javax.crypto.SealedObject</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">multipleSessions</emphasis>: a true/false flag indicating if a given client may have multiple SRP login sessions active simultaneously.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Any other options passed in that do not match one of the previous named options is treated as a JNDI property to use for the environment passed to the <literal>InitialContext</literal> constructor. This is useful if the SRP server interface is not available from the default <literal>InitialContext</literal>.
+ </para>
+ <para>
+ The <literal>SRPLoginModule</literal> needs to be configured along with the standard <literal>ClientLoginModule</literal> to allow the SRP authentication credentials to be used for validation of access to security J2EE components. An example login configuration entry that demonstrates such a setup is:
+ </para>
+ <programlisting>srp {
+ org.jboss.security.srp.jaas.SRPLoginModule required
+ srpServerJndiName="SRPServerInterface"
+ ;
+
+ org.jboss.security.ClientLoginModule required
+ password-stacking="useFirstPass"
+ ;
+};
+</programlisting>
+ <para>
+ On the JBoss server side, there are two MBeans that manage the objects that collectively make up the SRP server. The primary service is the <literal>org.jboss.security.srp.SRPService</literal> MBean, and it is responsible for exposing an RMI accessible version of the SRPServerInterface as well as updating the SRP authentication session cache. The configurable SRPService MBean attributes include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">JndiName</emphasis>: The JNDI name from which the SRPServerInterface proxy should be available. This is the location where the <literal>SRPService</literal> binds the serializable dynamic proxy to the <literal>SRPServerInterface</literal>. If not specified it defaults to <literal>srp/SRPServerInterface</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">VerifierSourceJndiName</emphasis>: The JNDI name of the <literal>SRPVerifierSource</literal> implementation that should be used by the <literal>SRPService</literal>. If not set it defaults to <literal>srp/DefaultVerifierSource</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">AuthenticationCacheJndiName</emphasis>: The JNDI name under which the authentication <literal>org.jboss.util.CachePolicy</literal> implementation to be used for caching authentication information is bound. The SRP session cache is made available for use through this binding. If not specified it defaults to <literal>srp/AuthenticationCache</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ServerPort</emphasis>: RMI port for the <literal>SRPRemoteServerInterface</literal>. If not specified it defaults to 10099.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ClientSocketFactory</emphasis>: An optional custom <literal>java.rmi.server.RMIClientSocketFactory</literal> implementation class name used during the export of the <literal>SRPServerInterface</literal>. If not specified the default <literal>RMIClientSocketFactory</literal> is used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">ServerSocketFactory</emphasis>: An optional custom <literal>java.rmi.server.RMIServerSocketFactory</literal> implementation class name used during the export of the <literal>SRPServerInterface</literal>. If not specified the default <literal>RMIServerSocketFactory</literal> is used.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">AuthenticationCacheTimeout</emphasis>: Specifies the timed cache policy timeout in seconds. If not specified this defaults to 1800 seconds(30 minutes).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">AuthenticationCacheResolution</emphasis>: Specifies the timed cache policy resolution in seconds. This controls the interval between checks for timeouts. If not specified this defaults to 60 seconds(1 minute).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">RequireAuxChallenge</emphasis>: Set if the client must supply an auxiliary challenge as part of the verify phase. This gives control over whether the <literal>SRPLoginModule</literal> configuration used by the client must have the <literal>useAuxChallenge</literal> option enabled.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">OverwriteSessions</emphasis>: A flag indicating if a successful user auth for an existing session should overwrite the current session. This controls the behavior of the server SRP session cache when clients have not enabled the multiple session per user mode. The default is false meaning that the second attempt by a user to authentication will succeed, but the resulting SRP session will not overwrite the previous SRP session state.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The one input setting is the <literal>VerifierSourceJndiName</literal> attribute. This is the location of the SRP password information store implementation that must be provided and made available through JNDI. The <literal>org.jboss.security.srp SRPVerifierStoreService</literal> is an example MBean service that binds an implementation of the <literal>SRPVerifierStore</literal> interface that uses a file of serialized objects as the persistent store. Although not realistic for a production environment, it does allow for testing of the SRP protocol and provides an example of the requirements for an <literal>SRPVerifierStore</literal> service. The configurable <literal>SRPVerifierStoreService</literal> MBean attributes include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">JndiName</emphasis>: The JNDI name from which the <literal>SRPVerifierStore</literal> implementation should be available. If not specified it defaults to <literal>srp/DefaultVerifierSource</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">StoreFile</emphasis>: The location of the user password verifier serialized object store file. This can be either a URL or a resource name to be found in the classpath. If not specified it defaults to <literal>SRPVerifierStore.ser</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The <literal>SRPVerifierStoreService</literal> MBean also supports <literal>addUser</literal> and <literal>delUser</literal> operations for addition and deletion of users. The signatures are:
+ </para>
+ <programlisting>public void addUser(String username, String password) throws IOException;
+public void delUser(String username) throws IOException;
+</programlisting>
+ <para>
+ An example configuration of these services is presented in <xref linkend="Providing_Password_Information_for_SRP-The_SRPVerifierStore_interface"/>.
+ </para>
+ <section id="The_Secure_Remote_Password_SRP_Protocol-Providing_Password_Information_for_SRP">
+ <title>Providing Password Information for SRP</title>
+ <para>
+ The default implementation of the <literal>SRPVerifierStore</literal> interface is not likely to be suitable for your production security environment as it requires all password hash information to be available as a file of serialized objects. You need to provide an MBean service that provides an implementation of the <literal>SRPVerifierStore</literal> interface that integrates with your existing security information stores. The <literal>SRPVerifierStore</literal> interface is shown in.
+ </para>
+ <example id="Providing_Password_Information_for_SRP-The_SRPVerifierStore_interface">
+ <title>The SRPVerifierStore interface</title>
+ <programlisting>package org.jboss.security.srp;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.KeyException;
+
+public interface SRPVerifierStore
+{
+ public static class VerifierInfo implements Serializable
+ {
+ /**
+ * The username the information applies to. Perhaps redundant
+ * but it makes the object self contained.
+ */
+ public String username;
+
+ /** The SRP password verifier hash */
+ public byte[] verifier;
+ /** The random password salt originally used to verify the password */
+ public byte[] salt;
+ /** The SRP algorithm primitive generator */
+ public byte[] g;
+ /** The algorithm safe-prime modulus */
+ public byte[] N;
+ }
+
+ /**
+ * Get the indicated user's password verifier information.
+ */
+ public VerifierInfo getUserVerifier(String username)
+ throws KeyException, IOException;
+ /**
+ * Set the indicated users' password verifier information. This
+ * is equivalent to changing a user's password and should
+ * generally invalidate any existing SRP sessions and caches.
+ */
+ public void setUserVerifier(String username, VerifierInfo info)
+ throws IOException;
+
+ /**
+ * Verify an optional auxiliary challenge sent from the client to
+ * the server. The auxChallenge object will have been decrypted
+ * if it was sent encrypted from the client. An example of a
+ * auxiliary challenge would be the validation of a hardware token
+ * (SafeWord, SecureID, iButton) that the server validates to
+ * further strengthen the SRP password exchange.
+ */
+ public void verifyUserChallenge(String username, Object auxChallenge)
+ throws SecurityException;
+}
+</programlisting>
+ <para>
+ The primary function of a <literal>SRPVerifierStore</literal> implementation is to provide access to the <literal>SRPVerifierStore.VerifierInfo</literal> object for a given username. The <literal>getUserVerifier(String)</literal> method is called by the <literal>SRPService</literal> at that start of a user SRP session to obtain the parameters needed by the SRP algorithm. The elements of the <literal>VerifierInfo</literal> objects are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">username</emphasis>: The user's name or id used to login.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">verifier</emphasis>: This is the one-way hash of the password or PIN the user enters as proof of their identity. The <literal>org.jboss.security.Util</literal> class has a <literal>calculateVerifier</literal> method that performs that password hashing algorithm. The output password <literal>H(salt | H(username | ':' | password))</literal> as defined by RFC2945. Here <literal>H</literal> is the SHA secure hash function. The username is converted from a string to a <literal>byte[]</literal> using the UTF-8 encoding.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">salt</emphasis>: This is a random number used to increase the difficulty of a brute force dictionary attack on the verifier password database in the event that the database is compromised. It is a value that should be generated from a cryptographically strong random number algorithm when the user's existing clear-text password is hashed.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">g</emphasis>: The SRP algorithm primitive generator. In general this can be a well known fixed parameter rather than a per-user setting. The <literal>org.jboss.security.srp.SRPConf</literal> utility class provides several settings for g including a good default which can obtained via <literal>SRPConf.getDefaultParams().g()</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">N</emphasis>: The SRP algorithm safe-prime modulus. In general this can be a well known fixed parameter rather than a per-user setting. The <literal>org.jboss.security.srp.SRPConf</literal> utility class provides several settings for <literal>N</literal> including a good default which can obtained via <literal>SRPConf.getDefaultParams().N()</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ So, step 1 of integrating your existing password store is the creation of a hashed version of the password information. If your passwords are already store in an irreversible hashed form, then this can only be done on a per-user basis as part of an upgrade procedure for example. Note that the <literal>setUserVerifier(String, VerifierInfo)</literal> method is not used by the current SRPSerivce and may be implemented as no-op method, or even one that throws an exception stating that the store is read-only.
+ </para>
+ <para>
+ Step 2 is the creation of the custom <literal>SRPVerifierStore</literal> interface implementation that knows how to obtain the <literal>VerifierInfo</literal> from the store you created in step 1. The <literal>verifyUserChallenge(String, Object)</literal> method of the interface is only called if the client <literal>SRPLoginModule</literal> configuration specifies the <literal>hasAuxChallenge</literal> option. This can be used to integrate existing hardware token based schemes like SafeWord or Radius into the SRP algorithm.
+ </para>
+ <para>
+ Step 3 is the creation of an MBean that makes the step 2 implementation of the <literal>SRPVerifierStore</literal> interface available via JNDI, and exposes any configurable parameters you need. In addition to the default <literal>org.jboss.security.srp.SRPVerifierStoreService</literal> example, the SRP example presented later in this chapter provides a Java properties file based <literal>SRPVerifierStore</literal> implementation. Between the two examples you should have enough to integrate your security store.
+ </para>
+ </example>
+ </section>
+ <section id="The_Secure_Remote_Password_SRP_Protocol-Inside_of_the_SRP_algorithm">
+ <title>Inside of the SRP algorithm</title>
+ <para>
+ The appeal of the SRP algorithm is that is allows for mutual authentication of client and server using simple text passwords without a secure communication channel. You might be wondering how this is done. If you want the complete details and theory behind the algorithm, refer to the SRP references mentioned in a note earlier. There are six steps that are performed to complete authentication:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ The client side <literal>SRPLoginModule</literal> retrieves the SRPServerInterface instance for the remote authentication server from the naming service.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client side <literal>SRPLoginModule</literal> next requests the SRP parameters associated with the username attempting the login. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. The <literal>getSRPParameters(username)</literal> call retrieves the SRP parameters for the given username.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client side <literal>SRPLoginModule</literal> begins an SRP session by creating an <literal>SRPClientSession</literal> object using the login username, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking the <literal>SRPServerInterface.init</literal> method and passes in the username and client generated random number <literal>A</literal>. The server returns its own random number <literal>B</literal>. This step corresponds to the exchange of public keys.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client side <literal>SRPLoginModule</literal> obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the login <literal>Subject</literal>. The server challenge response <literal>M2</literal> from step 4 is verified by invoking the <literal>SRPClientSession.verify</literal> method. If this succeeds, mutual authentication of the client to server, and server to client have been completed. The client side <literal>SRPLoginModule</literal> next creates a challenge <literal>M1</literal> to the server by invoking <literal>SRPClientSession.response</literal> method passing the server random number <literal>B</literal> as an argument. This challenge is sent to the server via the <literal>SRPServerInterface.verify</literal> method and server's response is saved as <literal>M2</literal>. This step corresponds to an exchange of challenges. At this point the server has verified t!
hat the user is who they say they are.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The client side <literal>SRPLoginModule</literal> saves the login username and <literal>M1</literal> challenge into the <literal>LoginModule</literal> sharedState map. This is used as the Principal name and credentials by the standard JBoss <literal>ClientLoginModule</literal>. The <literal>M1</literal> challenge is used in place of the password as proof of identity on any method invocations on J2EE components. The <literal>M1</literal> challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the <literal>SRPCacheLoginModule</literal>.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Although SRP has many interesting properties, it is still an evolving component in the JBossSX framework and has some limitations of which you should be aware. Issues of note include the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Because of how JBoss detaches the method transport protocol from the component container where authentication is performed, an unauthorized user could snoop the SRP <literal>M1</literal> challenge and effectively use the challenge to make requests as the associated username. Custom interceptors that encrypt the challenge using the SRP session key can be used to prevent this issue.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent J2EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout very long (up to 2,147,483,647 seconds, or approximately 68 years), or handle re-authentication in your code on failure.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ By default there can only be one SRP session for a given username. Because the negotiated SRP session produces a private session key that can be used for encryption/decryption between the client and server, the session is effectively a stateful one. JBoss supports for multiple SRP sessions per user, but you cannot encrypt data with one session key and then decrypt it with another.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ To use end-to-end SRP authentication for J2EE component calls, you need to configure the security domain under which the components are secured to use the <literal>org.jboss.security.srp.jaas.SRPCacheLoginModule</literal>. The <literal>SRPCacheLoginModule</literal> has a single configuration option named <literal>cacheJndiName</literal> that sets the JNDI location of the SRP authentication <literal>CachePolicy</literal> instance. This must correspond to the <literal>AuthenticationCacheJndiName</literal> attribute value of the <literal>SRPService</literal> MBean. The <literal>SRPCacheLoginModule</literal> authenticates user credentials by obtaining the client challenge from the <literal>SRPServerSession</literal> object in the authentication cache and comparing this to the challenge passed as the user credentials. <xref linkend="Inside_of_the_SRP_algorithm-A_sequence_diagram_illustrating_the_interaction_of_the_SRPCacheLoginModule_with_the_SRP_session_cache."/> illustrate!
s the operation of the SRPCacheLoginModule.login method implementation.
+ </para>
+ <figure id="Inside_of_the_SRP_algorithm-A_sequence_diagram_illustrating_the_interaction_of_the_SRPCacheLoginModule_with_the_SRP_session_cache.">
+ <title>A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/j2ee_chap8-14.jpg" align="center"/>
+ </imageobject>
+ </mediaobject>
+ </figure>
+ <section id="Inside_of_the_SRP_algorithm-An_SRP_example">
+ <title>An SRP example</title>
+ <para>
+ We have covered quite a bit of material on SRP and now its time to demonstrate SRP in practice with an example. The example demonstrates client side authentication of the user via SRP as well as subsequent secured access to a simple EJB using the SRP session challenge as the user credential. The test code deploys an EJB JAR that includes a SAR for the configuration of the server side login module configuration and SRP services. As in the previous examples we will dynamically install the server side login module configuration using the <literal>SecurityConfig</literal> MBean. In this example we also use a custom implementation of the <literal>SRPVerifierStore</literal> interface that uses an in memory store that is seeded from a Java properties file rather than a serialized object store as used by the <literal>SRPVerifierStoreService</literal>. This custom service is <literal>org.jboss.book.security.ex3.service.PropertiesVerifierStore</literal>. The following shows the !
contents of the JAR that contains the example EJB and SRP services.
+ </para>
+ <programlisting>[examples]$ jar tf output/security/security-ex3.jar
+META-INF/MANIFEST.MF
+META-INF/ejb-jar.xml
+META-INF/jboss.xml
+org/jboss/book/security/ex3/Echo.class
+org/jboss/book/security/ex3/EchoBean.class
+org/jboss/book/security/ex3/EchoHome.class
+roles.properties
+users.properties
+security-ex3.sar
+</programlisting>
+ <para>
+ The key SRP related items in this example are the SRP MBean services configuration, and the SRP login module configurations. The <literal>jboss-service.xml</literal> descriptor of the <literal>security-ex3.sar</literal> is given in <xref linkend="An_SRP_example-The_security_ex3.sar_jboss_service.xml_descriptor_for_the_SRP_services"/>, while <xref linkend="An_SRP_example-The_client_side_standard_JAAS_configuration"/> and <xref linkend="An_SRP_example-The_server_side_XMLLoginConfig_configuration"/> give the example client side and server side login module configurations.
+ </para>
+ <example id="An_SRP_example-The_security_ex3.sar_jboss_service.xml_descriptor_for_the_SRP_services">
+ <title>The security-ex3.sar jboss-service.xml descriptor for the SRP services</title>
+ <programlisting><server>
+ <!-- The custom JAAS login configuration that installs
+ a Configuration capable of dynamically updating the
+ config settings -->
+
+ <mbean code="org.jboss.book.security.service.SecurityConfig"
+ name="jboss.docs.security:service=LoginConfig-EX3">
+ <attribute name="AuthConfig">META-INF/login-config.xml</attribute>
+ <attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute>
+ </mbean>
+
+ <!-- The SRP service that provides the SRP RMI server and server side
+ authentication cache -->
+ <mbean code="org.jboss.security.srp.SRPService"
+ name="jboss.docs.security:service=SRPService">
+ <attribute name="VerifierSourceJndiName">srp-test/security-ex3</attribute>
+ <attribute name="JndiName">srp-test/SRPServerInterface</attribute>
+ <attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute>
+ <attribute name="ServerPort">0</attribute>
+ <depends>jboss.docs.security:service=PropertiesVerifierStore</depends>
+ </mbean>
+
+ <!-- The SRP store handler service that provides the user password verifier
+ information -->
+ <mbean code="org.jboss.security.ex3.service.PropertiesVerifierStore"
+ name="jboss.docs.security:service=PropertiesVerifierStore">
+ <attribute name="JndiName">srp-test/security-ex3</attribute>
+ </mbean>
+</server>
+</programlisting>
+ </example>
+ <example id="An_SRP_example-The_client_side_standard_JAAS_configuration">
+ <title>The client side standard JAAS configuration</title>
+ <programlisting>srp {
+ org.jboss.security.srp.jaas.SRPLoginModule required
+ srpServerJndiName="srp-test/SRPServerInterface"
+ ;
+
+ org.jboss.security.ClientLoginModule required
+ password-stacking="useFirstPass"
+ ;
+};
+</programlisting>
+ </example>
+ <example id="An_SRP_example-The_server_side_XMLLoginConfig_configuration">
+ <title>The server side XMLLoginConfig configuration</title>
+ <programlisting><application-policy name="security-ex3">
+ <authentication>
+ <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
+ flag = "required">
+ <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
+ </login-module>
+ <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
+ flag = "required">
+ <module-option name="password-stacking">useFirstPass</module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+</programlisting>
+ </example>
+ <para>
+ The example services are the <literal>ServiceConfig</literal> and the <literal>PropertiesVerifierStore</literal> and <literal>SRPService</literal> MBeans. Note that the <literal>JndiName</literal> attribute of the <literal>PropertiesVerifierStore</literal> is equal to the <literal>VerifierSourceJndiName</literal> attribute of the <literal>SRPService</literal>, and that the <literal>SRPService</literal> depends on the <literal>PropertiesVerifierStore</literal>. This is required because the <literal>SRPService</literal> needs an implementation of the <literal>SRPVerifierStore</literal> interface for accessing user password verification information.
+ </para>
+ <para>
+ The client side login module configuration makes use of the <literal>SRPLoginModule</literal> with a <literal>srpServerJndiName</literal> option value that corresponds to the JBoss server component <literal>SRPService</literal> JndiName attribute value(<literal>srp-test/SRPServerInterface</literal>). Also needed is the <literal>ClientLoginModule</literal> configured with the <literal>password-stacking="useFirstPass"</literal> value to propagate the user authentication credentials generated by the <literal>SRPLoginModule</literal> to the EJB invocation layer.
+ </para>
+ <para>
+ There are two issues to note about the server side login module configuration. First, note the <literal>cacheJndiName=srp-test/AuthenticationCache</literal> configuration option tells the <literal>SRPCacheLoginModule</literal> the location of the <literal>CachePolicy</literal> that contains the <literal>SRPServerSession</literal> for users who have authenticated against the <literal>SRPService</literal>. This value corresponds to the <literal>SRPService</literal><literal>AuthenticationCacheJndiName</literal> attribute value. Second, the configuration includes a <literal>UsersRolesLoginModule</literal> with the <literal>password-stacking=useFirstPass</literal> configuration option. It is required to use a second login module with the <literal>SRPCacheLoginModule</literal> because SRP is only an authentication technology. A second login module needs to be configured that accepts the authentication credentials validated by the <literal>SRPCacheLoginModule</literal> to set!
the principal's roles that determines the principal's permissions. The <literal>UsersRolesLoginModule</literal> is augmenting the SRP authentication with properties file based authorization. The user's roles are coming the <literal>roles.properties</literal> file included in the EJB JAR.
+ </para>
+ <para>
+ Now, run the example 3 client by executing the following command from the book examples directory:
+ </para>
+ <programlisting>[examples]$ ant -Dchap=security -Dex=3 run-example
+...
+run-example3:
+ [echo] Waiting for 5 seconds for deploy...
+ [java] Logging in using the 'srp' configuration
+ [java] Created Echo
+ [java] Echo.echo()#1 = This is call 1
+ [java] Echo.echo()#2 = This is call 2
+</programlisting>
+ <para>
+ In the <literal>examples/logs</literal> directory you will find a file called <literal>ex3-trace.log</literal>. This is a detailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key and verification.
+ </para>
+ <para>
+ Note that the client has taken a long time to run relative to the other simple examples. The reason for this is the construction of the client's public key. This involves the creation of a cryptographically strong random number, and this process takes quite a bit of time the first time it occurs. If you were to log out and log in again within the same VM, the process would be much faster. Also note that <literal>Echo.echo()#2</literal> fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the <literal>SRPService</literal> cache expiration. The <literal>SRPService</literal> cache policy timeout has been set to a mere 10 seconds to force this issue. As stated earlier, you need to make the cache timeout very long, or handle re-authentication on failure.
+ </para>
+ </section>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-Running_JBoss_with_a_Java_2_security_manager">
+ <title>Running JBoss with a Java 2 security manager</title>
+ <para>
+ By default the JBoss server does not start with a Java 2 security manager. If you want to restrict privileges of code using Java 2 permissions you need to configure the JBoss server to run under a security manager. This is done by configuring the Java VM options in the <literal>run.bat</literal> or <literal>run.sh</literal> scripts in the JBoss server distribution bin directory. The two required VM options are as follows:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.security.manager</emphasis>: This is used without any value to specify that the default security manager should be used. This is the preferred security manager. You can also pass a value to the <literal>java.security.manager</literal> option to specify a custom security manager implementation. The value must be the fully qualified class name of a subclass of <literal>java.lang.SecurityManager</literal>. This form specifies that the policy file should augment the default security policy as configured by the VM installation.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="bold">java.security.policy</emphasis>: This is used to specify the policy file that will augment the default security policy information for the VM. This option takes two forms: <literal>java.security.policy=policyFileURL</literal> and <literal>java.security.policy==policyFileURL</literal>. The first form specifies that the policy file should augment the default security policy as configured by the VM installation. The second form specifies that only the indicated policy file should be used. The <literal>policyFileURL</literal> value can be any URL for which a protocol handler exists, or a file path specification.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Both the <literal>run.bat</literal> and <literal>run.sh</literal> start scripts reference an JAVA_OPTS variable which you can use to set the security manager properties.
+ </para>
+ <para>
+ Enabling Java 2 security is the easy part. The difficult part of Java 2 security is establishing the allowed permissions. If you look at the <literal>server.policy</literal> file that is contained in the default configuration file set, you'll see that it contains the following permission grant statement:
+ </para>
+ <programlisting>grant {
+ // Allow everything for now
+ permission java.security.AllPermission;
+};
+</programlisting>
+ <para>
+ This effectively disables security permission checking for all code as it says any code can do anything, which is not a reasonable default. What is a reasonable set of permissions is entirely up to you.
+ </para>
+ <para>
+ The current set of JBoss specific <literal>java.lang.RuntimePermissions</literal> that are required include:
+ </para>
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry> TargetName </entry>
+ <entry> What the permission allows </entry>
+ <entry> Risks </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry> org.jboss.security.SecurityAssociation.getPrincipalInfo </entry>
+ <entry> Access to the org.jboss.security.SecurityAssociation getPrincipal() and getCredentials() methods. </entry>
+ <entry> The ability to see the current thread caller and credentials. </entry>
+ </row>
+ <row>
+ <entry> org.jboss.security.SecurityAssociation.setPrincipalInfo </entry>
+ <entry> Access to the org.jboss.security.SecurityAssociation setPrincipal() and setCredentials() methods. </entry>
+ <entry> The ability to set the current thread caller and credentials. </entry>
+ </row>
+ <row>
+ <entry> org.jboss.security.SecurityAssociation.setServer </entry>
+ <entry> Access to the org.jboss.security.SecurityAssociation setServer method. </entry>
+ <entry> The ability to enable or disable multithread storage of the caller principal and credential. </entry>
+ </row>
+ <row>
+ <entry> org.jboss.security.SecurityAssociation.setRunAsRole </entry>
+ <entry> Access to the org.jboss.security.SecurityAssociation pushRunAsRole and popRunAsRole methods. </entry>
+ <entry> The ability to change the current caller run-as role principal. </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ To conclude this discussion, here is a little-known tidbit on debugging security policy settings. There are various debugging flag that you can set to determine how the security manager is using your security policy file as well as what policy files are contributing permissions. Running the VM as follows shows the possible debugging flag settings:
+ </para>
+ <programlisting>[bin]$ java -Djava.security.debug=help
+
+all turn on all debugging
+access print all checkPermission results
+combiner SubjectDomainCombiner debugging
+jar jar verification
+logincontext login context results
+policy loading and granting
+provider security provider debugging
+scl permissions SecureClassLoader assigns
+
+The following can be used with access:
+
+stack include stack trace
+domain dumps all domains in context
+failure before throwing exception, dump stack
+ and domain that didn't have permission
+
+Note: Separate multiple options with a comma
+</programlisting>
+ <para>
+ Running with <literal>-Djava.security.debug=all</literal> provides the most output, but the output volume is torrential. This might be a good place to start if you don't understand a given security failure at all. A less verbose setting that helps debug permission failures is to use <literal>-Djava.security.debug=access,failure</literal>. This is still relatively verbose, but not nearly as bad as the all mode as the security domain information is only displayed on access failures.
+ </para>
+ </section>
+ <section id="Security_on_JBoss-Using_SSL_with_JBoss_using_JSSE">
+ <title>Using SSL with JBoss</title>
+ <section id="Adding_SSL_to_EJB3">
+ <title>Adding SSL to EJB3</title>
+ <para>
+ By default JBoss EJB3 uses a socket based invoker layer on port 3878. This is set up in <filename> $JBOSS_HOME/server/<replaceable><serverconfig></replaceable>/deploy/ejb3.deployer/META-INF/jboss-service.xml</filename>. In some cases you may wish to use SSL as the protocol. In order to do this you must generate a keystore and then configure your beans to use SSL transport.
+ </para>
+ <section id="Adding_SSL_to_EJB3_Generating_the_keystore_and_truststore">
+ <title>Generating the keystore and truststore</title>
+ <para>
+ For SSL to work you need to create a public/private key pair, which will be stored in a keystore. Generate this using the <literal>genkey</literal> command that comes with the JDK.
+<programlisting>
+ $cd $JBOSS_HOME/server/production/conf/
+ $keytool -genkey -alias ejb3-ssl -keypass opensource -keystore localhost.keystore
+ Enter keystore password: opensource
+ What is your first and last name?
+ [Unknown]:
+ What is the name of your organizational unit?
+ [Unknown]:
+ What is the name of your organization?
+ [Unknown]:
+ What is the name of your City or Locality?
+ [Unknown]:
+ What is the name of your State or Province?
+ [Unknown]:
+ What is the two-letter country code for this unit?
+ [Unknown]:
+ Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
+ [no]: yes
+</programlisting>
+ where <literal>alias</literal> is the name ("ejb2-ssl") of the key pair within the keystore. <literal>keypass</literal> is the password ("opensource") for the keystore, and <literal>keystore</literal> specifies the location ("localhost.keystore") of the keystore to create/add to.
+ </para>
+ <para>
+ Since you have not signed our certificate through any certification authoritiy, you also need to create a truststore for the client, explicitly saying that you trust the certificate you just created. The first step is to export the certificate using the JDK keytool:
+<programlisting>
+ $ keytool -export -alias ejb3-ssl -file mycert.cer -keystore localhost.keystore
+ Enter keystore password: opensource
+ Certificate stored in file <mycert.cer>
+</programlisting>
+ </para>
+ <para>
+ Then you need to create the truststore if it does not exist and import the certificate into the trueststore:
+<programlisting>
+ $ keytool -import -alias ejb3-ssl -file mycert.cer -keystore localhost.truststore
+ Enter keystore password: opensource
+ Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
+ Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
+ Serial number: 43bff927
+ Valid from: Sat Jan 07 18:23:51 CET 2006 until: Fri Apr 07 19:23:51 CEST 2006
+ Certificate fingerprints:
+ MD5: CF:DC:71:A8:F4:EA:8F:5A:E9:94:E3:E6:5B:A9:C8:F3
+ SHA1: 0E:AD:F3:D6:41:5E:F6:84:9A:D1:54:3D:DE:A9:B2:01:28:F6:7C:26
+ Trust this certificate? [no]: yes
+ Certificate was added to keystore
+</programlisting>
+ </para>
+ </section>
+ <section>
+ <title id="Adding_SSL_to_EJB3_Setting_up_the_SSL_transport">Setting up the SSL transport</title>
+ <para>
+ The simplest way to define an SSL transport is to define a new Remoting connector using the <literal>sslsocket</literal> protocol as follows. This transport will listen on port 3843:
+<programlisting>
+ <mbean code="org.jboss.remoting.transport.Connector"
+ xmbean-dd="org/jboss/remoting/transport/Connector.xml"
+ name="jboss.remoting:type=Connector,transport=socket3843,handler=ejb3">
+ <depends>jboss.aop:service=AspectDeployer</depends>
+ <attribute name="InvokerLocator">sslsocket://0.0.0.0:3843</attribute>
+ <attribute name="Configuration">
+ <handlers>
+ <handler subsystem="AOP">
+ org.jboss.aspects.remoting.AOPRemotingInvocationHandler
+ </handler>
+ </handlers>
+ </attribute>
+ </mbean>
+</programlisting>
+ </para>
+ <para>
+ Now you need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using <literal>javax.net.ssl.keyStore</literal> and <literal>javax.net.ssl.keyStorePassword=opensource</literal> system properties when starting JBoss, as the following example shows:
+<programlisting>
+ $cd $JBOSS_HOME/bin
+ $ run -Djavax.net.ssl.keyStore=../server/production/conf/localhost.keystore
+ -Djavax.net.ssl.keyStorePassword=opensource
+</programlisting>
+ </para>
+ </section>
+ <section id="Adding_SSL_to_EJB3_Configuring_your_beans">
+ <title>Configuring your beans to use the SSL transport</title>
+ <para>
+ By default all the beans will use the default connector on <literal>socket://0.0.0.0:3873</literal>. By using the <literal>@org.jboss.annotation.ejb.RemoteBinding</literal> annotation you can have the bean invokable via SSL.
+<programlisting>
+ @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
+ @Remote(BusinessInterface.class)
+ public class StatefulBean implements BusinessInterface
+ {
+ ...
+ }
+</programlisting>
+ </para>
+ <para>
+ This bean will be bound under the JNDI name <literal>StatefulSSL</literal> and the proxy implementing the remote interface returned to the client will communicate with the server via SSL.
+ </para>
+ <para>
+ You can also enable different types of communication for your beans
+<programlisting>
+ @RemoteBindings({
+ @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL"),
+ @RemoteBinding(jndiBinding="StatefulNormal")
+ })
+ @Remote(BusinessInterface.class)
+ public class StatefulBean implements BusinessInterface
+ {
+ ...
+ }
+</programlisting>
+ </para>
+ <para>
+ Now if you look up <literal>StatefulNormal</literal> the returned proxy implementing the remote interface will communicate with the server via the normal unencrypted socket protocol, and if you look up <literal>StatefulSSL</literal> the returned proxy implementing the remote interface will communicate with the server via SSL.
+ </para>
+ </section>
+ <section id="Adding_SSL_to_EJB3_Setting_up_the_client_to_use_truststore">
+ <title>Setting up the client to use the truststore</title>
+ <para>
+If not using a certificate signed by a certificate authorization authority, you need to point the client to the truststore using the <literal>javax.net.ssl.trustStore</literal> system property and specify the password using the <literal>javax.net.ssl.trustStorePassword</literal> system property:
+<programlisting>
+java -Djavax.net.ssl.trustStore=${resources}/test/ssl/localhost.truststore
+ -Djavax.net.ssl.trustStorePassword=opensource com.acme.RunClient
+</programlisting>
+ </para>
+ </section>
+ </section>
+ <section id="Adding_SSL_to_EJB2.1">
+ <title>Adding SSL to EJB 2.1 calls</title>
+ <section id="Adding_SSL_to_EJB2.1_Generating_the_keystore_and_truststore">
+ <title>Generating the keystore and truststore</title>
+ <para>
+ This is similar to the steps described for Adding SSL to EJB3 calls.
+ </para>
+ </section>
+ <section id="Adding_SSL_to_EJB2.1_Setting_up_the_SSL_transport">
+ <title>Setting up the SSL transport</title>
+ <para>
+Now you need to tell JBoss Remoting where to find the keystore to be used for SSl and its password. This is done using <literal>javax.net.ssl.keyStore</literal> and <literal>javax.net.ssl.keyStorePassword=opensource</literal> system properties when starting JBoss, as the following example shows:
+<programlisting>
+ $cd $JBOSS_HOME/bin
+ $ run -Djavax.net.ssl.keyStore=../server/production/conf/localhost.keystore
+ -Djavax.net.ssl.keyStorePassword=opensource
+</programlisting>
+ </para>
+ <para>
+ If you wish to customize the SSLSocketBuilder you need to add the following to your <literal>$JBOSS_HOME/server/${serverConf}/conf/jboss-service.xml</literal> file.
+<programlisting>
+ <!-- This section is for custom (SSL) server socket factory -->
+ <mbean code="org.jboss.remoting.security.SSLSocketBuilder"
+ name="jboss.remoting:service=SocketBuilder,type=SSL"
+ display-name="SSL Server Socket Factory Builder">
+ <!-- IMPORTANT - If making ANY customizations, this MUST be set to false. -->
+ <!-- Otherwise, will used default settings and the following attributes will be ignored. -->
+ <attribute name="UseSSLServerSocketFactory">false</attribute>
+ <!-- This is the url string to the key store to use -->
+ <attribute name="KeyStoreURL">localhost.keystore</attribute>
+ <!-- The password for the key store -->
+ <attribute name="KeyStorePassword">sslsocket</attribute>
+ <!-- The password for the keys (will use KeystorePassword if this is not set explicitly. -->
+ <attribute name="KeyPassword">sslsocket</attribute>
+ <!-- The protocol for the SSLContext. Default is TLS. -->
+ <attribute name="SecureSocketProtocol">TLS</attribute>
+ <!-- The algorithm for the key manager factory. Default is SunX509. -->
+ <attribute name="KeyManagementAlgorithm">SunX509</attribute>
+ <!-- The type to be used for the key store. -->
+ <!-- Defaults to JKS. Some acceptable values are JKS (Java Keystore - Sun's keystore format), -->
+ <!-- JCEKS (Java Cryptography Extension keystore - More secure version of JKS), and -->
+ <!-- PKCS12 (Public-Key Cryptography Standards #12
+ keystore - RSA's Personal Information Exchange Syntax Standard). -->
+ <!-- These are not case sensitive. -->
+ <attribute name="KeyStoreType">JKS</attribute>
+ </mbean>
+</programlisting>
+<programlisting>
+<mbean code="org.jboss.remoting.security.SSLServerSocketFactoryService"
+ name="jboss.remoting:service=ServerSocketFactory,type=SSL"
+ display-name="SSL Server Socket Factory">
+ <depends optional-attribute-name="SSLSocketBuilder"
+ proxy-type="attribute">jboss.remoting:service=SocketBuilder,type=SSL</depends>
+ </mbean>
+</programlisting>
+ </para>
+ </section>
+ <section id="Adding_SSL_to_EJB2.1_configuring_your_beans">
+ <title>Configuring your beans to use the SSL transport</title>
+ <para>
+ In your <literal>$JBOSS_HOME/server/${serverConf}/conf/jboss-service.xml</literal> file, comment out the following lines:
+<programlisting>
+<mbean code="org.jboss.remoting.transport.Connector"
+ name="jboss.remoting:service=Connector,transport=socket"
+ display-name="Socket transport Connector">
+
+ <!-- Can either just specify the InvokerLocator attribute and not the invoker element in the -->
+ <!-- Configuration attribute, or do the full invoker configuration in the in invoker element -->
+ <!-- of the Configuration attribute. -->
+
+ <!-- Remember that if you do use more than one param on the uri, will have to include as a CDATA, -->
+ <!-- otherwise, parser will complain. -->
+ <!--
+ <attribute name="InvokerLocator">
+ <![CDATA[socket://${jboss.bind.address}:4446/?datatype=invocation]]>
+ </attribute>
+ -->
+
+ <attribute name="Configuration">
+ <!-- Using the following
+ <invoker>
+ element instead of the InvokerLocator above because specific attributes needed.
+ -->
+ <!-- If wanted to use any of the parameters below, can
+ just add them as parameters to the url above if wanted use
+ the InvokerLocator attribute. -->
+ <config>
+ <!-- Other than transport type and handler, none of these configurations are required
+ (will just use defaults). -->
+ <invoker transport="socket">
+ <attribute name="dataType" isParam="true">invocation</attribute>
+ <attribute name="marshaller"
+ isParam="true">org.jboss.invocation.unified.marshall.InvocationMarshaller</attribute>
+ <attribute name="unmarshaller"
+ isParam="true">org.jboss.invocation.unified.marshall.InvocationUnMarshaller</attribute>
+ <!-- This will be port on which the marshall loader port runs on. -->
+ <!-- <attribute name="loaderport" isParam="true">4447</attribute> -->
+ <!-- The following are specific to socket invoker -->
+ <!-- <attribute name="numAcceptThreads">1</attribute>-->
+ <!-- <attribute name="maxPoolSize">303</attribute>-->
+ <!-- <attribute name="clientMaxPoolSize" isParam="true">304</attribute>-->
+ <attribute name="socketTimeout" isParam="true">600000</attribute>
+ <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
+ <attribute name="serverBindPort">4446</attribute>
+ <!-- <attribute name="clientConnectAddress">216.23.33.2</attribute> -->
+ <!-- <attribute name="clientConnectPort">7777</attribute> -->
+ <attribute name="enableTcpNoDelay" isParam="true">true</attribute>
+ <!-- <attribute name="backlog">200</attribute>-->
+ <!-- The following is for callback configuration and is independant of invoker type -->
+ <!-- <attribute name="callbackMemCeiling">30</attribute>-->
+ <!-- indicates callback store by fully qualified class name -->
+ <!-- <attribute name="callbackStore">org.jboss.remoting.CallbackStore</attribute>-->
+ <!-- indicates callback store by object name -->
+ <!--
+ <attribute name="callbackStore">
+ jboss.remoting:service=CallbackStore,type=Serializable
+ </attribute>
+ -->
+ <!-- config params for callback store. if were declaring callback store via object name, -->
+ <!-- could have specified these config params there. -->
+ <!-- StoreFilePath indicates to which directory to write the callback objects. -->
+ <!-- The default value is the property value of 'jboss.server.data.dir' and
+ if this is not set, -->
+ <!-- then will be 'data'. Will then append 'remoting' and the callback client's session id. -->
+ <!-- An example would be 'data\remoting\5c4o05l-9jijyx-e5b6xyph-1-e5b6xyph-2'. -->
+ <!-- <attribute name="StoreFilePath">callback</attribute>-->
+ <!-- StoreFileSuffix indicates the file suffix to use
+ for the callback objects written to disk. -->
+ <!-- The default value for file suffix is 'ser'. -->
+ <!-- <attribute name="StoreFileSuffix">cst</attribute>-->
+ </invoker>
+
+ <!-- At least one handler is required by the connector. If have more than one, must decalre -->
+ <!-- different subsystem values. Otherwise, all invocations will be routed to the only one -->
+ <!-- that is declared. -->
+ <handlers>
+ <!-- can also specify handler by fully qualified classname -->
+ <handler subsystem="invoker">jboss:service=invoker,type=unified</handler>
+ </handlers>
+ </config>
+ </attribute>
+ <depends>jboss.remoting:service=NetworkRegistry</depends>
+ </mbean>
+</programlisting>
+ and add the following in it's place:
+<programlisting>
+ <mbean code="org.jboss.remoting.transport.Connector"
+ xmbean-dd="org/jboss/remoting/transport/Connector.xml"
+ name="jboss.remoting:service=Connector,transport=sslsocket">
+ display-name="SSL Socket transport Connector">
+
+ <attribute name="Configuration">
+ <config>
+ <invoker transport="sslsocket">
+ <attribute name="serverSocketFactory">
+ jboss.remoting:service=ServerSocketFactory,type=SSL
+ </attribute>
+ <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
+ <attribute name="serverBindPort">3843</attribute>
+ </invoker>
+ <handlers>
+ <handler subsystem="invoker">jboss:service=invoker,type=unified</handler>
+ </handlers>
+ </config>
+ </attribute>
+ <!--If you specify the keystore and password in the command line and you're
+ not using the custom ServerSocketFactory, you should take out the following line-->
+ <depends>jboss.remoting:service=ServerSocketFactory,type=SSL</depends>
+ <depends>jboss.remoting:service=NetworkRegistry</depends>
+ </mbean>
+</programlisting>
+ </para>
+ </section>
+ <section id="Adding_SSL_to_EJB2.1_Setting_up_the_client_to_use_truststore">
+ <title>Setting up the client to use the truststore</title>
+ <para>
+ This is similar to the steps described for EJB3.
+ </para>
+ </section>
+ </section>
+ </section>
+ <section id="Security_on_JBoss-Configuring_JBoss_for_use_Behind_a_Firewall">
+ <title>Configuring JBoss for use Behind a Firewall</title>
+ <para>
+ JBoss comes with many socket based services that open listening ports. In this section we list the services that open ports that might need to be configured to work when accessing JBoss behind a firewall. The following table shows the ports, socket type, associated service for the services in the default configuration file set. <xref linkend="Configuring_JBoss_for_use_Behind_a_Firewall-Additional_ports_in_the_all_configuration"/> shows the same information for the additional ports that exist in the all configuration file set.
+ </para>
+ <table id="Configuring_JBoss_for_use_Behind_a_Firewall-The_ports_found_in_the_default_configuration">
+ <title>The ports found in the default configuration</title>
+ <tgroup cols="3">
+ <colspec colname="c1" colnum="1" colwidth=".25*"/>
+ <colspec colname="c2" colnum="2" colwidth=".25*"/>
+ <colspec colname="c3" colnum="3" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry> Port </entry>
+ <entry> Type </entry>
+ <entry> Service </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry> 1098 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.naming.NamingService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 1099 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.naming.NamingService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 4444 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.invocation.jrmp.server.JRMPInvoker</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 4445 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.invocation.pooled.server.PooledInvoker</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 8009 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.web.tomcat.tc4.EmbeddedTomcatService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 8080 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.web.tomcat.tc4.EmbeddedTomcatService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 8083 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.web.WebService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 8093 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.mq.il.uil2.UILServerILService</literal>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <table id="Configuring_JBoss_for_use_Behind_a_Firewall-Additional_ports_in_the_all_configuration">
+ <title>Additional ports in the all configuration</title>
+ <tgroup cols="3">
+ <colspec colname="c1" colnum="1" colwidth=".25*"/>
+ <colspec colname="c2" colnum="2" colwidth=".25*"/>
+ <colspec colname="c3" colnum="3" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry> Port </entry>
+ <entry> Type </entry>
+ <entry> Service </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry> 1100 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.ha.jndi.HANamingService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 1101 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.ha.jndi.HANamingService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 1102 </entry>
+ <entry> UDP </entry>
+ <entry>
+ <literal>org.jboss.ha.jndi.HANamingService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 1161 </entry>
+ <entry> UDP </entry>
+ <entry>
+ <literal>org.jboss.jmx.adaptor.snmp.agent.SnmpAgentService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 1162 </entry>
+ <entry> UDP </entry>
+ <entry>
+ <literal>org.jboss.jmx.adaptor.snmp.trapd.TrapdService</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 3528 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.invocation.iiop.IIOPInvoker</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 4447 </entry>
+ <entry> TCP </entry>
+ <entry>
+ <literal>org.jboss.invocation.jrmp.server.JRMPInvokerHA</literal>
+ </entry>
+ </row>
+ <row>
+ <entry> 45566<footnote>
+ <para>
+ Plus two additional anonymous UDP ports, one can be set using the <literal>rcv_port</literal>, and the other cannot be set.
+ </para>
+ </footnote></entry>
+ <entry> UDP </entry>
+ <entry>
+ <literal>org.jboss.ha.framework.server.ClusterPartition</literal>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ <section id="Security_on_JBoss-How_to_Secure_the_JBoss_Server">
+ <title>How to Secure the JBoss Server</title>
+ <para>
+ JBoss comes with several admin access points that need to be secured or removed to prevent unauthorized access to administrative functions in a deployment. This section describes the various admin services and how to secure them.
+ </para>
+ <section id="How_to_Secure_the_JBoss_Server-The_JMX_Console">
+ <title>The JMX Console</title>
+ <para>
+ The <literal>jmx-console.war</literal> found in the deploy directory provides an html view into the JMX microkernel. As such, it provides access to arbitrary admin type access like shutting down the server, stopping services, deploying new services, etc. It should either be secured like any other web application, or removed.
+ </para>
+ </section>
+ <section id="How_to_Secure_the_JBoss_Server-The_Web_Console">
+ <title>The Web Console</title>
+ <para>
+ The <literal>web-console.war</literal> found in the <literal>deploy/management</literal> directory is another web application view into the JMX microkernel. This uses a combination of an applet and a HTML view and provides the same level of access to admin functionality as the <literal>jmx-console.war</literal>. As such, it should either be secured or removed. The <literal>web-console.war</literal> contains commented out templates for basic security in its <literal>WEB-INF/web.xml</literal> as well as commented out setup for a security domain in <literal>WEB-INF/jboss-web.xml</literal>.
+ </para>
+ </section>
+ <section id="How_to_Secure_the_JBoss_Server-The_HTTP_Invokers">
+ <title>The HTTP Invokers</title>
+ <para>
+ The <literal>http-invoker.sar</literal> found in the deploy directory is a service that provides RMI/HTTP access for EJBs and the JNDI <literal>Naming</literal> service. This includes a servlet that processes posts of marshalled <literal>org.jboss.invocation.Invocation</literal> objects that represent invocations that should be dispatched onto the <literal>MBeanServer</literal>. Effectively this allows access to MBeans that support the detached invoker operation via HTTP since one could figure out how to format an appropriate HTTP post. To security this access point you would need to secure the <literal>JMXInvokerServlet</literal> servlet found in the <literal>http-invoker.sar/invoker.war/WEB-INF/web.xml</literal> descriptor. There is a secure mapping defined for the <literal>/restricted/JMXInvokerServlet</literal> path by default, one would simply have to remove the other paths and configure the <literal>http-invoker</literal> security domain setup in the <literal>http!
-invoker.sar/invoker.war/WEB-INF/jboss-web.xml</literal> descriptor.
+ </para>
+ </section>
+ <section id="How_to_Secure_the_JBoss_Server-The_JMX_Invoker">
+ <title>The JMX Invoker</title>
+ <para>
+ The <literal>jmx-invoker-adaptor-server.sar</literal> is a service that exposes the JMX MBeanServer interface via an RMI compatible interface using the RMI/JRMP detached invoker service. The only way for this service to be secured currently would be to switch the protocol to RMI/HTTP and secure the <literal>http-invoker.sar</literal> as described in the previous section. In the future this service will be deployed as an XMBean with a security interceptor that supports role based access checks.
+ </para>
+ </section>
+ </section>
+</chapter>
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample (from rev 101059, projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample)
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample (rev 0)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_AUDIT_Appender.xml_sample 2010-02-22 06:09:11 UTC (rev 101228)
@@ -0,0 +1,33 @@
+
+...
+<!-- Emit events as JMX notifications
+<appender name="JMX" class="org.jboss.monitor.services.JMXNotificationAppender">
+ <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
+ <param name="Threshold" value="WARN"/>
+ <param name="ObjectName" value="jboss.system:service=Logging,type=JMXNotificationAppender"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %-5p [%c] %m"/>
+ </layout>
+</appender>
+-->
+
+<!-- Security AUDIT Appender -->
+<appender name="AUDIT" class="org.jboss.logging.appender.DailyRollingFileAppender">
+ <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
+ <param name="File" value="${jboss.server.log.dir}/audit.log"/>
+ <param name="Append" value="true"/>
+ <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %-5p [%c] (%t:%x) %m%n"/>
+ </layout>
+</appender>
+
+ <!-- ================ -->
+ <!-- Limit categories -->
+ <!-- ================ -->
+
+<!-- Limit the org.apache category to INFO as its DEBUG is verbose -->
+<category name="org.apache">
+ <priority value="INFO"/>
+</category>
+...
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample (from rev 101059, projects/docs/enterprise/5.1/JBoss_Security_Chapter/en-US/extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample)
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample (rev 0)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/en-US/extras/jboss-log4j-Security_Audit_Provider_Category.xml_sample 2010-02-22 06:09:11 UTC (rev 101228)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Limit the verbose MC4J EMS (lib used by admin-console) categories -->
+<category name="org.mc4j.ems">
+ <priority value="WARN"/>
+</category>
+
+<!-- Show the evolution of the DataSource pool in the logs [inUse/Available/Max]
+<category name="org.jboss.resource.connectionmanager.JBossManagedConnectionPool">
+ <priority value="TRACE"/>
+</category>
+ -->
+
+<!-- Category specifically for Security Audit Provider -->
+<category name="org.jboss.security.audit.providers.LogAuditProvider" additivity="false">
+<priority value="TRACE"/>
+ <appender-ref ref="AUDIT"/>
+</category>
+
+
+<!-- Limit the org.jboss.serial (jboss-serialization) to INFO as its DEBUG is verbose -->
+<category name="org.jboss.serial">
+ <priority value="INFO"/>
+</category>
+
Deleted: projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Chapter/publican.cfg 2010-02-17 06:01:22 UTC (rev 101059)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg 2010-02-22 06:09:11 UTC (rev 101228)
@@ -1,7 +0,0 @@
-# Config::Simple 4.59
-# Mon Feb 1 13:32:40 2010
-
-xml_lang: en-US
-type: Book
-brand: JBoss
-
Copied: projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg (from rev 101058, projects/docs/enterprise/5.1/JBoss_Security_Chapter/publican.cfg)
===================================================================
--- projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg (rev 0)
+++ projects/docs/enterprise/5.1/JBoss_Security_Guide/publican.cfg 2010-02-22 06:09:11 UTC (rev 101228)
@@ -0,0 +1,7 @@
+# Config::Simple 4.59
+# Mon Feb 1 13:32:40 2010
+
+xml_lang: en-US
+type: Book
+brand: JBoss
+
More information about the jboss-cvs-commits
mailing list