Apache NiFi LDAPS configuration issue - security

I have spent a whole day trying to figure out this odd issue. I have my NiFi instance stand up on a Linux server. I configured ldap-provider in login-identity-providers.xml as below
<provider>
<identifier>ldap-provider</identifier>
<class>org.apache.nifi.ldap.LdapProvider</class>
<property name="Authentication Strategy">SIMPLE</property>
<property name="Manager DN"></property>
<property name="Manager Password"></property>
<property name="TLS - Keystore">/Data/ssl/server_keystore.jks</property>
<property name="TLS - Keystore Password">changeit</property>
<property name="TLS - Keystore Type">JKS</property>
<property name="TLS - Truststore">/Data/ssl/server_truststore.jks</property>
<property name="TLS - Truststore Password">changeit</property>
<property name="TLS - Truststore Type">JKS</property>
<property name="TLS - Client Auth"></property>
<property name="TLS - Protocol">TLSv1.2</property>
<property name="TLS - Shutdown Gracefully"></property>
<property name="Referral Strategy">FOLLOW</property>
<property name="Connect Timeout">10 secs</property>
<property name="Read Timeout">10 secs</property>
<property name="Url">ldaps://myserver.hostname:636</property>
<property name="User Search Base">ou=people,dc=xxx,dc=net</property>
<property name="User Search Filter">cn={0}</property>
<property name="Authentication Expiration">12 hours</property>
When I starting nifi, I got a login page prompted first. However, I kept getting
2016-07-28 00:17:43,527 ERROR [NiFi Web Server-64] org.apache.nifi.ldap.LdapProvider myserver.hostname:636; nested exceptin is javax.naming.CommunicationException: myserver.hostname: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]
I then tried to use jvm argument in bootstrap.conf as
java.arg.15=-Djavax.net.ssl.trustStore=/Data/ssl/server_truststore.jks
It worked perfectly fine.
I also tried SSLPoke.class with the same truststore vm argument, it also worked fine.
java -Djavax.net.ssl.trustStore=/Data/ssl/server_truststore.jks SSLPoke myserver.hostname 636
"Successfully connected"
Now my question is why my configuration in NiFi login-identity-providers.xml doesn't work?

Unfortunately, NiFi does not support LDAPS currently. There is a JIRA [1] to build this capability. SIMPLE (plaintext) or START_TLS are the only valid options. Further, the SSL context configuration options are only considered when the Authentication Strategy is START_TLS.
[1] https://issues.apache.org/jira/browse/NIFI-2325

#davy_wei,
while Matt's comment is correct, if you are for some reason restricted from using LDAP to you LDAP/AD server (e.g. firewall rules), one option is to use stunnel or socat to tunnel between the protected LDAP and NiFi's LDAP client.
sample stunnel config would look like:
...
[ldap2ldaps]
accept = 127.0.0.1:whatever_port_you_want
client = yes
connect = your.real.ldaps.fqdn.or.ip:636
...
Remember this is the basic config. You may want to fine tune your stunnel to match your security requirements (e.g. restrict to particular ciphers, TLS version, etc)

Related

Configuring Service Discovery for Azure in Hazelcast

The Problem:
I'm setting up hazelcast AutoDiscovery feature to be used in Azure Environments. I am following the github document for the same: https://github.com/hazelcast/hazelcast-azure
But I am getting the following error:
Exception in thread "main" com.hazelcast.config.InvalidConfigurationException: Invalid configuration
at com.hazelcast.spi.discovery.impl.DefaultDiscoveryService.loadDiscoveryStrategies(DefaultDiscoveryService.java:147)
.....
com.hazelcast.core.server.StartServer.main(StartServer.java:46)
Caused by: com.hazelcast.config.properties.ValidationException: There is no discovery strategy factory to create 'DiscoveryStrategyConfig{properties={group-name=****, client-secret=****, subscription-id=****, client-id=****, tenant-id=****, cluster-id=****}, className='com.hazelcast.azure.AzureDiscoveryStrategy', discoveryStrategyFactory=null}' Is it a typo in a strategy classname? Perhaps you forgot to include implementation on a classpath?
at com.hazelcast.spi.discovery.impl.DefaultDiscoveryService.buildDiscoveryStrategy(DefaultDiscoveryService.java:186)
...
I have tried the following properties:
<azure enabled="true">
<client-id>****</client-id>
<client-secret>****</client-secret>
<tenant-id>****</tenant-id>
<subscription-id>****</subscription-id>
<cluster-id>****</cluster-id>
<group-name>****</group-name>
</azure>
Since This was not working I even tried using discovery strategy with the following code snipppet:
<discovery-strategies>
<!-- class equals to the DiscoveryStrategy not the factory! -->
<discovery-strategy enabled="true" class="com.hazelcast.azure.AzureDiscoveryStrategy">
<properties>
<property name="client-id">****</property>
<property name="client-secret">****</property>
<property name="tenant-id">****</property>
<property name="subscription-id">****</property>
<property name="cluster-id">****</property>
<property name="group-name">****</property>
</properties>
</discovery-strategy>
</discovery-strategies>
Even switched the value of class from:
class="com.hazelcast.azure.AzureDiscoveryStrategy"
to
class="com.hazelcast.azure.AzureDiscoveryStrategyFactory"
I have tried the above with hazelcast versions 3.12.2, 3.12.1, 3.12 and 3.11.4 and all are giving same result.
Please suggest what I am doing incorrectly and what else is required.

