Dynamically configure LDAP server Properties using text file - spring

I currently working with LDAP using Spring Security with XML Configuration. I need advice about how can i put attributes like URL, port, manager-dn and password in external file.
<ldap-server id="ldapServer"
url="ldap://xxxxx:3268/dc=xxxxx,dc=com" port="3268"
manager-dn="xxxxx#xxxxx.com" manager-password="xxxxxx" />
i mean, we need to put it externally because our other team (implementation team) need to change those properties values to go live without changing anything in war/binary file. Thank you

Done, thanks to this post
Steps :
create properties file and put it in the server
####### LDAP ##############
ldap.urls= ldap://xxxx:3268/dc=xxxxx,dc=com
ldap.manager-dn= xxxx#xxxxx.com
ldap.manager-password= xxxx
create properyplaceholder bean
<beans:bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<beans:property name="location">
<beans:value>file:///opt/xxxx/xxxxx/application.properties</beans:value>
</beans:property>
</beans:bean>
access the properties from XML beans
<ldap-server id="ldapServer" url="${ldap.urls}" port="3268"
manager-dn="${ldap.manager-dn}"
manager-password="${ldap.manager-password}" />

Related

Spring Context File Reuse with Different Properties

I have a fairly straight-forward spring-integration app that polls an external FTP site, processes any found files using some internal business logic and then posts a results file via FTP. Currently when we add a new customer, we copy the XML config file and a corresponding properties file and change a prefix on all bean definitions, bean references and properties. We then add those to an XML config file that simply does imports for all existing customers and their properties:
<property-placeholder location="
file:config/application.properties
,file:config/test-customer1.properties
,file:config/test-customer2.properties
"/>
<import resource="test-customer1-context.xml" />
<import resource="test-customer2-context.xml" />
These xml files are identical except for a unique customer prefix in the bean names. Seems like there must be a way for me to reuse a single XML file (or a Java Config object) with different sets of properties. My first thought was to implement a custom CustomerScope, but I don't see how the scope implementation can know the proper customer.
Any ideas as to how to accomplish this?
As requested, sample of customer context file
<bean id="testClient1RequestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="${test.client1.in.queue}"/>
</bean>
<bean id="testClient1ResultsQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="${test.client1.results.queue}"/>
</bean>
...

Spring LdapAuthentication and Load roles from local database

I have Spring Security configured to authenticate against LDAP server.
<security:authentication-manager >
<security:ldap-authentication-provider user-dn-pattern="uid={0}" />
</security:authentication-manager>
After authentication I want to load roles from local database for the same user. How can I load local database roles using "ldap-authentication-provider"?
If I add the second authentication provider as below:
<security:authentication-manager >
<security:ldap-authentication-provider user-dn-pattern="uid={0}" />
<security:authentication-provider ref="daoAuthenticationProvider" />
</security:authentication-manager>
daoAuthenticationProvider added, but Spring does not use the second provider when first auth provider authenticates the user. Only if the first auth provider fails to authenticate it goes next in the list.
So basically look like we have to customize
<security:ldap-authentication-provider user-dn-pattern="uid={0}" />
to load ROLEs from local database.
Any suggestions? How should this be implemented?
An authentication provider must deliver a fully populated authentication token on successfull authentication, so it's not possible to use one provider to check the user's credentials, and another one to assign authorities (roles) to it.
You can however customize an ldap auth provider to fetch user roles from database instead of the default behaviour (searching for the user's groups in ldap). The LdapAuthenticationProvider has two strategies injected: one that performs the authentication itself (LdapAuthenticator), and another one that fetches the user's authorities (LdapAuthoritiesPopulator). You can achieve your requirements if you supply an LdapAuthoritiesPopulator implementation that loads roles from database. In case you already have a UserDetailsService working against the database, you can easily integrate that by wrapping it in a UserDetailsServiceLdapAuthoritiesPopulator and injecting it in the LdapAuthenticationProvider.
Since this configuration is rather uncommon, the security xml namespace doesn't provide tags/attributes to set it up, but the raw bean config isn't too complicated. Here is the outline:
1) I suppose you have an ldap-server somewhere in your config. It's important to assign and id to it, which will allow us to reference it later.
<security:ldap-server url="..." id="ldapServer" .../>
2) From the authentication-manager section, you will only refer to the customized provider:
<security:authentication-manager>
<security:authentication-provider ref="customLdapAuthProvider"/>
</security:authentication-manager>
3) Now, the essential part:
<bean id="customLdapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg name="authenticator">
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg name="contextSource" ref="ldapServer"/>
<property name="userDnPatterns">
<list>
<value>uid={0}</value>
</list>
</property>
</bean>
</constructor-arg>
<constructor-arg name="authoritiesPopulator">
<bean class="org.springframework.security.ldap.authentication.UserDetailsServiceLdapAuthoritiesPopulator">
<constructor-arg name="userService" ref="userService"/>
</bean>
</constructor-arg>
</bean>
The authenticator is basically the same as the one that would be created by the namespace config. (Note the contextSource attribute referencing the ldap server.)
The authoritiesPopulator is a simple wrapper around your userService implementation which is supposed to be defined somewhere in your config.

