This is an automated email from the ASF dual-hosted git repository.

vyommani pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new a081ed080 RANGER-5819: Make grant/revoke endpoint security patterns 
slash-insensitive (follow-up to RANGER-5677) (#1284)
a081ed080 is described below

commit a081ed080b6320c04c63a29a1166e9d27fb8207a
Author: Vyom Mani Tiwari <[email protected]>
AuthorDate: Mon Oct 5 17:06:03 2026 +0530

    RANGER-5819: Make grant/revoke endpoint security patterns slash-insensitive 
(follow-up to RANGER-5677) (#1284)
---
 .../conf.dist/security-applicationContext.xml      |  8 +--
 .../TestGrantRevokeSecurityNonePatterns.java       | 83 ++++++++++++++++++++++
 2 files changed, 87 insertions(+), 4 deletions(-)

diff --git 
a/security-admin/src/main/resources/conf.dist/security-applicationContext.xml 
b/security-admin/src/main/resources/conf.dist/security-applicationContext.xml
index b99a5537c..dfe7cca9c 100644
--- 
a/security-admin/src/main/resources/conf.dist/security-applicationContext.xml
+++ 
b/security-admin/src/main/resources/conf.dist/security-applicationContext.xml
@@ -41,12 +41,12 @@ 
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd";>
        <security:http pattern="/images/ranger_logo.png" security="none" />
        <security:http pattern="/images/favicon.ico" security="none"/>
        <security:http pattern="/service/assets/policyList/*" security="none"/>
-       <security:http pattern="/service/assets/resources/grant" 
security="none"/>
-       <security:http pattern="/service/assets/resources/revoke" 
security="none"/>
+       <security:http pattern="/service/assets/resources/grant/**" 
security="none"/>
+       <security:http pattern="/service/assets/resources/revoke/**" 
security="none"/>
        <security:http pattern="/service/gds/download/**" security="none"/>
        <security:http pattern="/service/plugins/policies/download/**" 
security="none"/>
-       <security:http pattern="/service/plugins/services/grant/*" 
security="none"/>
-       <security:http pattern="/service/plugins/services/revoke/*" 
security="none"/>
+       <security:http pattern="/service/plugins/services/grant/**" 
security="none"/>
+       <security:http pattern="/service/plugins/services/revoke/**" 
security="none"/>
        <security:http pattern="/service/tags/download/**" security="none"/>
        <security:http pattern="/service/roles/download/**" security="none"/>
        <security:http pattern="/service/xusers/download/**" security="none"/>
diff --git 
a/security-admin/src/test/java/org/apache/ranger/security/web/filter/TestGrantRevokeSecurityNonePatterns.java
 
b/security-admin/src/test/java/org/apache/ranger/security/web/filter/TestGrantRevokeSecurityNonePatterns.java
new file mode 100644
index 000000000..5bc4860b4
--- /dev/null
+++ 
b/security-admin/src/test/java/org/apache/ranger/security/web/filter/TestGrantRevokeSecurityNonePatterns.java
@@ -0,0 +1,83 @@
+/*
+ * 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.ranger.security.web.filter;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.util.StreamUtils;
+
+import javax.servlet.http.HttpServletRequest;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * security="none" on grant/revoke must match the path with and without a 
trailing slash.
+ * A single-segment wildcard does not match the trailing-slash form, which 
then falls
+ * through to the authenticated filter chain.
+ */
+public class TestGrantRevokeSecurityNonePatterns {
+    @Test
+    public void pluginAndAssetGrantRevokePatternsMatchTrailingSlash() throws 
Exception {
+        String xml = StreamUtils.copyToString(new 
ClassPathResource("conf.dist/security-applicationContext.xml").getInputStream(),
 StandardCharsets.UTF_8);
+
+        assertSecurityNoneCovers(xml, "/service/plugins/services/grant/", 
"/service/plugins/services/grant/dev_hive");
+        assertSecurityNoneCovers(xml, "/service/plugins/services/revoke/", 
"/service/plugins/services/revoke/dev_hive");
+        assertSecurityNoneCovers(xml, "/service/assets/resources/grant", 
"/service/assets/resources/grant");
+        assertSecurityNoneCovers(xml, "/service/assets/resources/revoke", 
"/service/assets/resources/revoke");
+
+        // A single-segment wildcard matches the service path and misses the 
trailing slash, which is why these patterns use /**
+        assertFalse(matches("/service/plugins/services/grant/*", 
"/service/plugins/services/grant/dev_hive/"));
+    }
+
+    private static void assertSecurityNoneCovers(String xml, String 
pathPrefix, String path) {
+        String pattern = securityNonePattern(xml, pathPrefix);
+
+        assertTrue(matches(pattern, path), pattern + " should match " + path);
+        assertTrue(matches(pattern, path + "/"), pattern + " should match " + 
path + "/");
+    }
+
+    // Assumes pattern="…" is the first attribute and is written with no extra 
whitespace.
+    private static String securityNonePattern(String xml, String pathPrefix) {
+        String marker = "pattern=\"" + pathPrefix;
+        int start = xml.indexOf(marker);
+
+        assertTrue(start >= 0, "missing security=\"none\" pattern for " + 
pathPrefix);
+
+        int valueStart = start + "pattern=\"".length();
+        int valueEnd = xml.indexOf('"', valueStart);
+
+        return xml.substring(valueStart, valueEnd);
+    }
+
+    private static boolean matches(String pattern, String path) {
+        HttpServletRequest request = mock(HttpServletRequest.class);
+
+        when(request.getServletPath()).thenReturn(path);
+        when(request.getPathInfo()).thenReturn(null);
+        when(request.getMethod()).thenReturn("POST");
+
+        return new AntPathRequestMatcher(pattern).matches(request);
+    }
+}

Reply via email to