TcpDiscoverySpi returns HTTP 401 - [Apache Ignite Cluster, installed on Azure Kubernetes Services]

EXCEPTION during IgniteClient startup (Springboot job):
TcpDiscoverySpi - Failed to get registered addresses from IP finder on start
Server returned HTTP response code: 401 for URL https://
I've created the service account, and read the token.
Then I0ve putted the value of che attribute token inside a file
Then I've tries with ignitevisorcmd to connect, but it's seems there is an error i'm not able to identify
Snippet of my "ignite-config.xml":
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<!--
Enables Kubernetes IP finder with default settings.
-->
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.kubernetes.TcpDiscoveryKubernetesIpFinder">
<property name="MasterUrl" value="https://XXXX-aks-001-ignitecluster-XXXXXXXX.hcp.westeurope.azmk8s.io"/>
<property name="AccountToken" value="C:\Users\XXXXXXXX\Desktop\TOP\token"/>
<property name="ServiceName" value="ignite"/>
</bean>
</property>
</bean>
</property>
What's wrong!!?!??!?!??!
Check if you have RBAC enabled cluster. If you do, you will have to give permission to your ignite pod to access the endpoints.
https://kubernetes.io/docs/admin/authorization/rbac/

jboss fuse 6.2.1 mq in fabric

i have jboss fuse 6.2.1 on linux server in a fabric mode with two child container. I created mq with this command
fabric:mq-create --group mur --assign-container risng1,risng2 --port tcp=61617 mur-broker
MQ profile mq-broker-mur.mur-broker ready
but i expect transport protocol will be configured with static port 61617 but it is dynamic.
In fuse 6.1 i modifed base template broker.xml
<transportConnector name="openwire" uri="tcp://0.0.0.0:${bindPort}"/>
bind port is configured in properties in profile. In fuse 6.2 does not work. My question is how to configured static port in fabric mode on jms broker?
I found closed issue https://issues.jboss.org/browse/FABRIC-1237
solved,
you can use custom template in your profile
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use system properties and fabric as variables in this configuration file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<bean class="io.fabric8.mq.fabric.ConfigurationProperties"/>
</property>
</bean>
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="${broker-name}" dataDirectory="${data}" start="false" restartAllowed="false">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" producerFlowControl="true">
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
<policyEntry queue=">" producerFlowControl="true" memoryLimit="1mb">
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<persistenceAdapter>
<kahaDB directory="${data}/kahadb"/>
</persistenceAdapter>
<plugins>
<jaasAuthenticationPlugin configuration="karaf" />
</plugins>
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70"/>
</memoryUsage>
<storeUsage>
<storeUsage limit="500 mb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="500 mb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<transportConnectors>
<transportConnector name="openwire" uri="tcp://${bindAddress}:61617"/>
</transportConnectors>
</broker>
</beans>
and the edit properties
group = mur
broker-name = mur-broker
connectors=openwire
kind = MasterSlave
data = ${runtime.data}mur-broker
config=profile\:broker-mur.xml
config.checksum=${checksum:profile\:broker-mur.xml}
standby.pool=default
bindAddress=0.0.0.0
bindPort=61617

Failed to serialize object GridSecurityContext on local node

While launching a local GridGain instance in a local node for the sake of testing I'm getting the following
class org.gridgain.grid.GridException: Failed to start SPI: GridTcpDiscoverySpi [locPort=47500, locPortRange=100, statsPrintFreq=0, netTimeout=5000, sockTimeout=2000, ackTimeout=5000, maxAckTimeout=600000, joinTimeout=0, hbFreq=2000, maxMissedHbs=1, threadPri=10, storesCleanFreq=60000, reconCnt=10, topHistSize=1000, gridName=null, locNodeId=dd235392-85b2-4f13-8a36-c433c5053c84, marsh=GridJdkMarshaller [], gridMarsh=org.gridgain.grid.marshaller.optimized.GridOptimizedMarshaller#56589a42, locNode=GridTcpDiscoveryNode [id=dd235392-85b2-4f13-8a36-c433c5053c84, addrs=[0:0:0:0:0:0:0:1, 127.0.0.1], sockAddrs=[/0:0:0:0:0:0:0:1:47500, /127.0.0.1:47500], discPort=47500, order=0, loc=true, ver=GridProductVersion [major=6, minor=1, maintenance=6, revTs=1401961981]], locAddr=null, locHost=0.0.0.0/0.0.0.0, ipFinder=GridTcpDiscoveryVmIpFinder [addrs=[/127.0.0.1:0], super=GridTcpDiscoveryIpFinderAdapter [shared=false]], metricsStore=null, spiState=CONNECTING, ipFinderHasLocAddr=true, recon=false, joinRes=GridTuple [val=null], nodeAuth=org.gridgain.grid.kernal.managers.discovery.GridDiscoveryManager$3#6bdf5fb8, gridStartTime=0]
at org.gridgain.grid.kernal.managers.GridManagerAdapter.startSpi(GridManagerAdapter.java:221)
at org.gridgain.grid.kernal.managers.discovery.GridDiscoveryManager.start(GridDiscoveryManager.java:371)
at org.gridgain.grid.kernal.GridKernal.startManager(GridKernal.java:1523)
... 8 more
Caused by: class org.gridgain.grid.spi.GridSpiException: Failed to authenticate local node (will shutdown local node).
at org.gridgain.grid.spi.discovery.tcp.GridTcpDiscoverySpi.joinTopology(GridTcpDiscoverySpi.java:1507)
at org.gridgain.grid.spi.discovery.tcp.GridTcpDiscoverySpi.spiStart0(GridTcpDiscoverySpi.java:994)
at org.gridgain.grid.spi.discovery.tcp.GridTcpDiscoverySpi.spiStart(GridTcpDiscoverySpi.java:916)
at org.gridgain.grid.kernal.managers.GridManagerAdapter.startSpi(GridManagerAdapter.java:218)
... 10 more
You can find the full stack trace at this link http://pastebin.com/7D17vuCY
I've tried also to configure a local IP Finder like this, but with no joy.
<property name="discoverySpi">
<bean class="org.gridgain.grid.spi.discovery.tcp.GridTcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.gridgain.grid.spi.discovery.tcp.ipfinder.vm.GridTcpDiscoveryVmIpFinder">
<property name="addresses" value="127.0.0.1"></property>
</bean>
</property>
</bean>
</property>
Any clue what's wrong with it?
OK, I've solved this by setting the localAddress property
<property name="discoverySpi">
<bean class="org.gridgain.grid.spi.discovery.tcp.GridTcpDiscoverySpi">
<property name="localAddress" value="127.0.0.1"/>
</bean>
</property>
The workaround is to run with -Djava.net.preferIPv4Stack=true or upgrade to GridGain 6.2.0.

Spring Security LDAP Bind Authenticator Verifies Only First 8 Characters of a Password

My web application uses Spring Security for authentication and authorisation.
The authentication is pre-authenticated via a corporate SSO. However, as a fallback, the application uses a form based login for authentication otherwise. This too is achieved using Spring Security by having a list of Authentication Providers configured in the deployment descriptor. Consider a typical scenario as described by a sequence as follows.
If the corporate SSO pre-authentication fails, the login page is presented to the user.
The entered credentials are submitted and since the SSOPreAuthentication Provider cannot find the principal (assuming SSO failure), the request is forwarded to the next Authentication Provider which is LdapAuthenticationProvider.
Here, what I have accidentally come across is that the LdapAuthenticationProvider that uses a BindAuthenticator, binds a username to the LDAP even if the password is partially correct (Only first 8 characters of the password are matched. The remaining are ignored).
Following is the configuration in my deployment descriptor, relevant to the discussion
<?xml version="1.0" encoding="UTF-8"?>
<!-- DO NOT EDIT FILE GENERATED BY BUILD SCRIPT (edit the config template version) -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"><security:http auto-config="false" access-denied-page="/accessDenied.htm" access-decision-manager-ref="accessDecisionManager">
<security:form-login login-page="/login.htm" authentication-failure-url="/login.htm?error=true" />
<security:logout logout-success-url="/login.htm" />
<security:intercept-url pattern="/**/*" access="ROLE_DENIED" />
</security:http>
<bean id="preauthSSOFilter" class="MySSOProcessingFilter">
<security:custom-filter position="PRE_AUTH_FILTER" />
<property name="principalRequestHeader" value="XX1" />
<property name="credentialsRequestHeader" value="XX2" />
<property name="ldapUserIdRequestHeader" value="XX3" />
<property name="ldapDNRequestHeader" value="XX4" />
<property name="ldapAuthenticator" ref="ldapBindAuthenticator" />
<property name="anonymousUserIfPrincipalRequestHeaderMissing" value="[none]" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="ldapContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" />
<bean id="ldapContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="ldap://myLDAP.com:983/o=something.com"/>
</bean>
<bean id="ldapAuthenticationProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
<security:custom-authentication-provider />
<constructor-arg ref="ldapBindAuthenticator" />
<constructor-arg ref="ldapAuthoritiesPopulator" />
</bean>
<bean id="ldapBindAuthenticator" class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
<constructor-arg ref="ldapContextSource"/>
<property name="userSearch" ref="ldapUserSearch" />
</bean>
<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value=""/>
<constructor-arg index="1" value="(uid={0})"/>
<constructor-arg index="2" ref="ldapContextSource" />
</bean>
<bean id="ldapAuthoritiesPopulator" class="org.springframework.security.ldap.populator.UserDetailsServiceLdapAuthoritiesPopulator">
<constructor-arg ref="userDetailsService" />
</bean>
And here is a trace of the logs for two scenarios:
When the password is completely wrong (All characters wrong)
18:34:13,599 DEBUG [FilterChainProxy] /j_spring_security_check at
position 4 of 8 in additional filter chain; firing Filter:
'org.springframework.security.ui.webapp.AuthenticationProcessingFilter[
order=700; ]' 18:34:13,599 DEBUG [AuthenticationProcessingFilter]
Request is to process authentication 18:34:13,599 DEBUG
[ProviderManager] Authentication attempt using
org.springframework.security.providers.ldap.LdapAuthenticationProvider
18:34:13,599 DEBUG [FilterBasedLdapUserSearch] Searching for user
'#username#', with user search [ searchFilter: '(uid={0})',
searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag:
false ] 18:34:13,599 DEBUG [AbstractContextSource] Principal: ''
18:34:13,943 DEBUG [AbstractContextSource] Got Ldap context on server
'ldap://myLDAP.com:983/o=something.com' 18:34:14,130 DEBUG
[DefaultSpringSecurityContextSource] Creating context with principal:
'uid=#username#, ou=people, l=AP, o=somthing.com' 18:34:14,458 DEBUG
[BindAuthenticator] Failed to bind as uid=#username#, ou=people, l=AP:
org.springframework.ldap.AuthenticationException: [LDAP: error code 49
- Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid
Credentials]
When the password is correct or partially(only first 8 characters match) correct
18:30:11,849 DEBUG [FilterChainProxy] /j_spring_security_check at
position 4 of 8 in additional filter chain; firing Filter:
'org.springframework.security.ui.webapp.AuthenticationProcessingFilter[
order=700; ]' 18:30:11,849 DEBUG [AuthenticationProcessingFilter]
Request is to process authentication 18:30:11,849 DEBUG
[ProviderManager] Authentication attempt using
org.springframework.security.providers.ldap.LdapAuthenticationProvider
18:30:11,849 DEBUG [FilterBasedLdapUserSearch] Searching for user
'#username#', with user search [ searchFilter: '(uid={0})',
searchBase: '', scope: subtree, searchTimeLimit: 0, derefLinkFlag:
false ] 18:30:11,849 DEBUG [AbstractContextSource] Principal: ''
18:30:12,193 DEBUG [AbstractContextSource] Got Ldap context on server
'ldap://myLDAP.com:983/o=something.com' 18:30:12,365 DEBUG
[DefaultSpringSecurityContextSource] Creating context with principal:
'uid=#username#, ou=people, l=AP, o=something.com' 18:30:12,708 DEBUG
[AbstractContextSource] Got Ldap context on server
'ldap://myLDAP.com:983/o=something.com'
Can someone explain this mysterious behavior ?

Resources