= Proposal title = || '''Date''' || 2010/12/15 || || '''Contact(s)''' || [http://wiki.osgeo.org/wiki/User:Heikki Heikki Doeleman] & [http://wiki.osgeo.org/wiki/User:Josegar Jose Garcia] || || '''Last edited''' || 2010/12/15 || || '''Status''' || Draft In Progress || || '''Assigned to release''' || 2.7 || || '''Resources''' || Nordic countries (Denmark, Finland, Norway and Sweden) || == Overview == Short description of the improvement proposal. ... === Proposal Type === * '''Type''': GUI Change, Core Change, Module Change, Guideline and project governance procedures, ... * '''App''': !GeoNetwork or !Intermap * '''Module''': eg. Harvester, Kernel, Data Manager, Metadata Import, Lucene Index, Search Interface ... === Links === * '''Documents''': * '''Email discussions''': * '''Other wiki discussions''': === Voting History === * Vote proposed by X on Y, result was +/-n (m non-voting members). ---- == Motivations == This document describes the architecture we propose to enable and enhance the use of various security providers with !GeoNetwork opensource. We will give an overview of the current way of dealing with security in !GeoNetwork 2.x and !GeoNetwork 3.x, after which we will present this proposal in more detail. This proposal entails the use of [http://static.springsource.org/spring-security/site/ Spring Security], a well-known framework that supports the use of one or several security providers. It also entails the introduction of a dedicated GN security component (!GeoNetwork Authentication & Authorization Provider, GAAP), which is already in use in !GeoNetwork 3.x, into !GeoNetwork 2.x. === current situation in !GeoNetwork 2.x === This section describes the implementation of authentication and authorization in the current releases of !GeoNetwork 2.x (as also in trunk). ==== Users and Groups ==== !GeoNetwork maintains DBMS tables for Users and Groups. A User is an entity that can log in, log out, has a Profile (this is best understood as a Role), and is part of one or more Groups. Access to metadata is restricted by Profile and Group. The Group privileges to access a metadata are stored in a DBMS table and also in the Lucene index. In the code these access privileges are overridden by checking on Profile (esp. Users with Profile "Administrator" are permitted access to all metadata). The metadata access is further specified in access types (View, Edit, and a few other ones). ==== LDAP ==== It is possible to configure an external LDAP security provider. In this case, after a successful login, the User information obtained from LDAP is temporarily inserted into the !GeoNetwork Users DBMS table. When the session ends (upon logout or expiration) they remain in the database. It is not possible to configure more than one LDAP provider. === current situation in !GeoNetwork 3.x === This section describes the implementation of authentication and authorization in the current branch of !GeoNetwork 3.x. In !GeoNetwork 3.x the picture is slightly changed because of the introduction of a new, separate Web application, !GeoNetwork CSW/ebRIM. This application restricts access to its ebRIM metadata based on the privileges for the ISO19139 metadata (in "Legacy" !GeoNetwork) that the ebRIM metadata was created for. In order to separate concerns an extra new Web application was introduced, GAAP (!GeoNetwork Authentication & Authorization Provider). The !GeoNetwork Users and Groups DBMS tables, as well as the metadata privileges table in !GeoNetwork 3.x are moved to GAAP. !GeoNetwork CSW/ebRIM consults GAAP to control access to its ebRIM metadata. Legacy !GeoNetwork consults GAAP to control access to its metadata. === outline of proposed changes === This section summarizes our proposed changes. The changes are intended to: * allow for the use of more than one authentication provider, simultaneously * add support for [http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language SAML]-based authentication (Single-Sign On) * allow for the use of other types of external security providers * improve on the implementation when using !GeoNetwork Authentication and/or one or more external security providers * improve performance as compared to the current !GeoNetwork 3.x code * The proposal involves the introduction of GAAP in !GeoNetwork 2.x and modifications to the working of GAAP and Legacy !GeoNetwork. == Proposal == === basic architecture === ==== security token map ==== !GeoNetwork maintains an in-memory map of security tokens, !SecurityTokenMap. This map associates a session id with a security token. The token contains all information !GeoNetwork uses to allow access to its resources: the User Profile and list of Groups the User is part of. When determining access rights, the metadata privileges as stored in the DBMS and Lucene (depending on type of access -- Lucene is used for free text searches) are compared to the Groups found in the security token in the current session. ==== security servlet filter ==== A servlet filter intercepts all requests to !GeoNetwork and verifies whether the current session id is present in !SecurityTokenMap. If it is, nothing special happens and the request continues to its destination service in !GeoNetwork. If the session id is not in !SecurityTokenMap, the filter requests GAAP for an anonymous security token. The session id is mapped to this anonymous token and stored in !SecurityTokenMap. ==== logging in ==== When a User is logging in, the login form is requested from GAAP. GAAP uses Spring Security to access one or more security providers. If the credentials provided in the login form can be matched against one of them, a security token is created that contains all required information, the User's name (and possibly other info like contact details), Profile, and list of Groups. This security token is returned to !GeoNetwork that adds or updates the entry for the current session in !SecurityTokenMap. When the User logs out or the session expires the corresponding entry is removed from !SecurityTokenMap. ==== logged in ==== When a User is logged in and accessing some resource where authorization is involved, !SecurityTokenMap is consulted to match this User's privileges to the permissions set for the resource. As an example when a (text) search is done, the privileges stored in Lucene for each document matching the text search are compared to the Groups in !SecurityTokenMap to decide whether to include a text search result in the result set returned to the client. ==== administration ==== Users with Profile "Administrator" are authorized to manage Groups, Users, and configure external (e.g. LDAP) security providers. The actual DBMS and web pages enabling this currently reside in !GeoNetwork, but in our proposed architecture this belongs in GAAP. So we'll move the administration of users and groups, and also the configuration of security providers, to GAAP. The security provider configuration data is stored in a !SecurityProvider DBMS table and dynamically applied to the Spring Security configuration. Security providers may be marked as ACTIVE or INACTIVE by the Administrator. When performing an authorization, GAAP's Spring Security will only consult the security providers marked as ACTIVE. ==== component model ==== A UML component model to illustrate our proposal is this: [[Image(component-model.png)]] === !GeoNetwork application === This section discusses the changes to the !GeoNetwork application. !GeoNetwork uses session to maintain state about the privileges of the current user. This remains exactly the same in this proposal. ==== authentication ==== The main difference lies in how the authentication is performed. In this proposal !GeoNetwork delegates authentication to GAAP; the result of this authentication is a !SecurityToken returned by GAAP and associated to the current session. A UML Activity diagram giving a high-level view of !GeoNetwork delegating to GAAP is this: [[Image(GeoNetworkSecurityFilterActivity.png)]] Because the Users and Groups DBMS tables are moved to GAAP, their information is part of the !SecurityToken; where currently !GeoNetwork has numerous places where it consults the DBMS to look up the current user's groups, these lookups are modified to use the !SecurityToken instead. !SecurityTokens are kept in an application-scope map, with session-id as the key to look them up. If the user does not log in, the !SecurityToken is an anonymous !SecurityToken. The delegation is handled by a Servlet Filter, !GeoNetwork Security Filter. This filter intercepts all requests to !GeoNetwork, checks if the current session id is known in the !SecurityToken Map and if not, it forwards the request to GAAP. GAAP returns a !SecurityToken that is added to the Map, so subsequent requests from the same client (as long as the session is valid) do not need to consult GAAP again. After this, !GeoNetwork Security Filter lets the request continue normally to its destination (one of the !GeoNetwork services). A more detailed UML Sequence diagram showing !GeoNetwork delegating to GAAP is this: [[Image(GeoNetworkSecurityFilterSequence.png)]] A short description of the steps in the above sequence diagram: 1. Clients sends a request to !GeoNetwork, which is intercepted by !GeoNetworkSecurityFilter 2. !GeoNetworkSecurityFilter retrieves !SecurityTokenMap from application scope 3. !GeoNetworkSecurityFilter retrieves the current session id 4. !GeoNetworkSecurityFilter checks whether current session id has an associated !SecurityToken in !SecurityTokenMap 5. If not, !GeoNetworkSecurityFilter forwards the request to GAAP's !AuthenticationService; GAAP responds with a !SecurityToken 6. !GeoNetworkSecurityFilter adds the !SecurityToken to !SecurityTokenMap 7. !GeoNetworkSecurityFilter calls the method "authenticate()" in Jeeves !UserSession. For non-anonymous users this means, login to !GeoNetwork 8. !GeoNetworkSecurityFilter sets !UserSession in session scope 9. The request continues normally to its !GeoNetwork service destination 10. The service response is returned to the client ==== login ==== In the login service, !GeoNetwork delegates authentication to GAAP. The UML Sequence diagram showing !GeoNetwork login is this: [[Image(GeoNetworkLoginSequence.png)]] ==== logout ==== In the logout service !GeoNetwork the !UserSession and !SecurityToken are removed. Next request to !GeoNetwork will request to GAAP a new !SecurityToken, that can be either an anonymous !SecurityToken (if no authentication is attempted) or a !SecurityToken containing details about the authenticated user. The UML Sequence diagram showing !GeoNetwork logout is this: [[Image(GeoNetworkLogoutSequence.png)]] A short description of the steps in the above sequence diagram: 1. Client sends a request to !GeoNetwork logout service 2. The session is invalidating, removing the !UserSession information 3. !SecurityToken is removed from !GeoNetworkSecurityTokenMap 4. The client is forwarded to !GeoNetwork main page ==== other changes ==== Some other changes to the !GeoNetwork application foreseen by this proposal are: * move Login form, and Users and Groups DBMS tables to GAAP: this is about authentication, so should be located in the dedicated Authentication application (GAAP) * move administration GUI pages related to the above DBMS tables to GAAP * change lookups in !GeoNetwork code to the above DBMS tables, to lookup the info in !SecurityTokenMap instead the login form and the non-GUI login ("xml login") delegate the act of logging in to GAAP === GAAP application === This section describes the GAAP application, both its Authentication Service and the administrative GUI interface. ==== authentication service ==== The Authentication Service is GAAP's raison d'être: to provide authentication functions to its client applications, while acting as a façade to hide details of the underlying security provider(s) from its client applications. Authentication requests from GAAP clients attempt to reach their destination, !AuthenticationService. This will succeed if the request is anonymous (no attempt at authentication is made) or if a succesful authentication happened in the Spring Security !FilterChain that intercepts requests to this service. [[Image(SpringSecurityAuthenticationServiceActivity.png)]] A succesful request to !AuthenticationService causes it to return a !SecurityToken to the client application; this can be either an anonymous !SecurityToken (if no authentication was attempted) or a !SecurityToken containing details about the authenticated user. A failed login attempt causes the Spring Security !FilterChain to throw an exception, which itself is processed in a later filter in this chain, so that a response indicating the failed login condition is returned along with an anoymous !SecurityToken. ==== security providers ==== One or more security providers need to be configured and active so that GAAP has at least one source to authenticate against. They can be of many different types that are supported out-of-the-box by Spring Security. Some examples: JDBC, LDAP, SAML-based, Open-ID based, in-memory (specified only in Spring Security itself). The classic !GeoNetwork Users DBMS table, having moved from the !GeoNetwork application to the GAAP application, is treated exactly as any other security provider, except that it is the default if you don't configure anything else. To make sure that the super-super-user "admin" is always available to GAAP, it is configured in an in-memory security provider to Spring Security. Users with role Administrator can use the GAAP GUI administrative pages to configure one or more security providers. Security providers can be ACTIVE or INACTIVE; if INACTIVE their configuration is still there but they are not used in the Spring Security authenticating !FilterChain. ==== userproperties ==== You may remember from the description of current !GeoNetwork 2.x that in case LDAP authentication is used, the LDAP users are inserted into the !GeoNetwork Users table, where they remain even when their session ends. The reason for this is that an Administrator might decide to change these users' groups or role, and it would be impractical to do this everytime again when an LDAP user logs in. One drawback of the current implementation is of course that previously existing data in the Users table simply gets overwritten when this happens; switching between JDBC and LDAP authentication in current !GeoNetwork is definitely not recommended without extra safeguards like backing up the database before making such a switch. All this is of course no longer a problem in this proposed solution; not only can you switch between various security providers, you can also use them at the same time. Still, some data related to users should still be persisted; for example when an Administrator changes an LDAP user's groups or role. For this reason, everytime a successful non-anonymous authentication has been made, the information contained in !SecurityToken is also persisted in the DBMS table !UserProperties. === GAAP Administrative GUI === The pages in the !GeoNetwork admin section that deal with Users and Groups are moved to the GAAP web application. In the !GeoNetwork "system configuration" page, which operates on the DBMS table Settings, currently some authentication sources can be configured, to wit an LDAP provider or a Shibboleth source. These are removed from that page. In GAAP a page dedicated to security provider configuration is introduced. Administrator users can configure one ore more security providers and flip their ACTIVE/INACTIVE state. This configuration is persisted in the GAAP DBMS table !SecurityProviders, and is also (when changed) applied on-the-fly to the Spring Security configuration so changes take immediate effect. The GAAP Administrative GUI also allows Administrator users to configure some of GAAP's behaviour. The following options are available: * User Properties strategy. Administrator users can edit user's role and groups in GAAP. It is possible that the security provider that has authenticated a user has provided some or all of that information (more likely 'role' info) originally. If the option GAAPONLY is selected, GAAP will henceforth only use the (Administrator-changed) user information and ignore any info from the security provider the next time this user logs in. This is also the default. If the option EXTERNAL is selected, GAAP will each time look at the info from the security provider and overwrite any changes made to it in GAAP by an Administrator. Although the GAAP Administrative pages reside in the GAAP web application, they will be transparently made accessible through the same links in the !GeoNetwork Admin page. The GAAP GUI is also accessible through its own, !GeoNetwork-independent base URL. The GAAP GUI runs on Spring MVC, using JSP with Sitemesh. === saml 2.0 security provider === We will use the standard Spring Security Extension for SAML. This library is able to authenticate users against any SAML 2.0 compatible Identity Provider. Some of the features we support are: * Both Service Provider (SP) and Identity Provider (IDP) initiated !WebSSO profile of the SAML v2 protocol stack * HTTP-POST and HTTP-Redirect bindings * Automatic generation of Service Provider metadata * Configuration of multiple IDPs GAAP support for SAML can function in one of the two modes of IDP discovery: * A default IDP has been configured which is then always used * User is allowed to select IDP from the list of configured ones; entry point then redirects user to the selection page. SP-initiated flow is to say, the user's Single Sign-On identity is created by the user starting at the !GeoNetwork (the Service Provider). GAAP's login form shows a list of all trusted Identity Providers; the user can choose one, and upon submit is redirected to that Identity Provider's login form. After authentication at the Identity Provider the user comes back to !GeoNetwork. IDP-initiated flow is when the user has already authenticated with a trusted Identity Provider when doing a request to !GeoNetwork; in this case the request carries a SAML Authentication token that is validated by GAAP and if valid, allows the user Single-!SignOn access to !GeoNetwork. The AuthNRequest SAML message is sent to the IDP using either HTTP-POST or HTTP-Redirect binding and the request is stored in the cache for subsequent matching with the response. All configured IDPs are considered to be members of a single circle of trust. The SAML Single log-out profile is currently not supported, invocation of logout at will only destroy the local session. A UML Activity diagram giving a view of how GAAP manages a SP-initiated WebSSO is: [[Image(SAMLAuthenticationActivity.png)]] 1. When the user selects an IDP in GAAP login to validate against it, SAMLEntryPoint sends to the IDP an AuthNRequest SAML message . 2. A SAML response created by the IDP is send to a GAAP URL, monitored by SAMLProcessingFilter that parses the SAML message wrapping it into SAMLAuthenticationToken. 3. The SAMLAuthenticationProvider validates the SAMLAuthenticationToken and 4. If the validation succeeds a Spring !AuthenticationToken is created and the flow continues to create the GAAP !AuthenticationToken as described previously. Because we support SAML 2.0, not SAML 1.1 or earlier, you can only use Shibboleth 2.0, not earlier versions. === Backwards Compatibility Issues === The structure of the database will change and even partially moved to another DBMS schema. It is likely that for this migration we'll need to provide a specific migration tool that entails more than just an SQL script. === New libraries added === Spring Security 3 .. todo more ? == Risks == This is a major overhaul of the current application architecture. == Participants == * [http://wiki.osgeo.org/wiki/User:Heikki Heikki Doeleman] * [http://wiki.osgeo.org/wiki/User:Josegar Jose Garcia]