-
Notifications
You must be signed in to change notification settings - Fork 1
GSIP 71
A completely reengineered security system with emphasis on flexibility and configurability.
{info} This proposal supersedes the following past proposals:
- [GSIP 53 Geoserver security improvement]
- [GSIP 63 - Encrypt Plaintext Passwords]. {info}
Christian Mueller Justin Deoliveira
Intended for 2.2
Under Discussion, In Progress, Completed, Rejected, Deferred
This proposal is a major retrofit of the GeoServer security subsystem. The following highlights the added functionality:
- Support for groups, with ability to assign roles to an entire group rather than individual users
- Support for password encryption allowing for storing user passwords in non-plain text
- Configurability - ability to configure new types of authentication (ex. LDAP) out of the box
- Extensibility - ability to extend system to add new authentication types, user and role database backends, etc… through plug-ins
A new class named GeoServerSecurityManager
is the facade for the new
security subsystem and plays the same role that Catalog
plays for
the catalog subsystem, and GeoServer
plays for the configuration
subsystem.
The current version of the class can be found here
The new security subsystem adds two entities:
- User/Group Service - Backend database for users
- Role Service - Backend database for roles, and their assignment to users and groups
A user/group service provides a source user/group database and is a
replacement for what is currently stored in the users.properties
file. This service is explain in more detail
here
.
A role service provides a source for role information, including
available roles and the users/group those roles are assigned to. This
service also replaced information currently stored in
users.properties
. This service is documented in more detailed
here
.
Both user/group and role services can be read or read-write, the former providing a service that is only a source of user/role information, the latter providing the ability to modify.
This proposal adds the ability to store passwords encrypted, rather than
in plain text. This is supported for both user passwords (previously
stored in users.properties
and also configuration passwords for
stores (ex. database passwords), stored in the store.xml
for a
particular store.
A variety of encryption methods are available, including:
- Plain-text
- Digest
- Password based encryption (PBE)
PBE encryption comes in two flavours, strong and weak. Strong PBE encryption requires additional JCE jars not included in all Java installations. For those system that don’t come with strong encryption out of the box it is possible to download install them manually.
More documentation available here .
The new security work adds the ability to place constraints on user passwords such as password length, mix of case and characters, etc…
Documented in more detail here .
The security subsystem allows for the control of how users are authenticated in geoserver, with the ability to add and configure new types of authentication such as LDAP. The notion of an “authentication chain” is provided to allow for a number of authentication strategies and scenarios.
More documentation about authentication here .
Because of the highly configurable nature of the new security subsystem it is quite possible that through a misconfiguration the administrator could potentially disable authentication, preventing even herself from logging in the geoserver admin ui to fix the problem. For this reason the notion of a root account is added. The root account is one that is meant to always be available regardless of the state of the normal authentication chain.
The username for the root account is “root” and the password is the master password, explained in more detail below.
With the ability to do password encryption comes the requirement to
store encryption keys in a secure way. This is achieved with a java
keystore . For this reason an
internal keystore is maintained in the security
directory under the
data directory. The keystore is named geoserver.jceks
.
As the name implies the type of keystore used is JCEKS
rather than
the default JKS
type. This is because JCEKS is capable of storing
secret keys as well as private keys. JKS can only do private keys. More
information about the difference available in this
article .
The keystore is protected by the master password , explained in more detail below. Documentation regarding the keystore can be found here .
As mentioned above the master password serves two purposes:
- As the password for the root account
- Protect the internal keystore that contains keys used for encryption
Naturally is important that the master password be stored in a secure way since the master password being compromised means that the entire system has been compromised. A number of measures are taken to enhance the security of the master password.
The first is that we use a digest encryption method for the purposes of simple password validation, for instance during login to the root account. Digest encryption is one-way which means we avoid ever having to decrypt the master password back into plain text.
However, there is one case in which we must decrypt the master password back into plain text and that is to access the keystore. To facilitate this we store a separately encrypted version of the master password. The encryption method used in this secondary case is a PBE method in which the key is generated by applying a permutation to a pre-defined alphabet. This obviously is not perfect since it means a malicious user could easily decrypt the master password by studying the GeoServer source code. But it is better than simply storing the master password in plain text on the file system.
The method of storing the master password is extensible, with the above scheme being the default that comes out of the box. In environments that require a higher level of security it is recommended an alternate scheme be used. One such possibility is by using an external url for the source of the master password. This url can be a link to a static resource, or a link to a dynamic web service that can generate the master password. And finally there is the option of writing a completely custom master password provider.
That said, when handling the master password in plain text, obtained from whichever method, we always take two precautions to minimize the exposure of the password.
- Never store it in a String, instead we use a char array
- Always scramble the char array when we are done
To illustrate with code, instead of doing this:
String masterpw = getSecurityManager().getMasterPassword();
//do sometthing
We always do this:
char[] masterpw = getSecurityManager().getMasterPassword();
try {
// do something
}
finally {
getSecurityManager().disposePassword(masterpw);
}
The reason for this is that java strings are immutable, and pooled in memory for performance reasons. Which means it would be possible to analyze the contents of the java heap to retrieve the master password. So for this reason we use a char[] array and scramble the contents of it after we are done in order to minimize the risk.
So it is important that code never do this:
char[] masterpw = getSecurityManager().getMasterPassword();
new String(masterpw);
Lastly the GeoServerSecurityManager.getMasterPassword ()
method is
of package visibility meaning only code within the
org.geoserver.security
package has the ability to retrieve its value
in plain text. Furthermore this package is sealed so that it is not
possible for a third party extension to place itself within the same
package.
More documentation regarding passwords and encryption is available here .
The new security subsystem comes with a new structure in the data
directory under the security
directory. The new file tree looks like
the following:
config.xml
geoserver.jceks
layers.properties
service.properties
rest.properties
auth/
filter/
masterpw
pwpolicy
role
usergroup
-
config.xml
is the top level configuration file. It contains global security options. -
geoserver.jceks
is the keystore used for encryption keys. Explained above. -
layers.properties
,service.properties
, andrest.properties
are unchanged. -
auth
is the root directory for authentication provider configurations. Example above. -
filter
is the root directory for security filter configurations. -
masterpw
is the root directory for master password provider configurations. Exampled above. -
pwpolicy
is the root directory for password policy configurations. -
role
is the root directory for role service configurations. Explained above. -
usergroup
is the root directory for user group service configurations. Explained above.
Under each of the individual directories, auth
, filter
,
masterpw
, etc… can contain multiple configurations, each contained
within another subdirectory named the same as the configuration name.
Under each directory contains a file named config.xml
that contains
the persisted configuration itself as XML. Depending on the entity the
directory will also contain other files, for instance a usergroup
configuration directory can contain the xml files containing the actual
user database.
Read on to the next section for more information.
Upon upgrade to the new security subsystem the old configuration is migrated to the new. This is similar to how the catalog and configuration are migrated upon upgrading from a pre geoserver 1.7.x configuration.
The first part of the migration involves replacing users.properties
with a user group service and role service configuration. Both of the
configurations are named “default” and located under the usergroup
and role
directories respectively.
usergroup/
default/
config.xml
users.xml
users.xsd
role/
default/
config.xml
roles.xml
roles.xsd
Both services persist the user and role databases as xml. The default
users.xml
has the following contents:
<userRegistry version="1.0" xmlns="http://www.geoserver.org/security/users">
<users>
<user enabled="true" name="admin" password="crypt1:e114FDdortfDNv01rzEpnDk3cmd+UsNE"/>
</users>
<groups>
</groups>
</userRegistry>
The default roles.xml
has the following contents:
<roleRegistry version="1.0" xmlns="http://www.geoserver.org/security/roles">
<roleList>
<role id="ROLE_ADMINISTRATOR"/>
</roleList>
<userList>
<userRoles username="admin">
<roleRef roleID="ROLE_ADMINISTRATOR"/>
</userRoles>
</userList>
<groupList/>
</roleRegistry>
Also during migration a default authentication provider is created that authenticates users by using the usergroup service to look up user info, and verify passwords.
auth/
default/
config.xml
The config.xml
contains mainly the name of the usergroup service to
use for the user lookup.
<usernamePassword>
<id>-344bdadf:1358c667d8c:-7ffb</id>
<name>default</name>
<className>org.geoserver.security.UsernamePasswordAuthenticationProvider</className>
<userGroupServiceName>default</userGroupServiceName>
</usernamePassword>
During migration a master password provider configuration is created for storing the geoserver master password. For historical reasons the default master password is “geoserver”.
A master password provider is an extension point for allowing different
strategies for storing and retrieving the geoserver master password. The
default provider uses a file named passwd
inside of the
configuration directory that stores the encrypted master password.
masterpw/
default/
config.xml
passwd
Master password providers explained in more detail above.
During migration two password policies are created:
pwpolicy/
default/
config.xml
master/
config.xml
The first, “default”, is the default policy used for user passwords. It places no constraints on user passwords.
The second, “master” is the policy used to constrain the master password. The only constraint it places is a minimum length of 8 characters, which is required in order to password protect the keystore.
Password policies explained in more detail above.
Issue/Concern | Resolution |
---|---|
Developer docs | |
User doc tweaks | |
JCE policy jars not available everywhere, state that |
As explained above this proposal changes the security configuration structure, but migrates old configuration upon startup. So the work is backward compatible but not forward compatible. This mirrors how the catalog / configuration handed backward compatibly during the upgrade from 1.7 to 2.0.
Andrea Aime: Alessio Fabiani: Ben Caradoc Davies: Gabriel Roldan: Justin Deoliveira: Jody Garnett: Mark Leslie: Rob Atkinson: Simone Giannecchini:
JIRA Task Email Discussion Wiki Page
©2020 Open Source Geospatial Foundation