-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HBASE-24579: Failed SASL authentication does not result in an exception on client side #1921
HBASE-24579: Failed SASL authentication does not result in an exception on client side #1921
Conversation
…on on client side read input stream even if the auhentication is comleted add a test
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left few comments, please take a look
hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java
Outdated
Show resolved
Hide resolved
hbase-client/src/main/java/org/apache/hadoop/hbase/security/HBaseSaslRpcClient.java
Outdated
Show resolved
Hide resolved
catch (Exception e){ | ||
if(e instanceof RemoteException){ | ||
LOG.debug("Sasl connection failed: ", e); | ||
throw e; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be out of if condition right? Don't we want to re-throw IOException
other than RemoteException
?
Which brings the question, why to even have if condition? I know RemoteException
coming from readStatus
is imp to us but we don't want to swallow IOException if inStream.readInt()
throws one because inStream.readInt()
is pre-requisite to know whether the status is SaslStatus.SUCCESS
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, the if condition is not necessary, I'll fix that.
As far as I understand SaslStatus.SUCCESS
should have been handled at this point and having no new data in the stream is a valid usecase. If we would re-throw IOExceptions we would re-throw the EOFException
we would get when trying to read from such a stream.
…on on client side remove if condition only catch IOExceptions
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
🎊 +1 overall
This message was automatically generated. |
readStatus(inStream); | ||
} | ||
catch (IOException e){ | ||
if(e instanceof RemoteException){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still have this condition? I was talking about removing this condition because with this condition, we are swallowing IOException
other than RemoteException
, which we don't want to do. We want to re-throw all categories of IOException
here, not just RemoteException
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you removed the outer condition instead of
if(e instanceof RemoteException)
.
Let me copy my previous comment:
I know RemoteException
coming from readStatus
is imp to us but we don't want to swallow IOException if inStream.readInt()
throws one because inStream.readInt()
is pre-requisite to know whether the status is SaslStatus.SUCCESS
I am talking about what is happening within readStatus(inStream)
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just run a test on a test system. This time authentication was set up correctly and the goal was to see what happens in a normal usecase.
When it reached the new readStatus(inStream);
The following exception was thrown:
java.net.SocketTimeoutException: 20000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/xxx remote=yyy ]
at org.apache.hadoop.net.SocketIOWithTimeout.doIO(SocketIOWithTimeout.java:164)
at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:161)
at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:131)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at java.io.DataInputStream.readInt(DataInputStream.java:387)
at org.apache.hadoop.hbase.security.HBaseSaslRpcClient.readStatus(HBaseSaslRpcClient.java:51)
This is an IOException
. This is exactly the kind of exception that we do not want to re-throw, because it is caused by the additional readStatus
and would not exist otherwise. The line if(e instanceof RemoteException)
is there to filter out exceptions like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @BukrosSzabolcs for the explanation. Got your point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
…on on client side (#1921) Signed-off-by: Wellington Chevreuil <[email protected]> Signed-off-by: Viraj Jasani <[email protected]> (cherry picked from commit bd79c40)
…on on client side (#1921) Signed-off-by: Wellington Chevreuil <[email protected]> Signed-off-by: Viraj Jasani <[email protected]> (cherry picked from commit bd79c40)
…on on client side (apache#1921) Signed-off-by: Wellington Chevreuil <[email protected]> Signed-off-by: Viraj Jasani <[email protected]>
…on on client side (apache#1921) Signed-off-by: Wellington Chevreuil <[email protected]> Signed-off-by: Viraj Jasani <[email protected]> (cherry picked from commit bd79c40)
…nabled after finishing negotiation Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (apache#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here.
…nabled after finishing negotiation (#4642) Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here. Signed-off-by: Duo Zhang <[email protected]> Signed-off-by: Viraj Jasani <[email protected]>
…nabled after finishing negotiation (#4642) Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here. Signed-off-by: Duo Zhang <[email protected]> Signed-off-by: Viraj Jasani <[email protected]>
…nabled after finishing negotiation (#4642) Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here. Signed-off-by: Duo Zhang <[email protected]> Signed-off-by: Viraj Jasani <[email protected]> Conflicts: hbase-client/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java
…nabled after finishing negotiation (#4642) Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here. Signed-off-by: Duo Zhang <[email protected]> Signed-off-by: Viraj Jasani <[email protected]>
…nabled after finishing negotiation (apache#4642) Revert "HBASE-24579: Failed SASL authentication does not result in an exception on client side (apache#1921)" This reverts commit bd79c40. When Kerberos authentication succeeds, on the server side, after receiving the final SASL token from the client, we simply wait for the client to continue by sending the connection header. After HBASE-24579, on the client side, an additional readStatus() was added, which mistakenly assumes that after negotiation has completed a status code will be sent. However when authentication has succeeded the server will not send one. As a result the client will hang and only throw an exception when the configured read timeout is reached, which is 20 seconds by default. We cannot unilaterally send the expected additional status code from the server side because older clients will not expect it. The first call will fail because the client finds unexpected bytes in the stream ahead of the call response. Fabricating a call response also does not seem a viable strategy for backwards compatibility. The HBASE-24579 change needs to be reconsidered given the difficult backwards compatibility challenges here. Signed-off-by: Duo Zhang <[email protected]> Signed-off-by: Viraj Jasani <[email protected]> Conflicts: hbase-client/src/test/java/org/apache/hadoop/hbase/security/TestHBaseSaslRpcClient.java (cherry picked from commit 33b3bbe) Change-Id: I52e69e0e72e158f90868156291a15324ee7aaf3c
read input stream even if the authentication is completed
add a test