Geronimo_MoinMoin_wiki > Security
Added by Confluence Administrator, last edited by Confluence Administrator on Aug 02, 2006

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 Concepts

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.

Authorization

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.

Current State

Configuring LoginModules and Security Realms

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.

Configuring Server Components to Talk to Security Realms

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).

Where This is Used

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).

Configuring Clients to Talk to Security Realms

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.

Future Changes

There are a number of to-dos in the security area:

  • We need to provide more login modules, including:
    • One that rejects logins for a user after X unsuccessful attempts (in a row or in Y minutes)
    • One that validates against an LDAP login domain
    • One that validates client certificates against a particular certificate authority
  • The SQLLoginModule needs to be updated to execute user-specific queries instead of loading the entire list of users and groups every time
  • Role mapping needs to change to support login domain names
    • The mapping should go by login domain name, principal class, and principal name
    • You should be able to specify more than one default principal; for example, you might want the default (unauthenticated) subject to get one user principal and two group principals
  • Perhaps enforce rules about when loginDomainName should be set in the LoginModuleGBean doStart method, or something like that.
  • Auto-mapping of principals to groups needs to be enhanced (configured per login domain, etc.)
  • Maybe automatically return the server-side Subject for server-side usage of JaasLoginCoordinator
  • Replace the static registration with GeronimoLoginConfiguration with an IOC assignment of GLC to each security realm (or better yet, vice versa).
  • Add some kind of fancier validator object to a SecurityRealm that can enforce rules like "user only valid between 9 and 5". It can't only reject new logins; it must also terminate an existing valid login at the appropriate time. It's not clear how to do this right. This would replace the previous ability to set a realm-specific max login duration.
  • We need more tests of all this functionality