This is an automated email from the ASF dual-hosted git repository.
andor pushed a commit to branch branch-3.9
in repository https://gitbox.apache.org/repos/asf/zookeeper.git
The following commit(s) were added to refs/heads/branch-3.9 by this push:
new bd5be58c5 ZOOKEEPER-4851: Honor X-Forwarded-For optionally in
IPAuthenticationProvider
bd5be58c5 is described below
commit bd5be58c562ce992de8af43cdef0bdb34261a525
Author: Andor Molnár <[email protected]>
AuthorDate: Tue Sep 3 15:04:07 2024 -0500
ZOOKEEPER-4851: Honor X-Forwarded-For optionally in IPAuthenticationProvider
Reviewers: kezhuw, purushah
Author: anmolnar
Closes #2181 from anmolnar/ZOOKEEPER-4851
(cherry picked from commit 2c2b74c1c11b6531aabb1bf06782e859048d5983)
Signed-off-by: Andor Molnar <[email protected]>
---
.../src/main/resources/markdown/zookeeperAdmin.md | 10 +++
.../server/auth/IPAuthenticationProvider.java | 6 ++
.../server/auth/IPAuthenticationProviderTest.java | 85 ++++++++++++++++++++++
3 files changed, 101 insertions(+)
diff --git a/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
b/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
index 80aebcfa6..9c4408d2e 100644
--- a/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
+++ b/zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
@@ -1572,6 +1572,16 @@ and [SASL authentication for
ZooKeeper](https://cwiki.apache.org/confluence/disp
- 1. Regenerate `superDigest` when migrating to new algorithm.
- 2. `SetAcl` for a znode which already had a digest auth of old
algorithm.
+* *IPAuthenticationProvider.skipxforwardedfor* :
+ (Java system property:
**zookeeper.IPAuthenticationProvider.skipxforwardedfor**)
+ **New in 3.9.3:**
+ IPAuthenticationProvider needs the client IP address to authenticate the
user.
+ By default, it tries to read **X-Forwarded-For** HTTP header first and if
it's not
+ found, reads the **Host** header. Some proxy configuration requires this to
+ properly identify the client IP, but we can disable it relying only on the
**Host**
+ header by setting this config option to **true**.
+ Default value is **false**.
+
* *X509AuthenticationProvider.superUser* :
(Java system property: **zookeeper.X509AuthenticationProvider.superUser**)
The SSL-backed way to enable a ZooKeeper ensemble
diff --git
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/IPAuthenticationProvider.java
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/IPAuthenticationProvider.java
index 9334f7c5e..c73d12f78 100644
---
a/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/IPAuthenticationProvider.java
+++
b/zookeeper-server/src/main/java/org/apache/zookeeper/server/auth/IPAuthenticationProvider.java
@@ -30,6 +30,8 @@ import org.apache.zookeeper.server.ServerCnxn;
public class IPAuthenticationProvider implements AuthenticationProvider {
public static final String X_FORWARDED_FOR_HEADER_NAME = "X-Forwarded-For";
+ static final String SKIP_X_FORWARDED_FOR_KEY =
"zookeeper.IPAuthenticationProvider.skipxforwardedfor";
+
public String getScheme() {
return "ip";
}
@@ -150,6 +152,10 @@ public class IPAuthenticationProvider implements
AuthenticationProvider {
* @return IP address
*/
public static String getClientIPAddress(final HttpServletRequest request) {
+ if (Boolean.getBoolean(SKIP_X_FORWARDED_FOR_KEY)) {
+ return request.getRemoteAddr();
+ }
+
// to handle the case that a HTTP(s) client connects via a proxy or
load balancer
final String xForwardedForHeader =
request.getHeader(X_FORWARDED_FOR_HEADER_NAME);
if (xForwardedForHeader == null) {
diff --git
a/zookeeper-server/src/test/java/org/apache/zookeeper/server/auth/IPAuthenticationProviderTest.java
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/auth/IPAuthenticationProviderTest.java
new file mode 100644
index 000000000..fc814f7ea
--- /dev/null
+++
b/zookeeper-server/src/test/java/org/apache/zookeeper/server/auth/IPAuthenticationProviderTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zookeeper.server.auth;
+
+import static
org.apache.zookeeper.server.auth.IPAuthenticationProvider.SKIP_X_FORWARDED_FOR_KEY;
+import static
org.apache.zookeeper.server.auth.IPAuthenticationProvider.X_FORWARDED_FOR_HEADER_NAME;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import javax.servlet.http.HttpServletRequest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class IPAuthenticationProviderTest {
+
+ private HttpServletRequest request;
+
+ @Before
+ public void setUp() throws Exception {
+ System.clearProperty(SKIP_X_FORWARDED_FOR_KEY);
+ request = mock(HttpServletRequest.class);
+ }
+
+ @After
+ public void tearDown() {
+ System.clearProperty(SKIP_X_FORWARDED_FOR_KEY);
+ }
+
+ @Test
+ public void testGetClientIPAddressSkipXForwardedFor() {
+ // Arrange
+ System.setProperty(SKIP_X_FORWARDED_FOR_KEY, "true");
+ doReturn("192.168.1.1").when(request).getRemoteAddr();
+
doReturn("192.168.1.2,192.168.1.3,192.168.1.4").when(request).getHeader(X_FORWARDED_FOR_HEADER_NAME);
+
+ // Act
+ String clientIp = IPAuthenticationProvider.getClientIPAddress(request);
+
+ // Assert
+ assertEquals("192.168.1.1", clientIp);
+ }
+
+ @Test
+ public void testGetClientIPAddressWithXForwardedFor() {
+ // Arrange
+ System.setProperty(SKIP_X_FORWARDED_FOR_KEY, "false");
+ doReturn("192.168.1.1").when(request).getRemoteAddr();
+
doReturn("192.168.1.2,192.168.1.3,192.168.1.4").when(request).getHeader(X_FORWARDED_FOR_HEADER_NAME);
+
+ // Act
+ String clientIp = IPAuthenticationProvider.getClientIPAddress(request);
+
+ // Assert
+ assertEquals("192.168.1.2", clientIp);
+ }
+
+ @Test
+ public void testGetClientIPAddressMissingXForwardedFor() {
+ // Arrange
+ System.setProperty(SKIP_X_FORWARDED_FOR_KEY, "false");
+ doReturn("192.168.1.1").when(request).getRemoteAddr();
+
+ // Act
+ String clientIp = IPAuthenticationProvider.getClientIPAddress(request);
+
+ // Assert
+ assertEquals("192.168.1.1", clientIp);
+ }
+}