Good example of Spring Configuration using java.util.prefs or Commons Configuration

One application I'm working on has several URLs and other information that is instance specific. The first pass uses a typical Spring PropertyPlaceholderConfigurer with a properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties"/>
</bean>
The main issue with this is of course the property file is an artifact that must be checked in, and for starting a new instance would require updating that artifact. For a streamline deployment, I would like to have the ApplicationContext bootstrap itself based on database table(s). I have seen solutions like this forum post, does anyone here know of better tools or is this defacto approach to this problem? I would also like to be able to update/reload the settings at runtime using JMX or other facilities, but having to restart the app after changes to the database would still be a better solution to the current one.
The way we did it was to put some configuration information in the environment and then pull the relevant info from there.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="searchSystemEnvironment" value="true" />
</bean>
If configuration changes then the app will need to be restarted. Can also put all the different configurations into the environment and nest the variables like the following:
<bean id="db" class="org.DataSource"
p:databaseServer="${${MODE}_DBSERVER}"
p:databaseName="${${MODE}_DBNAME}" />
where $MODE = dev, qa, etc.

external config based on context path

I would like to deploy multiple independent copies of a particular web-app on the same tomcat server under different context paths. Each web-app will need different configuration settings (database name, password, etc), but I would like to keep the wars exactly identical.
My plan was to have the app figure out its context path on startup, then read a specific .properties file outside of tomcat identified by the context path. For example, if a war was deployed to {tomcat path}/webapps/pineapple, then I would want to read /config/pineapple.properties
I've been trying to find a way to inject an instance of ServletContext via spring (3), but all the advice I've seen so far use the deprecated ServletContextFactoryBean.
Is there a better way to get the context path injected or better way to load external files based on the context path?
With the help of ServletContextAttributeFactoryBean and Spring EL, you can reference ServletContext init parameters (<context-param> in web.xml) like that:
#{contextAttributes.myKey}
This allows you to use PropertyPlaceHolderConfigurer and load property files from arbitrary, user-defined locations:
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="#{contextParameters.APP_HOME}/conf/app.properties"/>
</bean>
The corresponding definition of the ServletContext init parameter in Tomcat's context.xml:
<Parameter name="APP_HOME" value="file:/test" override="false"/>
Or in your app's web.xml:
<context-param>
<param-name>APP_HOME</param-name>
<param-value>file:/test</param-value>
</context-param>
This should be the solution.
<bean name="envConfig" class="EnvironmentConfiguration">
<property name="locations">
<list>
<value>file:///#{servletContext.contextPath}.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
Extend Propertyplaceholderconfigurer to use DB to pick up the values. Example here
Load the actual values of the settings (database name, password etc) to the db as part of seed data
When your web-app's app ctx is being initialized, the properties are resolved from the DB
This is the approach we have been following and works great. If you can switch to Spring 3.1 then it has support for Environment Profiles which may be useful for you.

How to pass global properties in ibatis

I'm developing a Spring MVC application using ibatis for the database interaction layer. I'd like to be able to set the name of the database via a properties file in my classpath (or via the spring xml configuration) so I can change the database on the fly for a certain application and can be changed by setting the parameter and redeploying the application.
What I'm looking for is being able to set the database name on an existing database. Lets say I have a system called DB1 with databases: user, user_qa, and user_dev. I'd like to be able to parameterize the SQLs so that instead of doing:
SELECT * FROM user.Logins
I'd do
SELECT * FROM $database.user$.Logins
So I can change the database.user property and redeploy the application instead of rewriting a ton of SQL statements each time I changed the name of the databases.
Pretty simple to do in Spring. Say you have a basic conf file [database.properties]:
jdbc.username = user
jdbc.host = mydbserver.com
Then in your Spring config xml file :
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
</bean>
Now where you want those variables substitute the name in the config file:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="host"><value>${jdbc.host}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
</bean>

Resources