Please describe desired steps of proposed new feature/enhancement:
1. The existing administrator guide at
http://webpasswordsafe.googlecode.com/svn/trunk/docs/AdministratorGuide.html is
relatively sparse in relation to describing authentication plugin configuration
2. Some other issues have been submitted where people appear to have had
trouble configuring ldap integration (Issues 84, 93, 100)
3. It took me significantly longer than I would have liked to configure this,
but I did succeed
4. Regardless of the above, very nice project & thanks for sharing.
What version of the product are you using? On what operating system?
Product versions 1.3 & 1.4 svn rev 203. The operating system should not be
important to this feature request, but for completeness the submission below
was compiled using Windows Server 2008 R2
Since these actions took longer than I would have liked, I've attempted to
document them. The documentation will likely be used elsewhere, but since it
was completed in personal time, I'm happy to have GPL v2 applied to it, should
you decide to incorporate it into your existing docs. Regardless, having it
available in the issues tracker hopefully saves someone else some time :)
This text attempts to consolidate existing documentation, that describe
configuration steps to deliver a working integration between WebPasswordSafe
and Microsoft Active Directory.
Prerequisites:
This guide does not assist with the completion of these steps:
• WebPasswordSafe installed and functional using the default / LocalAuthenticator authentication (1). This integration guide was written and tested against WebPasswordSafe-1.3 with debug logging enabled, and WebPasswordsafe-1.4 (svn revision 203; default logging)
• Microsoft Active Directory installed and functional. This integration guide was written and tested against an active directory at forest & domain functional level of Windows Server 2012. It is anticipated it would work regardless of functional level.
• The ability to create a user account in the Active Directory with Domain Users membership. WebPasswordSafe will use this account for the purpose of Distinguished Name lookup of users that attempt to login to WebPasswordSafe
• A Public Key Infrastructure installed and functional. (2) It is necessary that the PKI be able to sign certificates for the purpose of Server Authentication
• All Active Directory Domain Controllers must have a Server Authentication certificate installed, (2) along with the associated CA / Intermediate CA('s)
(1) See:
http://webpasswordsafe.googlecode.com/svn/trunk/docs/AdministratorGuide.html
for the pre-existing Administrator Guide.
(2) In the context of Active Directory, the simplest configuration from the
perspective of this implementation is that Active Directory Certificate
Services already be installed:
http://technet.microsoft.com/en-au/library/hh831740.aspx
In the case that AD-CS is not already existing in the environment, one
approach is the use of OpenSSL to create a private CA, generate and install
certificates.
Microsoft documentation for the creation of the Certificate Signing Request,
installation of the resulting certificate:
http://support.microsoft.com/kb/321051
3rd party documentation for the creation of the Certificate Signing Request,
signing of the CSR using an OpenSSL generated CA, installation of the resulting
certificate:
http://www.javaxt.com/Tutorials/Windows/How_to_Enable_LDAPS_in_Active_Directory
OpenSSL binaries for Windows hosts: (note: this guide was written using OpenSSL
on Centos 6.5, not these binaries)
http://www.openssl.org/related/binaries.html
Integration steps:
Note: Where a domain name is required in the examples, this document assumes
the domain name is contoso.com. These values should be modified to match your
environment.
From the WebPasswordSafe host, confirm that ldaps is configured, working and
accessible on each of your domain controllers:
Telnet domain.controller.fully.qualified.name 636
The test should be regarded successful if you are able to establish a
connection; meaningful communication with the server is not important for this
test.
Install your CA certificate, along with any intermediary certificates, into
the CA keystore of the Java installation that Tomcat is using:
https://code.google.com/p/webpasswordsafe/wiki/AdminGuide (Comment
by da...@darins.net, Jun 3, 2011)
The next section builds on the existing documentation available at:
http://webpasswordsafe.googlecode.com/svn/trunk/docs/AdministratorGuide.html
In case you have no other backup, make a copy of your existing
webpasswordsafe-service.xml from:
<webpasswordsafe-app-name>\WEB-INF
Open webpasswordsafe -service.xml in your editor of choice. First we will step
through each of the required changes, culminating in a complete working example
config at the end:
Change chaining of authenticator beans to include ldapAuthenticator. Original
setting:
<bean id="userLockoutAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.UserLockoutAuthenticator">
<property name="authenticator" ref="localAuthenticator" />
In the default configuration the line:
<property name="authenticator" ref="localAuthenticator" />
Causes all authentication requests to be evaluated against the built in user
database. Alternate options for this entry are:
Ref="ldapAuthenticator"
Populating ldapAuthenticator would cause all authentication attempts to be
validated only by ldap / Active Directory.
Ref="multiAuthenticator"
Populating multiAuthenticator allows per-user rules to be configured regarding
the authentication scheme used. We will choose this option.
Proposed setting:
<property name="authenticator" ref="multiAuthenticator" />
The bean ids "multiAuthenticator" , "authnContextSource" & "authnLdapTemplate"
need to be moved from the xml comment into the main part of the xml document.
The bean id "multiAuthenticator" contains the default text:
<entry key="users">
<list>
<value>admin</value>
</list>
</entry>
<entry key="authenticator" value-ref="localAuthenticator"></entry>
This setting causes the default user admin to be able to authenticate against
the built in authentication database. In a properly designed and implemented
Active Directory environment, it should never be necessary to attempt to login
using the built in authentication database. Since any need for this
functionality is likely to occur in a disaster, we make that action as easy as
possible. NOTE: it is still necessary to know the password for the account that
is stored in the local authentication database. Preserving knowledge of that
password is left as an exercise for the reader
Proposed setting:
<value>SomeRandomString-admin</value>
The beain id "authnContextSource" contains a number of settings that must be
customized for your Active Directory environment:
Add a property not already existing:
<property name="referral" value="follow" />
This setting should mitigate the risk of authentication failures due to
"javax.naming.PartialResultException: Unprocessed Continuation Reference(s).
More information is available:
http://pe-kay.blogspot.com.au/2013/01/webpasswordsafe-ldap-authentication.html
http://technet.microsoft.com/en-us/library/cc978014.aspx
<property name="url" value="ldap://localhost:389" />
Using ldap (as opposed to ldaps) introduces the risk that the password of every
user logging in to WebPasswordSafe will be transmitted in clear text across
your network. As this situation is so undesirable, clear text ldap
configurations will not be discussed further.
Proposed setting: ldaps://
Specifying a port number when connecting to Active Directory ldaps can have
unexpected results. If you intend to connect to the ldap directory over ssl, no
port number should be specified
If you intend to connect to the Global Catalog ldap directory over ssl, ":3269"
should be specified
In a configuration where certificates are being manually deployed, using a
Global Catalog can help to minimise the number of directory severs that will be
queried. This in turn can minimise the risk of requesting a response from a
server that does not have the appropriate certificates installed. More
information about Global Catalog search:
http://technet.microsoft.com/en-us/library/cc978012.aspx.
Proposed setting: <none - no port setting proposed>
Assuming you are not deploying WebPasswordSafe on a domain controller,
localhost could be replaced using one of two options:
Fully Qualified Domain Name (FQDN) of a domain controller in your directory, eg:
Dc1.contoso.com
FQDN of your directory, eg:
Contoso.com
Proposed setting: contoso.com
Complete proposed setting:
"ldaps://contoso.com"
Ldap bind & user lookup account
<property name="userDn" value="cn=Manager,dc=webpasswordsafe,dc=com" />
<property name="password" value="" />
For each directory user that attempts to authenticate WebPasswordSafe uses the
account defined above to lookup the Distinguished Name of that user. Assuming
default AD permissions are in place, this account needs nothing more than
membership of "Domain Users". Assuming you created a "WebPasswordSafe" user in
the default "Users" folder.
The proposed configuration is:
<property name="userDn" value="CN=WebPasswordSafe,CN=Users,DC=contoso,DC=com" />
<property name="password" value="WebPasswordSafe-account-password" />
It is worth remembering that some characters need special handling in xml. For
example, if the lookup account is defined in an OU in the root of the directory
called "Service & Special Accounts", the proposed configuration would need to
be modified to:
<property name="userDn" value="CN=WebPasswordSafe,CN=Service & Special
Accounts,DC=contoso,DC=com" />
<property name="password" value="WebPasswordSafe-account-password" />
<bean id="ldapAuthenticator"
Contains the properties:
Filter - If you configure this property with:
<property name="filter" value="(&(objectclass=person)(sAMAccountName=$1))"
/>
Your users would need to be defined in WebPasswordSafe using their
sAMAccountName. sAMAccountName is the value displayed in Active Directory Users
& Computers on the Account tab. Other potential properties to use for
authentication can be explored using LDP:
http://technet.microsoft.com/en-us/library/cc772839(v=ws.10).aspx
Base
Assuming you want all users in the domain to be potential WebPasswordSafe
users, the proposed setting is:
<property name="base" value="dc=corpneta,dc=com" />
It is worth remembering that all users of WebPasswordsafe need to be created /
defined there - it is not sufficient to have an Active Directory account to be
able to login.
At this point, you should be able to start your java servlet container, and
have WebPasswordSafe attempt ldaps authentication. If user contoso\Alice
(Alice@Contoso.com) exists in the domain, and should be granted access to
WebPasswordSafe, then a user with UserName "Alice" should exist in
WebPasswordSafe.
If it still fails to work:
As per:
http://webpasswordsafe.googlecode.com/svn-history/r174/trunk/docs/AdministratorG
uide.html
/webpasswordsafe/src/main/resources/log4j.xml
can be edited to increase log file verbosity:
This means you will have to build WebPasswordSafe from source (this change is
not possible using the webpasswordsafe-sample-1.3.war - but you weren't going
to use that anyway, right?)
DEBUG is likely the log level you wish to configure
Be aware that DEBUG logging can cause passwords to be logged; be sure not to
run this configuration in production, and to delete log files before reverting
to a production configuration.
Example log entries, and possible causes:
2014-05-24 08:09:20,011 DEBUG [http-nio-443-exec-5]: ldap error authenticating:
simple bind failed: localhost:636; nested exception is
javax.naming.CommunicationException: simple bind failed: contoso.com:636 [Root
exception is javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find
valid certification path to requested target]
(copied & adapted from
https://code.google.com/p/webpasswordsafe/wiki/AdminGuide)
As per the referenced page, the above error suggests your java cacerts file
does not contain your CA certificate, or possibly an intermediary CA
certificate is missing
2014-05-24 08:49:29,089 DEBUG [http-nio-443-exec-5]: Got Ldap context on server
'ldaps://dc1.contoso.com:636'
2014-05-24 08:49:29,245 DEBUG [http-nio-443-exec-5]: ldap error authenticating:
nested exception is javax.naming.PartialResultException [Root exception is
javax.naming.CommunicationException: simple bind failed: contoso.com:636 [Root
exception is java.net.SocketException: Connection reset]]
In the above case, dc1.contoso.com had a certificate installed for ldaps, but
another domain controller did not. Ensuring all domain controllers had a
certificate in place for ldaps resolved the issue. Another workaround that
solved the issue in the test environment was to connect to
"ldaps://dc1.contoso.com:3269" - (GC ldap)
2014-05-25 19:40:08,246 DEBUG [http-nio-443-exec-4]: ldap error authenticating:
Uncategorized exception occured during LDAP processing; nested exception is
javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr:
DSID-0C090724, comment: In order to perform this operation a successful bind
must be completed on the connection., data 0, v23f0 ]; remaining name
'dc=contoso,dc=com'
In the above case, the password property in authnContextSource was missing
Webpasswordsafe-service.xml file created by following the steps in this guide:
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2008-2013 Josh Drummond
This file is part of WebPasswordSafe.
WebPasswordSafe is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
WebPasswordSafe is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with WebPasswordSafe; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- core services -->
<context:component-scan base-package="net.webpasswordsafe.server.service" />
<!-- pluggable services -->
<bean id="passwordGenerator"
class="net.webpasswordsafe.server.plugin.generator.SimpleRandomPasswordGenerator" >
<property name="passwordLength" value="20" />
<property name="allowLowercase" value="true" />
<property name="allowUppercase" value="true" />
<property name="allowNumeric" value="true" />
<property name="specialChars" value="!@#$%^*" />
<property name="excludeChars" value="O0l1" />
</bean>
<bean id="authenticator"
class="net.webpasswordsafe.server.plugin.authentication.IPLockoutAuthenticator">
<property name="authenticator" ref="userLockoutAuthenticator" />
<property name="failedLoginThreshold" value="10" />
<property name="lockoutLength" value="1440" />
<property name="whitelist">
<set>
<value>127.0.0.1</value>
</set>
</property>
</bean>
<bean id="userLockoutAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.UserLockoutAuthenticator">
<property name="authenticator" ref="multiAuthenticator" />
<property name="failedLoginThreshold" value="5" />
<property name="whitelist">
<set>
<value>admin</value>
</set>
</property>
</bean>
<bean id="localAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.LocalAuthenticator">
</bean>
<bean id="multiAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.CompositeAuthenticator">
<property name="authenticators">
<list>
<map>
<entry key="users">
<list>
<value>SomeRandomString-admin</value>
</list>
</entry>
<entry key="authenticator" value-ref="localAuthenticator"></entry>
</map>
<map>
<entry key="anyUser" value="true" />
<entry key="authenticator" value-ref="ldapAuthenticator"></entry>
</map>
</list>
</property>
</bean>
<bean id="authnContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="referral" value="follow" />
<property name="url" value="ldaps://contoso.com" />
<property name="userDn" value="CN=WebPasswordSafe,CN=Users,DC=contoso,DC=com" />
<property name="password" value="WebPasswordSafe-account-password" />
</bean>
<bean id="authnLdapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="authnContextSource" />
</bean>
<bean id="ldapAuthenticator" class="net.webpasswordsafe.server.plugin.authentication.LdapAuthenticator">
<property name="ldapTemplate" ref="authnLdapTemplate" />
<property name="filter" value="(&(objectclass=person)(sAMAccountName=$1))" />
<property name="base" value="dc=corpneta,dc=com" />
</bean>
<!-- ## Uncomment to use a different authenticator implementation
<bean id="demoAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.DemoAuthenticator">
<property name="demoPassword" value="demo" />
</bean>
<bean id="rsaAuthenticator"
class="net.webpasswordsafe.server.plugin.authentication.RsaSecurIdAuthenticator">
<property name="configPath" value="/usr/local/rsa/rsa_api.properties" />
</bean>
-->
<bean id="roleRetriever"
class="net.webpasswordsafe.server.plugin.authentication.LocalRoleRetriever">
<property name="adminUsers">
<set>
<value>admin</value>
</set>
</property>
</bean>
<bean id="authorizer"
class="net.webpasswordsafe.server.plugin.authorization.DefaultAuthorizer">
<property name="allowAdminBypassPasswordPermissions" value="true" />
</bean>
<bean id="auditLoggerLog4j"
class="net.webpasswordsafe.server.plugin.audit.Log4jAuditLogger">
<property name="delimiter" value=" || " />
</bean>
<bean id="auditLoggerDatabase"
class="net.webpasswordsafe.server.plugin.audit.DatabaseAuditLogger" />
<bean id="auditLogger"
class="net.webpasswordsafe.server.plugin.audit.CompositeAuditLogger">
<property name="auditLoggers">
<list>
<ref bean="auditLoggerLog4j" />
<ref bean="auditLoggerDatabase" />
</list>
</property>
</bean>
<!-- Encryption related settings, these should not be changed after initial deployment otherwise
data may be corrupted or unreadable -->
<!-- ## Uncomment for Jasypt Encryption -->
<bean id="digester" class="net.webpasswordsafe.server.plugin.encryption.JasyptDigester">
<property name="passwordEncryptor" ref="passwordEncryptor" />
</bean>
<bean id="passwordEncryptor" class="org.jasypt.util.password.StrongPasswordEncryptor" />
<bean id="encryptor" class="net.webpasswordsafe.server.plugin.encryption.JasyptEncryptor">
<property name="stringEncryptor" ref="strongEncryptor" />
</bean>
<bean id="bcProvider" class="org.bouncycastle.jce.provider.BouncyCastleProvider" />
<bean id="strongEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="algorithm" value="${encryptor.jasypt.algorithm}" />
<property name="provider" ref="bcProvider" />
<property name="password" value="${encryptor.jasypt.password}" />
<property name="keyObtentionIterations" value="${encryptor.jasypt.keyObtentionIterations}" />
</bean>
<!-- ## Uncomment for OWASP-ESAPI Encryption -->
<!--
<bean id="digester" class="net.webpasswordsafe.server.plugin.encryption.EsapiDigester">
<constructor-arg index="0" value="${encryptor.esapi.useClasspath}" />
<constructor-arg index="1" value="${encryptor.esapi.resourceDir}" />
</bean>
<bean id="encryptor" class="net.webpasswordsafe.server.plugin.encryption.EsapiEncryptor">
<constructor-arg index="0" value="${encryptor.esapi.useClasspath}" />
<constructor-arg index="1" value="${encryptor.esapi.resourceDir}" />
</bean>
-->
</beans>
Original issue reported on code.google.com by e...@tunedglobal.com on 25 May 2014 at 11:17
Original issue reported on code.google.com by
e...@tunedglobal.com
on 25 May 2014 at 11:17