= Improved security =
|| '''Date''' || 2012/08/01 ||
|| '''Contact(s)''' || [http://wiki.osgeo.org/wiki/User:Jeichar Jesse Eichar], Francois Prunayre ||
|| '''Last edited''' || ||
|| '''Status''' || Done ||
|| '''Assigned to release''' || 2.9.x ||
|| '''Resources''' || Funding Ifremer ||
|| '''Ticket''' || #1070 ||
|| '''Code''' || https://github.com/jesseeichar/core-geonetwork/commits/feature/spring-security ||
== Overview ==
This proposal entails the use of Spring Security (http://www.springsource.org/spring-security), a well-known framework that supports the use of one or several security providers. Main goals are:
* SSO configuration (CAS)
* improve LDAP support
* import user privileges (support more than one group, define profile mapping)
* support more than one authentication provider
* when accessing a protected page, user is moved to a login page and will be redirected to the protected resource (instead of ServiceNotAllowed exception #313)
* ... and keep local user database and shibboleth support.
=== Proposal Type ===
* '''Type''': Security
* '''App''': !GeoNetwork
* '''Module''':
=== Links ===
* '''Email discussions''':
* '''IRC discussions''':
* '''Related work''':
* http://trac.osgeo.org/geonetwork/wiki/proposals/ImprovedSecurityArchitecture
* [wiki:Adding CAS authentication support]
=== Voting History ===
* None as yet
----
== Proposal ==
Right now the user-profiles configuration file is used to control what profiles exist and what profiles can access which services.
This proposal moves the security control from user-profiles to spring-security.
Example:
{{{
}}}
=== Configuration ===
A set of files config-security* is added in order to easily configure authentication mechanism:
* configure access for GeoNetwork services
* configure authentication provider(s)
* Local database
* LDAP
* LDAP+Local database
* CAS+LDAP
* CAS+local database
The main configuration to activate authentication mechanism is config-security.xml where import could be activated:
{{{
}}}
Then LDAP, CAS configuration (eg. LDAP url, CAS URL, ...) is made in config-security.properties.
==== LDAP ====
===== Connection Settings =====
To enable LDAP support:
* add the CAS base URL property in config-security.properties::
{{{
# LDAP security properties
ldap.base.provider.url=ldap://localhost:389
ldap.base.dn=dc=fao,dc=org
ldap.security.principal=cn=admin,dc=fao,dc=org
ldap.security.credentials=ldap
}}}
* ldap.base.provider.url: This tells the portal where the LDAP server is located. Make sure that the computer with the catalog can hit the computer with the LDAP server. Check to make sure that the appropriate ports are opened, etc.
* ldap.base.dn=dc=fao,dc=org: this will usually look something like: "dc=organizationnamehere,dc=org"
* ldap.security.principal & ldap.security.credentials: Define LDAP administrator user to use to bind to LDAP. If not define, an anonymous bind is made. Principal is the username and credentials property the password.
* To verify that you have the correct settings, try to connect to the LDAP server using an LDAP browser application.
* define where to find users in LDAP structure for authentication::
{{{
ldap.base.search.base=ou=people
ldap.base.dn.pattern=uid={0},${ldap.base.search.base}
#ldap.base.dn.pattern=mail={0},${ldap.base.search.base}
}}}
* ldap.base.search.base: this is where the catalog will look for users (for authentication)
* ldap.base.dn.pattern: this is the distinguished name for the user to bind with. {0} is replaced by the user name typed in the sign in screen.
* add the following import to config-security.xml::
{{{
}}}
===== Authorization Settings =====
When using LDAP, user information and privileges could be defined from the LDAP attributes.
====== User details ======
All user informations could be retrieved from the LDAP as defined in the config-security-overrides.properties.
This property file defined for each user attribute in the catalog database which LDAP attributes match.
If the attribute is empty or not defined, a default value could be defined. The configuration is the following::
{{{
# Map user information to LDAP attributes and default values
# ldapUserContextMapper.mapping[name]=ldap_attribute,default_value
ldapUserContextMapper.mapping[name]=cn,
ldapUserContextMapper.mapping[surname]=givenName,
ldapUserContextMapper.mapping[mail]=mail,data@myorganization.org
ldapUserContextMapper.mapping[organisation]=,myorganization
ldapUserContextMapper.mapping[kind]=,
ldapUserContextMapper.mapping[address]=,
ldapUserContextMapper.mapping[zip]=,
ldapUserContextMapper.mapping[state]=,
ldapUserContextMapper.mapping[city]=,
ldapUserContextMapper.mapping[country]=,
}}}
====== Privileges configuration ======
When using LDAP, user groups and user profiles could be set from LDAP information or not.
To manage user privileges from the local database, set the ldap.privilege.import property in
config-security.properties to false::
{{{
ldap.privilege.import=false
}}}
If LDAP information should be used to define user privileges, set it to true::
{{{
ldap.privilege.import=true
}}}
When importing privileges from LDAP, the catalog administrator could decide to create groups
defined in the LDAP and not defined in local database. For this set the following property to true::
{{{
ldap.privilege.create.nonexisting.groups=false
}}}
======= Simple privileges configuration =======
In order to define which groups the user is member of and which profile is the user::
{{{
ldapUserContextMapper.mapping[privilege]=groups,sample
# If not set, the default profile is RegisteredUser
# Valid profiles are http://geonetwork-opensource.org/manuals/trunk/eng/developer/apidocs/geonetwork/org/fao/geonet/constants/Geonet.Profile.html
ldapUserContextMapper.mapping[profile]=privileges,RegisteredUser
}}}
Attributes configuration:
* privilege attribute contains the group this user is member of. More than one group is allowed.
* profile attribute contains the profile of the user
======= Profile mapping configuration =======
If LDAP attribute containing profiles does not match the catalog profile list, a mapping could be defined
in config-security-overrides.properties::
{{{
# Map LDAP custom profiles to catalog profiles. Not used if ldap.privilege.pattern is defined.
ldapUserContextMapper.profilMapping[Admin]=Administrator
ldapUserContextMapper.profilMapping[Editeur]=Reviewer
ldapUserContextMapper.profilMapping[Public]=RegisteredUser
}}}
For example, in the previous configuration, the attribute value Admin will be mapped to Administrator (which
is a valid profile for the catalog).
======= Advanced privileges configuration =======
An attribute could define both the profile and the group for a user. To extract this information,
a custom pattern could be defined to populate user privileges according to that attribute::
{{{
# In config-security-overrides.properties
ldapUserContextMapper.mapping[privilege]=cat_privileges,sample
# In config-security.properties
ldap.privilege.pattern=CAT_(.*)_(.*)
ldap.privilege.pattern.idx.group=1
ldap.privilege.pattern.idx.profil=2
}}}
The LDAP attribute can contains the following configuration to define the different type of users::
{{{
-- Define a catalog admin:
cat_privileges=CAT_ALL_Administrator
-- Define a reviewer for the group GRANULAT
cat_privileges=CAT_GRANULAT_Reviewer
-- Define a reviewer for the group GRANULAT and editor for MIMEL
cat_privileges=CAT_GRANULAT_Reviewer
cat_privileges=CAT_MIMEL_Editor
-- Define a reviewer for the group GRANULAT and editor for MIMEL and RegisteredUser for NATURA2000
cat_privileges=CAT_GRANULAT_Reviewer
cat_privileges=CAT_MIMEL_Reviewer
cat_privileges=CAT_NATURA2000_RegisterdUser
-- Only a registered user for GRANULAT
cat_privileges=CAT_GRANULAT_RegisteredUser
}}}
===== Synchronization =====
A synchronization task is taking care of removing LDAP user which may be deleted. For example:
* T0: a user A sign in the catalog. A local user A is created in the user database
* T1: A is deleted from the LDAP (A could not sign in in the catalog anymore)
* T2: the synchronization task will check that all local LDAP users exist in LDAP:
* if user is not owner of any records, it will be deleted
* if user is owner of metadata records, warning message is avaialable on the catalog logging system. record's owner should be changed to another user before the task could remove the user.
By default the task is runned once every day. Configuration could be changed in config-security.properties::
{{{
# Run LDAP sync every day at 23:30
ldap.sync.cron=0 30 23 * * ?
}}}
===== Debugging =====
If connection fails, try to increase logging for LDAP in log4j.cfg::
{{{
log4j.logger.geonetwork.ldap = DEBUG
log4j.logger.org.springframework = DEBUG, console, jeeves
log4j.logger.org.springframework.* = DEBUG
log4j.logger.org.springframework.security.ldap = DEBUG
}}}
==== CAS ====
To enable CAS support:
* add the CAS base URL property in config-security.properties::
{{{
cas.baseURL=https://localhost:8443/cas
cas.ticket.validator.url=${cas.baseURL}
cas.login.url=${cas.baseURL}/login
cas.logout.url=${cas.baseURL}/logout?url=${geonetwork.https.url}/
}}}
* add the following import to config-security.xml::
{{{
}}}
=== Backwards Compatibility Issues ===
* Security configuration is made using configuration file (and not user interface)
* Database changes (migration script provided):
* User table : add a authtype column to identify local/external users
* Configuration overrides would not work at all for that.
== Risks ==
== Participants ==
* As above