| Geronimo_MoinMoin_wiki > Security |
This page is an extremely incomplete discussion of security configuration in Geronimo, present and future.
Note that "present" is as of late October 2005, post M5.
(see also JettyHttpsConfiguration for info on configuring Jetty to support ssl/https)
Security Realm: This is what most app servers would consider to be a security realm. It has a name, and a set of back-end stuff that makes authentication work. It can do auditing and lockout and so on. As it happens, under the covers, it uses a series of Login Modules to make this work.
Login Module: A JAAS LoginModule, which is a portable API for security services. In theory any login module should work with any product; however, some of the ones we ship with Geronimo take advantage of Geronimo-specific features and wouldn't really work elsewhere. Still, any portable JAAS login module developed elsewhere will run fine in Geronimo. A Login Module may represent a back-end Login Domain, or it might just enforce a policy (such as auditing every login attempt). It's up to you to arrange the login modules (order and control flags) in the Security Realm to get the desired effect.
Login Domain: What your network administrator might consider to be a security realm – Active Directory, LDAP, a SQL database with security information, a Netegrity or RSA product, etc. A valid source of authentication information (typically, users and groups). When you successfully log in to a login domain, you get a set of Principals that identify you (usually one of type user and several of type group, though any type of Principal is possible). The way for a Geronimo application to interact with a Login Domain is to configure a Login Module for that Login Domain, and then stuff the Login Module into a Security Realm.
Principal: Something that a Login Domain (via a LoginModule) uses to identify you. Implements java.security.Principal. Every Login Domain may use different Principal types. So when you go to map users to J2EE roles, you need to say which Principal class / Principal name combinations map to each role – the equivalent of "user Bob" or "group Developers" should be in a role. You should also say which Login Domain this applies to, so if there were 2 different LDAP servers, you could say "user Bob from the Finance LDAP server and group Developers from the Engineering LDAP server" should be in a role. However, that's not presently implemented correctly.
Control Flag: There are 4 possible control flags for a login module, and they indicate what should happen in the overall login process if a particular login module succeeds or fails. For the specific options and what they mean, see http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html
Subject: In JAAS, every user is represented by a Subject. The Subject holds a collection of all the Principals for the user. It may also hold credentials such as the password or certificate used to log in. When a user logs in to Geronimo, the server gets a fully-populated Subject for the user. The client side of this transaction only gets a partially populated Subject, but it's enough to identify the user to the server so the server can use it's fully-populated Subject for anything it needs to do.
!DomainPrincipal
: For every principal generated by a login domain, Geronimo may create a matching DomainPrincipal principal that includes both the original principal and the login domain name.
!RealmPrincipal
: For every principal generated by a login domain within a realm, Geronimo may create a matching RealmPrincipal principal that includes the DomainPrincipal
and the realm name.
The j2ee declarative security model is based on roles, whereas the JAAS login model is based on principals. We need to map the principals to roles to determine if a particular user has a particular permission. This principal-role mapping is described in a security element in a geronimo j2ee plan. For each role, the principals that map to it are specified. These can be plain unwrapped principals direct from a login module, or domain or realm principals that include the login domain name and the realm name respectively. Most simple geronimo deployments can use the plain unwrapped principals. You should consider using the wrapped domain principals if you have 2 or more login domains that return the same principal class and name but the origin of the principal is needed to determine permissions. For instance, you might have 2 LDAP systems with the same group names, but with different meanings. Labeling the principals with the login domain will enable geronimo to distinguish which LDAP system was used to authenticate the user. A further level of control is supplied by using the RealmPrincipal
, which also includes the realm name. This enables geronimo to distinguish between uses of the same login module in two realms. One possible use of this might be if one realm contains additional or different login modules.
Here's an example of a security realm with 2 login modules, that produces only plain unwrapped principals:
<gbean name="client-properties-realm"
class="org.apache.geronimo.security.realm.GenericSecurityRealm">
<attribute name="realmName">client-properties-realm</attribute>
<xml-reference name="LoginModuleConfiguration">
<lc:login-config xmlns:lc="http://geronimo.apache.org/xml/ns/loginconfig">
<lc:login-module control-flag="REQUIRED" server-side="true">
<lc:login-domain-name>client-properties-realm</lc:login-domain-name>
<lc:login-module-class>org.apache.geronimo.security.realm.providers.PropertiesFileLoginModule</lc:login-module-class>
<lc:option name="usersURI">var/security/users.properties</lc:option>
<lc:option name="groupsURI">var/security/groups.properties</lc:option>
</lc:login-module>
<lc:login-module control-flag="REQUIRED" server-side="true">
<lc:login-domain-name>default</lc:login-domain-name>
<lc:login-module-class>org.apache.geronimo.security.jaas.NamedUPCredentialLoginModule</lc:login-module-class>
<lc:option name="org.apache.geronimo.jaas.NamedUPCredentialLoginModule.Name">default</lc:option>
</lc:login-module>
</lc:login-config>
</xml-reference>
<reference name="ServerInfo">
<module>org/apache/geronimo/System</module>
<name>ServerInfo</name>
</reference>
<reference name="LoginService">
<name>JaasLoginService</name>
</reference>
</gbean>
In this example we configure a PropertiesFileLoginModule (which loads users and groups from separate files), and a credential populator (which stores a user's credentials in the Subject). The properties file module takes options indicating where to find the properties files, while the credential populator includes the domain name of the credential to be created. The properties file module represents a login domain (with a loginDomainName), while the credential populator doesn't (it doesn't generate any principals). The security realm configuration declares both login modules as REQUIRED.
Note 1: The first module must be REQUIRED or OPTIONAL if you always want the second module to be executed (for example, for an auditing module that should audit login failures too).
Note 2: If you need to use DomainPrincipals
or RealmPrincipals
to distinguish principals of the same class and name, you should supply a domain name for your login module.
The LoginService component manages security realms and logins. However, it's a bit painful to deal with directly, so we provide a handy helper class.
The JaasLoginCoordinator does the dirty work of dealing with the LoginService on your behalf. The JaasLoginCoordinator is itself a LoginModule, so you think you're dealing with one single LoginModule, where under the covers it's interacting with the LoginService and a security realm that may be configured with an arbitrarily complex set of login modules.
Each security realm automatically has a JaasLoginCoordinator registered under the same name as the security realm name. If you can just use that, then no further configuration is necessary.
Otherwise, to set up a configuration with a different name than the realm name, you usually create a ServerRealmConfigurationEntry GBean, where you give it the name of the realm you want to work with, and the name you plan to use to identify it when you try to log in (which must be different than the realm name so as not to conflict with the automatic mapping above). You might give it the realm name "foo-realm" and the configuration name "foo-client". Then when you try to login to "foo-client", under the covers, it will log you in using all the login modules configured for the security realm "foo-realm". A typical configuration looks like this:
<gbean name="geronimo.security:type=ConfigurationEntry,jaasId=foo-client"
class="org.apache.geronimo.security.jaas.ServerRealmConfigurationEntry">
<attribute name="applicationConfigName" type="java.lang.String">foo-client</attribute>
<attribute name="realmName" type="java.lang.String">foo-realm</attribute>
</gbean>
Note that a the Subject returned from a successfuly login in this fashion will be a limited client-side Subject (because you're acting as a client of the LoginService). This gets all the principals generated by the server-side login modules, but not any of the RealmPrincipal}}s generated by Geronimo itself and used for role mapping / authorization by Geronimo. To turn the limited client-side Subject into a full server-side Subject, you can call {{ContextManager.getServerSideSubject(clientSideSubject).
The JMX remoting implementation looks for a configuration entry called "JMX". You can either create a security realm with that name, or (more likely) add a ServerRealmConfigurationEntry mapping "JMX" to some security realm name.
EJB containers don't need to invoke the JaasLoginCoordinator, because the client will always log in before invoking the EJB container. A web client is authenticated by the web container using the web container's configured security realm, and an application client is authenticated by some security realm specified on the client side before connecting to the EJB container. In other words, the EJB container always receives a Subject/Principals previously prepared, it never gets a username and password that it needs to validate itself. It still needs to handle role mapping, and authorization against the current Subject, however.
Connectors are similar to EJB in that the caller should have authenticated already. However, the connector might need to map the previous principals into something the conector can use (e.g. application user "ammulder" should log in to Oracle or SAP as "muldera" with a different password, or whatever). This is only relevant for container-managed authentication, but that is relatively popular. Currently the strategy for this is to use a realm bridge, though that might be adjusted in the future (to just add secondary login modules that provide connector-specific Principals at the normal login time).
This is pretty much the same, only you need to manually configure the client to use a JaasLoginCoordinator, and give it the realm name and server host/port as options. Typically, you'd use a JAAS configuration file to do this, with an entry like this:
my-app {
org.apache.geronimo.security.jaas.JaasLoginCoordinator required
host="localhost"
port="4242"
realm="my-realm";
};
In this case, the configuration name can be the same as the realm name, because the coordinator configuration runs on the client side and the realm configuration runs on the server side. Still, it might be easier to make them different, so the configuration name identifies the application while the realm name identifies the security realm, as in the example above.
There are a number of to-dos in the security area: