Skip to content

Commit 647b99d

Browse files
RANGER-5359: Add unit test cases for knox-agent module
1 parent e16ce56 commit 647b99d

File tree

8 files changed

+1952
-0
lines changed

8 files changed

+1952
-0
lines changed

knox-agent/pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,18 @@
317317
<version>${junit.jupiter.version}</version>
318318
<scope>test</scope>
319319
</dependency>
320+
<dependency>
321+
<groupId>org.mockito</groupId>
322+
<artifactId>mockito-inline</artifactId>
323+
<version>${mockito.version}</version>
324+
<scope>test</scope>
325+
</dependency>
326+
<dependency>
327+
<groupId>org.mockito</groupId>
328+
<artifactId>mockito-junit-jupiter</artifactId>
329+
<version>${mockito.version}</version>
330+
<scope>test</scope>
331+
</dependency>
320332
</dependencies>
321333
<build>
322334
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>

knox-agent/src/test/java/org/apache/ranger/admin/client/TestRangerAdminJersey2RESTClient.java

Lines changed: 780 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.ranger.authorization.knox;
20+
21+
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
22+
import org.apache.ranger.plugin.policyengine.RangerAccessResource;
23+
import org.apache.ranger.plugin.policyengine.RangerAccessResourceImpl;
24+
import org.junit.jupiter.api.Assertions;
25+
import org.junit.jupiter.api.MethodOrderer;
26+
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.TestMethodOrder;
28+
import org.junit.jupiter.api.extension.ExtendWith;
29+
import org.mockito.junit.jupiter.MockitoExtension;
30+
31+
import java.util.Arrays;
32+
import java.util.HashSet;
33+
import java.util.List;
34+
import java.util.Set;
35+
36+
/**
37+
* @generated by Cursor
38+
* @description <Unit Test for KnoxRangerPlugin class>
39+
*/
40+
@ExtendWith(MockitoExtension.class)
41+
@TestMethodOrder(MethodOrderer.MethodName.class)
42+
public class TestKnoxRangerPlugin {
43+
@Test
44+
public void test01_init_setsResultProcessorOnce() {
45+
KnoxRangerPlugin plugin = new KnoxRangerPlugin();
46+
47+
Assertions.assertNull(plugin.getResultProcessor());
48+
plugin.init();
49+
Assertions.assertNotNull(plugin.getResultProcessor());
50+
51+
// second init should not reset and should not throw
52+
plugin.init();
53+
Assertions.assertNotNull(plugin.getResultProcessor());
54+
}
55+
56+
@Test
57+
public void test02_requestBuilder_verifyBuildable_throwsOnMissing() {
58+
KnoxRangerPlugin.RequestBuilder b = new KnoxRangerPlugin.RequestBuilder();
59+
Assertions.assertThrows(IllegalStateException.class, b::verifyBuildable);
60+
61+
b.service("svc");
62+
Assertions.assertThrows(IllegalStateException.class, b::verifyBuildable);
63+
64+
b.topology("top");
65+
Assertions.assertThrows(IllegalStateException.class, b::verifyBuildable);
66+
67+
b.user("u");
68+
// no exception now
69+
b.verifyBuildable();
70+
}
71+
72+
@Test
73+
public void test03_requestBuilder_build_setsAllFields() {
74+
Set<String> groups = new HashSet<>(Arrays.asList("g1", "g2"));
75+
List<String> fwd = Arrays.asList("1.1.1.1", "2.2.2.2");
76+
77+
KnoxRangerPlugin.RequestBuilder b = new KnoxRangerPlugin.RequestBuilder()
78+
.service("svc")
79+
.topology("top")
80+
.user("user")
81+
.groups(groups)
82+
.clientIp("10.0.0.1")
83+
.remoteIp("10.0.0.1")
84+
.forwardedAddresses(fwd);
85+
86+
RangerAccessRequest req = b.build();
87+
Assertions.assertEquals("user", req.getUser());
88+
Assertions.assertEquals("allow", req.getAction());
89+
Assertions.assertEquals("allow", req.getAccessType());
90+
Assertions.assertEquals("10.0.0.1", req.getClientIPAddress());
91+
Assertions.assertEquals(groups, req.getUserGroups());
92+
Assertions.assertEquals(fwd, req.getForwardedAddresses());
93+
94+
RangerAccessResource res = req.getResource();
95+
Assertions.assertTrue(res instanceof RangerAccessResourceImpl);
96+
Assertions.assertEquals("svc", ((RangerAccessResourceImpl) res).getValue(KnoxRangerPlugin.KnoxConstants.ResourceName.Service));
97+
Assertions.assertEquals("top", ((RangerAccessResourceImpl) res).getValue(KnoxRangerPlugin.KnoxConstants.ResourceName.Topology));
98+
}
99+
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.ranger.authorization.knox;
20+
21+
import org.apache.knox.gateway.filter.AbstractGatewayFilter;
22+
import org.apache.knox.gateway.security.GroupPrincipal;
23+
import org.apache.knox.gateway.security.ImpersonatedPrincipal;
24+
import org.apache.knox.gateway.security.PrimaryPrincipal;
25+
import org.apache.ranger.audit.provider.MiscUtil;
26+
import org.apache.ranger.plugin.policyengine.RangerAccessRequest;
27+
import org.apache.ranger.plugin.policyengine.RangerAccessResult;
28+
import org.junit.jupiter.api.Assertions;
29+
import org.junit.jupiter.api.MethodOrderer;
30+
import org.junit.jupiter.api.Test;
31+
import org.junit.jupiter.api.TestMethodOrder;
32+
import org.junit.jupiter.api.extension.ExtendWith;
33+
import org.mockito.MockedStatic;
34+
import org.mockito.Mockito;
35+
import org.mockito.junit.jupiter.MockitoExtension;
36+
37+
import javax.security.auth.Subject;
38+
import javax.servlet.FilterChain;
39+
import javax.servlet.FilterConfig;
40+
import javax.servlet.ServletRequest;
41+
import javax.servlet.ServletResponse;
42+
import javax.servlet.http.HttpServletRequest;
43+
import javax.servlet.http.HttpServletResponse;
44+
45+
import java.lang.reflect.Field;
46+
import java.lang.reflect.Method;
47+
import java.security.PrivilegedExceptionAction;
48+
import java.util.Arrays;
49+
import java.util.List;
50+
51+
import static org.mockito.Mockito.mock;
52+
import static org.mockito.Mockito.times;
53+
import static org.mockito.Mockito.verify;
54+
import static org.mockito.Mockito.when;
55+
56+
/**
57+
* @generated by Cursor
58+
* @description <Unit Test for RangerPDPKnoxFilter class>
59+
*/
60+
@ExtendWith(MockitoExtension.class)
61+
@TestMethodOrder(MethodOrderer.MethodName.class)
62+
public class TestRangerPDPKnoxFilter {
63+
@Test
64+
public void test01_init_initializesPluginOnce() {
65+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
66+
FilterConfig cfg = mock(FilterConfig.class);
67+
when(cfg.getInitParameter("resource.role"))
68+
.thenReturn("WEBHDFS");
69+
70+
try (MockedStatic<MiscUtil> mu = Mockito.mockStatic(MiscUtil.class)) {
71+
filter.init(cfg);
72+
// second init call should reuse existing plugin and not throw
73+
filter.init(cfg);
74+
}
75+
}
76+
77+
@Test
78+
public void test02_doFilter_accessAllowed_callsChain() throws Exception {
79+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
80+
81+
// prepare Subject with principals
82+
Subject subject = new Subject();
83+
subject.getPrincipals().add(new PrimaryPrincipal("primary"));
84+
subject.getPrincipals().add(new ImpersonatedPrincipal("impersonated"));
85+
subject.getPrincipals().add(new GroupPrincipal("g1"));
86+
subject.getPrincipals().add(new GroupPrincipal("g2"));
87+
88+
ServletRequest req = mock(HttpServletRequest.class);
89+
ServletResponse res = mock(HttpServletResponse.class);
90+
FilterChain chain = mock(FilterChain.class);
91+
92+
when(req.getAttribute(AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME))
93+
.thenReturn("/cluster/top1/path");
94+
when(req.getRemoteAddr()).thenReturn("10.0.0.1");
95+
96+
// mock plugin
97+
KnoxRangerPlugin plugin = Mockito.mock(KnoxRangerPlugin.class);
98+
Field f = RangerPDPKnoxFilter.class.getDeclaredField("plugin");
99+
f.setAccessible(true);
100+
f.set(null, plugin);
101+
102+
RangerAccessResult allow = Mockito.mock(RangerAccessResult.class);
103+
when(allow.getIsAllowed()).thenReturn(true);
104+
when(plugin.isAccessAllowed(Mockito.any(RangerAccessRequest.class))).thenReturn(allow);
105+
106+
Subject.doAs(subject, (PrivilegedExceptionAction<Void>) () -> {
107+
filter.doFilter(req, res, chain);
108+
return null;
109+
});
110+
verify(chain, times(1)).doFilter(req, res);
111+
}
112+
113+
@Test
114+
public void test03_doFilter_accessDenied_sendsForbidden() throws Exception {
115+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
116+
Subject subject = new Subject();
117+
subject.getPrincipals().add(new PrimaryPrincipal("primary"));
118+
ServletRequest req = mock(HttpServletRequest.class);
119+
HttpServletResponse res = mock(HttpServletResponse.class);
120+
FilterChain chain = mock(FilterChain.class);
121+
122+
when(req.getAttribute(AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME))
123+
.thenReturn("/cluster/top1/path");
124+
when(req.getRemoteAddr()).thenReturn("10.0.0.1");
125+
126+
KnoxRangerPlugin plugin = Mockito.mock(KnoxRangerPlugin.class);
127+
Field f = RangerPDPKnoxFilter.class.getDeclaredField("plugin");
128+
f.setAccessible(true);
129+
f.set(null, plugin);
130+
131+
RangerAccessResult deny = Mockito.mock(RangerAccessResult.class);
132+
when(deny.getIsAllowed()).thenReturn(false);
133+
when(plugin.isAccessAllowed(Mockito.any(RangerAccessRequest.class))).thenReturn(deny);
134+
135+
Subject.doAs(subject, (PrivilegedExceptionAction<Void>) () -> {
136+
filter.doFilter(req, res, chain);
137+
return null;
138+
});
139+
verify(res, times(1)).sendError(403);
140+
}
141+
142+
@Test
143+
public void test04_getInitParameter_lowercasesName() {
144+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
145+
FilterConfig cfg = mock(FilterConfig.class);
146+
when(cfg.getInitParameter("resource.role")).thenReturn("WEBHDFS");
147+
Assertions.assertEquals("WEBHDFS", invokeGetInitParameter(filter, cfg, "RESOURCE.ROLE"));
148+
}
149+
150+
@Test
151+
public void test05_getForwardedAddresses_parsesHeader() {
152+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
153+
HttpServletRequest req = mock(HttpServletRequest.class);
154+
when(req.getHeader("X-Forwarded-For")).thenReturn("1.1.1.1,2.2.2.2");
155+
List<String> addrs = invokeGetForwardedAddresses(filter, req);
156+
Assertions.assertEquals(Arrays.asList("1.1.1.1", "2.2.2.2"), addrs);
157+
158+
when(req.getHeader("X-Forwarded-For")).thenReturn(null);
159+
Assertions.assertNull(invokeGetForwardedAddresses(filter, req));
160+
}
161+
162+
@Test
163+
public void test06_getTopologyName_extractsThirdTokenOrNull() {
164+
RangerPDPKnoxFilter filter = new RangerPDPKnoxFilter();
165+
Assertions.assertNull(invokeGetTopologyName(filter, null));
166+
Assertions.assertNull(invokeGetTopologyName(filter, "/one"));
167+
Assertions.assertEquals("two", invokeGetTopologyName(filter, "/one/two/three"));
168+
}
169+
170+
private String invokeGetInitParameter(RangerPDPKnoxFilter filter, FilterConfig cfg, String name) {
171+
try {
172+
Method m = RangerPDPKnoxFilter.class.getDeclaredMethod("getInitParameter", FilterConfig.class, String.class);
173+
m.setAccessible(true);
174+
return (String) m.invoke(filter, cfg, name);
175+
} catch (Exception e) {
176+
throw new RuntimeException(e);
177+
}
178+
}
179+
180+
private List<String> invokeGetForwardedAddresses(RangerPDPKnoxFilter filter, ServletRequest req) {
181+
try {
182+
Method m = RangerPDPKnoxFilter.class.getDeclaredMethod("getForwardedAddresses", ServletRequest.class);
183+
m.setAccessible(true);
184+
@SuppressWarnings("unchecked")
185+
List<String> ret = (List<String>) m.invoke(filter, req);
186+
return ret;
187+
} catch (Exception e) {
188+
throw new RuntimeException(e);
189+
}
190+
}
191+
192+
private String invokeGetTopologyName(RangerPDPKnoxFilter filter, String url) {
193+
try {
194+
Method m = RangerPDPKnoxFilter.class.getDeclaredMethod("getTopologyName", String.class);
195+
m.setAccessible(true);
196+
return (String) m.invoke(filter, url);
197+
} catch (Exception e) {
198+
throw new RuntimeException(e);
199+
}
200+
}
201+
}

0 commit comments

Comments
 (0)