Spring LDAP GSS-API - spring-ldap

I am trying to connect to AD using Spring LDAP. I am able to connect to a server with Simple Authentication but for one of the server only GSS-API authentication is active. I am not able to connect to this server using Spring LDAP.
Could someone help guiding me to resolve this issue? Any help is really appreciated!
Below is the my code;
#Configuration
#Profile("prod")
public class AppProdConfig {
#Bean
public LdapContextSource ldapContextSource(){
LdapContextSource ldapContextSource = new LdapContextSource();
ldapContextSource.setUrls(new String[]{"ldaps://1.1.1.1:636","ldaps://2.2.2.2:636"});
ldapContextSource.setBase("ou=users,ou=usersAndGroups,dc=ecommerce,dc=company");
ldapContextSource.setUserDn("user");
ldapContextSource.setPassword("password123");
return ldapContextSource;
}
#Bean
public LdapTemplate ldapTemplate(LdapContextSource ldapContextSource){
LdapTemplate ldapTemplate = new LdapTemplate(ldapContextSource);
return ldapTemplate;
}
}

Spring LDAP does not support this. My library will do this for you.

Related

Spring Reactive Cassandra, use custom CqlSession

How do we use a custom CqlSession on a Spring Webflux application combined with Spring starter reactive Cassandra please?
I am currently doing the following, which is working perfectly:
public class BaseCassandraConfiguration extends AbstractReactiveCassandraConfiguration {
#Bean
#NonNull
#Override
public CqlSessionFactoryBean cassandraSession() {
final CqlSessionFactoryBean cqlSessionFactoryBean = new CqlSessionFactoryBean();
cqlSessionFactoryBean.setContactPoints(contactPoints);
cqlSessionFactoryBean.setKeyspaceName(keyspace);
cqlSessionFactoryBean.setLocalDatacenter(datacenter);
cqlSessionFactoryBean.setPort(port);
cqlSessionFactoryBean.setUsername(username);
cqlSessionFactoryBean.setPassword(passPhrase);
return cqlSessionFactoryBean;
}
However, I would like to use a custom session, something like:
CqlSession session = CqlSession.builder().build();
How do we tell this configuration to use it?
Thank you
Option 1:
If you are looking to completely override the auto configured CqlSession bean, you can do so by providing your own CqlSesson bean ie.
#Bean
public CqlSession cassandraSession() {
return CqlSession.builder().withClientId(MyClientId).build();
}
The downside of override the entire bean is that you will lose the ability to configure this session via application properties and you will lose the defaults spring boot ships with.
Option 2:
If you want to leave the default values provided by spring boot and have the ability to configure the session via application properties you can use CqlSessionBuilderCustomizer to provide specific custom configurations to the CqlSession. This can be achieved by defining a bean of that type ie:
#Bean
public CqlSessionBuilderCustomizer myCustomiser() {
return cqlSessionBuilder -> cqlSessionBuilder.withClientId(MyClientId);;
}
My personal preference is option 2 as it maintains the functionality provided by spring boot which in my opinion results in an easier to maintain application over time.

TLS and Client Auth in Spring Integration

I'm experimenting with TLS, mutual TLS, and host verification in my app and am having some confusion with the behavior of the Integration components. I'm using a TcpNetClientConnection Factory and a TcpNetServerConnectionFactory. I don't have a solid understanding of how these components are interacting under the hood, and want to make sure my authentication is working (or not working) as expected.
#Bean
public TcpNetClientConnectionFactory tcpClientConnectionFactory() {
TcpNetClientConnectionFactory factory =
new TcpNetClientConnectionFactory(upstreamHost, upstreamPort);
factory.setTcpSocketFactorySupport(tcpSslSocketFactorySupport);
factory.setTcpSocketSupport(new DefaultTcpSocketSupport(isHostVerificationEnabled));
return factory;
}
#Bean
TcpNetServerConnectionFactory testTcpServerConnectionFactory() {
TcpNetServerConnectionFactory factory = new TcpNetServerConnectionFactory(upstreamPort);
factory.setTcpSocketFactorySupport(tcpSslSocketFactorySupport);
factory.setTcpSocketSupport(new DefaultTcpSocketSupport(isHostVerificationEnabled));
return factory;
}
#Bean
public DefaultTcpNetSSLSocketFactorySupport tcpSslSocketFactorySupport() {
TcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport(keyStore, trustStore, keyStorePassword,
trustStorePassword);
return new DefaultTcpNetSSLSocketFactorySupport(sslContextSupport);
}
It seems like the only way to create a TcpSSLContextSupport is to pass it both a keystore and a truststore. Why is the keystore necessary? If my server doesn't require client auth, I shouldn't have to pass a keystore to my client connection factory. The client factory should only have to have a truststore, to verify the server it's talking to.
In regard to client auth, does the server connection factory in my configuration require client auth? According to the reference, in order to enable client auth, I would need to override the postProcessServerSocket() method. However, I was getting SSL read exceptions until I added the client's cert to my server's truststore. Why was that necessary, since I haven't enabled client auth yet?
Finally, if the client connection factory does have a private key entry in its keystore, does it automatically utilize that key when opening a connection to the server? Or only if the server mandates client auth? It seems like my client connection factory is using its private key, even though I haven't set anything to mandate client auth yet.
The server doesn't require clientAuth by default; there's an example in the documentation about how to require it.
See this test case.
If I comment out the code at line 437
server.setTcpSocketSupport(new DefaultTcpSocketSupport(false) {
#Override
public void postProcessServerSocket(ServerSocket serverSocket) {
// ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
}
});
The test fails with
java.lang.AssertionError:
Expecting code to raise a throwable.
at org.springframework.integration.ip.tcp.connection.SocketSupportTests.testNetClientAndServerSSLDifferentContexts(SocketSupportTests.java:414)
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> testNetClientAndServerSSLDifferentContexts(true));
Yes, the default implementation requires a keystore but it can be one that is empty or doesn't contain a client key when client auth is not needed. We should probably relax that; feel free to open a GitHub issue to request it. And/Or you can simply provide your own implementation.
In the test case (that expects to fail) we use a keyStore that doesn't contain the client cert.
TcpSSLContextSupport clientSslContextSupport = new DefaultTcpSSLContextSupport(
badClient ? "server.ks" : "client.ks",
"client.truststore.ks", "secret", "secret");
Note that the server socket also has setWantsClientAuth - maybe that defaults to true which would explain what you observed (failure if you provide a cert on the client side). I haven't tested that; try setting it to false.

Spring Integration: Get rid of code duplication for setting up beans

For my SFTP client project, I am using spring integration. We have different clients and have to connect to different SFTP servers, but, all of the logic is same, so I have abstracted them out into AbstractSFTPEndPoint. Each client-specific class implements getClientId(), which is used by AbstractSFTPEndPoint to get client-specific details like SFTP credentials.
However, the entire logic is same for all the clients, but I am still having to implement specific classes for each client. This is mainly because we need separate "MessageSource" for each client.
How can I get rid of this duplication?
public class SFTPEndPointForClientAAAA extends AbstractSFTPEndPoint {
public String getClientId(){
return "clientAAAA";
}
#Bean(name = "channelForClientAAAA")
public QueueChannel inputFileChannel() {
return super.inputFileChannel();
}
#ServiceActivator(inputChannel = "channelForClientAAAA", poller = #Poller(fixedDelay = "500"))
public void serviceActivator(Message message) {
super.serviceActivator(message);
}
#Bean(name = "messageSourceForClientAAAA")
#InboundChannelAdapter(value = "channelForClientAAAA",
poller = #Poller(fixedDelay = "50", maxMessagesPerPoll = "2"))
public MessageSource messageSource() {
return super.messageSource();
}
}
Basically I have a bunch of SFTP hosts to connect to and apply same logic. I want that to be done automatically without having to implement class for each SFTP host.
See the dynamic ftp sample. It uses XML but the same techniques apply to Java configuration. It uses outbound adapters; inbound are a little more complicated because you might need to hook them into a common context. There are links in the readme for how to do that.
However, I recently answered a similar question for multiple IMAP mail adapters using Java configuration and then a follow-up question.
You should be able to use the technique used there.

Spring Integration DSL Channel Support

In the current release 1.0.2 of spring integration dsl I can see some of the basic channels are not present like ReST/HTTP, TCP/UDP, JDBC, MQTT, etc.
Just wanted to know whether this protocols/channel are in roadmap or it has been excluded deliberately.
PS: I might be sounding stupid with posted question but just wanted to know the reason.
From one side you should understand that it is enough big work to address them all. For example HTTP module is on our radar for the 1.1 release.
From other side the Spring Integration Java DSL is just an edition to the existing Spring Java & Annotation configuration, so any #Bean definition is valid there, too.
With those desired protocols you can go ahead and configure their components as #Bean and refer them from the .handle() or .from() EIP-methods.
For example:
#Bean
public MessageSource<Object> jdbcMessageSource() {
return new JdbcPollingChannelAdapter(this.dataSource, "SELECT * FROM foo");
}
#Bean
public IntegrationFlow myFlow() {
return IntegrationFlows.from(jdbcMessageSource())
.split(...)
.transform(...)
.handle(new MqttPahoMessageHandler("tcp://localhost:1883", "si-test-out"))
.get();
}

How to access IBM Connection with apache Wink

I am trying to use Apache Wink to get Service Document from an IBM host but I always get error 403 Forbidden. Here is my code :
import org.apache.wink.client.Resource;
import org.apache.wink.client.RestClient;
public class CommunityEvents {
private String uri = "https://w3-connections.ibm.com/profiles/atom/search.do?name=Nam,+Vu+Hoai";
public CommunityEvents() {
RestClient restClient = new RestClient();
Resource resource = restClient.resource(uri);
System.out.println(resource.get().getMessage());
}
public static void main(String[] args) {
new CommunityEvents();
}
}
The link is working fine when I put it into browser address. I have tried with other https and they worked.
Can someone correct my code or tell me what I missed ? what I need to do to access the link above ?
Thank you so much !
is the URL trusted by your JVM? I imagine it's a CACERTS issue. You'll want to extract the certificate using your browser, and use the keytool to import it into your JVM CACERTS.
Also Wink supports JSON and other resource styles, make sure you have the right library for ATOM+XML which is the current resource URL you selected.

Resources