|
18 | 18 | package org.apache.drill.exec.rpc.user.security;
|
19 | 19 |
|
20 | 20 | import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
|
21 |
| -import com.typesafe.config.ConfigValueFactory; |
22 | 21 | import org.apache.drill.categories.SecurityTest;
|
23 |
| -import org.apache.drill.common.config.DrillConfig; |
24 | 22 | import org.apache.drill.common.config.DrillProperties;
|
25 | 23 | import org.apache.drill.exec.ExecConstants;
|
| 24 | +import org.apache.drill.exec.rpc.RpcMetrics; |
26 | 25 | import org.apache.drill.exec.rpc.control.ControlRpcMetrics;
|
27 | 26 | import org.apache.drill.exec.rpc.data.DataRpcMetrics;
|
28 | 27 | import org.apache.drill.exec.rpc.security.KerberosHelper;
|
29 | 28 | import org.apache.drill.exec.rpc.user.UserRpcMetrics;
|
30 | 29 | import org.apache.drill.exec.rpc.user.security.testing.UserAuthenticatorTestImpl;
|
31 |
| -import org.apache.drill.test.BaseTestQuery; |
32 |
| -import org.apache.hadoop.security.authentication.util.KerberosName; |
33 |
| -import org.apache.hadoop.security.authentication.util.KerberosUtil; |
| 30 | +import org.apache.drill.test.ClientFixture; |
| 31 | +import org.apache.drill.test.ClusterFixture; |
| 32 | +import org.apache.drill.test.ClusterFixtureBuilder; |
| 33 | +import org.apache.drill.test.ClusterTest; |
34 | 34 | import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
|
35 | 35 | import org.junit.AfterClass;
|
36 | 36 | import org.junit.BeforeClass;
|
|
39 | 39 | import org.junit.experimental.categories.Category;
|
40 | 40 |
|
41 | 41 | import javax.security.auth.Subject;
|
42 |
| -import java.lang.reflect.Field; |
43 | 42 | import java.security.PrivilegedExceptionAction;
|
44 |
| -import java.util.Properties; |
45 | 43 |
|
46 |
| -import static junit.framework.TestCase.assertTrue; |
| 44 | +import static junit.framework.TestCase.assertEquals; |
47 | 45 |
|
48 |
| -@Ignore("See DRILL-5387") |
49 | 46 | @Category(SecurityTest.class)
|
50 |
| -public class TestUserBitKerberos extends BaseTestQuery { |
51 |
| - //private static final org.slf4j.Logger logger =org.slf4j.LoggerFactory.getLogger(TestUserBitKerberos.class); |
| 47 | +public class TestUserBitKerberos extends ClusterTest { |
52 | 48 |
|
53 | 49 | private static KerberosHelper krbHelper;
|
54 | 50 |
|
55 | 51 | @BeforeClass
|
56 | 52 | public static void setupTest() throws Exception {
|
57 |
| - |
58 | 53 | krbHelper = new KerberosHelper(TestUserBitKerberos.class.getSimpleName(), null);
|
59 | 54 | krbHelper.setupKdc(dirTestWatcher.getTmpDir());
|
| 55 | + cluster = defaultClusterConfig().build(); |
| 56 | + } |
60 | 57 |
|
61 |
| - // Create a new DrillConfig which has user authentication enabled and authenticator set to |
62 |
| - // UserAuthenticatorTestImpl. |
63 |
| - final DrillConfig newConfig = new DrillConfig(DrillConfig.create(cloneDefaultTestConfigProperties()) |
64 |
| - .withValue(ExecConstants.USER_AUTHENTICATION_ENABLED, |
65 |
| - ConfigValueFactory.fromAnyRef(true)) |
66 |
| - .withValue(ExecConstants.USER_AUTHENTICATOR_IMPL, |
67 |
| - ConfigValueFactory.fromAnyRef(UserAuthenticatorTestImpl.TYPE)) |
68 |
| - .withValue(ExecConstants.SERVICE_PRINCIPAL, |
69 |
| - ConfigValueFactory.fromAnyRef(krbHelper.SERVER_PRINCIPAL)) |
70 |
| - .withValue(ExecConstants.SERVICE_KEYTAB_LOCATION, |
71 |
| - ConfigValueFactory.fromAnyRef(krbHelper.serverKeytab.toString())) |
72 |
| - .withValue(ExecConstants.AUTHENTICATION_MECHANISMS, |
73 |
| - ConfigValueFactory.fromIterable(Lists.newArrayList("plain", "kerberos")))); |
74 |
| - |
75 |
| - final Properties connectionProps = new Properties(); |
76 |
| - connectionProps.setProperty(DrillProperties.USER, "anonymous"); |
77 |
| - connectionProps.setProperty(DrillProperties.PASSWORD, "anything works!"); |
78 |
| - |
79 |
| - // Ignore the compile time warning caused by the code below. |
80 |
| - |
81 |
| - // Config is statically initialized at this point. But the above configuration results in a different |
82 |
| - // initialization which causes the tests to fail. So the following two changes are required. |
83 |
| - |
84 |
| - // (1) Refresh Kerberos config. |
85 |
| - sun.security.krb5.Config.refresh(); |
86 |
| - // (2) Reset the default realm. |
87 |
| - final Field defaultRealm = KerberosName.class.getDeclaredField("defaultRealm"); |
88 |
| - defaultRealm.setAccessible(true); |
89 |
| - defaultRealm.set(null, KerberosUtil.getDefaultRealm()); |
90 |
| - |
91 |
| - updateTestCluster(1, newConfig, connectionProps); |
| 58 | + private static ClusterFixtureBuilder defaultClusterConfig() { |
| 59 | + return ClusterFixture.bareBuilder(dirTestWatcher) |
| 60 | + .clusterSize(1) |
| 61 | + .configProperty(ExecConstants.USER_AUTHENTICATION_ENABLED, true) |
| 62 | + .configProperty(ExecConstants.USER_AUTHENTICATOR_IMPL, UserAuthenticatorTestImpl.TYPE) |
| 63 | + .configProperty(ExecConstants.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL) |
| 64 | + .configProperty(ExecConstants.SERVICE_KEYTAB_LOCATION, krbHelper.serverKeytab.toString()) |
| 65 | + .configNonStringProperty(ExecConstants.AUTHENTICATION_MECHANISMS, Lists.newArrayList("plain", "kerberos")); |
92 | 66 | }
|
93 | 67 |
|
94 | 68 | @Test
|
95 | 69 | public void successKeytab() throws Exception {
|
96 |
| - final Properties connectionProps = new Properties(); |
97 |
| - connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL); |
98 |
| - connectionProps.setProperty(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL); |
99 |
| - connectionProps.setProperty(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath()); |
100 |
| - updateClient(connectionProps); |
101 |
| - |
102 |
| - // Run few queries using the new client |
103 |
| - testBuilder() |
| 70 | + try ( |
| 71 | + ClientFixture client = cluster.clientBuilder() |
| 72 | + .property(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL) |
| 73 | + .property(DrillProperties.USER, krbHelper.CLIENT_PRINCIPAL) |
| 74 | + .property(DrillProperties.KEYTAB, krbHelper.clientKeytab.getAbsolutePath()) |
| 75 | + .build() |
| 76 | + ) { |
| 77 | + |
| 78 | + // Run few queries using the new client |
| 79 | + client.testBuilder() |
104 | 80 | .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)")
|
105 | 81 | .unOrdered()
|
106 | 82 | .baselineColumns("session_user")
|
107 | 83 | .baselineValues(krbHelper.CLIENT_SHORT_NAME)
|
108 | 84 | .go();
|
109 |
| - test("SHOW SCHEMAS"); |
110 |
| - test("USE INFORMATION_SCHEMA"); |
111 |
| - test("SHOW TABLES"); |
112 |
| - test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'"); |
113 |
| - test("SELECT * FROM cp.`region.json` LIMIT 5"); |
| 85 | + |
| 86 | + client.runSqlSilently("SHOW SCHEMAS"); |
| 87 | + client.runSqlSilently("USE INFORMATION_SCHEMA"); |
| 88 | + client.runSqlSilently("SHOW TABLES"); |
| 89 | + client.runSqlSilently("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'"); |
| 90 | + client.runSqlSilently("SELECT * FROM cp.`region.json` LIMIT 5"); |
| 91 | + } |
114 | 92 | }
|
115 | 93 |
|
116 | 94 | @Test
|
117 | 95 | public void successTicket() throws Exception {
|
118 |
| - final Properties connectionProps = new Properties(); |
119 |
| - connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL); |
120 |
| - connectionProps.setProperty(DrillProperties.KERBEROS_FROM_SUBJECT, "true"); |
121 |
| - final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(krbHelper.CLIENT_PRINCIPAL, |
122 |
| - krbHelper.clientKeytab.getAbsoluteFile()); |
123 |
| - |
124 |
| - Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() { |
125 |
| - @Override |
126 |
| - public Void run() throws Exception { |
127 |
| - updateClient(connectionProps); |
128 |
| - return null; |
129 |
| - } |
130 |
| - }); |
| 96 | + Subject clientSubject = JaasKrbUtil.loginUsingKeytab( |
| 97 | + krbHelper.CLIENT_PRINCIPAL, |
| 98 | + krbHelper.clientKeytab.getAbsoluteFile() |
| 99 | + ); |
| 100 | + |
| 101 | + try ( |
| 102 | + ClientFixture client = Subject.doAs( |
| 103 | + clientSubject, |
| 104 | + (PrivilegedExceptionAction<ClientFixture>) () -> cluster.clientBuilder() |
| 105 | + .property(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL) |
| 106 | + .property(DrillProperties.KERBEROS_FROM_SUBJECT, "true") |
| 107 | + .build() |
| 108 | + ) |
| 109 | + ) { |
131 | 110 |
|
132 | 111 | // Run few queries using the new client
|
133 |
| - testBuilder() |
134 |
| - .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)") |
135 |
| - .unOrdered() |
136 |
| - .baselineColumns("session_user") |
137 |
| - .baselineValues(krbHelper.CLIENT_SHORT_NAME) |
138 |
| - .go(); |
139 |
| - test("SHOW SCHEMAS"); |
140 |
| - test("USE INFORMATION_SCHEMA"); |
141 |
| - test("SHOW TABLES"); |
142 |
| - test("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'"); |
143 |
| - test("SELECT * FROM cp.`region.json` LIMIT 5"); |
144 |
| - } |
| 112 | + client.testBuilder() |
| 113 | + .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)") |
| 114 | + .unOrdered() |
| 115 | + .baselineColumns("session_user") |
| 116 | + .baselineValues(krbHelper.CLIENT_SHORT_NAME) |
| 117 | + .go(); |
| 118 | + |
| 119 | + client.runSqlSilently("SHOW SCHEMAS"); |
| 120 | + client.runSqlSilently("USE INFORMATION_SCHEMA"); |
| 121 | + client.runSqlSilently("SHOW TABLES"); |
| 122 | + client.runSqlSilently("SELECT * FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_NAME LIKE 'COLUMNS'"); |
| 123 | + client.runSqlSilently("SELECT * FROM cp.`region.json` LIMIT 5"); |
| 124 | + } |
| 125 | + } |
145 | 126 |
|
146 | 127 | @Test
|
147 |
| - public void testUnecryptedConnectionCounter() throws Exception { |
148 |
| - final Properties connectionProps = new Properties(); |
149 |
| - connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL); |
150 |
| - connectionProps.setProperty(DrillProperties.KERBEROS_FROM_SUBJECT, "true"); |
151 |
| - final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(krbHelper.CLIENT_PRINCIPAL, |
152 |
| - krbHelper.clientKeytab.getAbsoluteFile()); |
153 |
| - |
154 |
| - Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() { |
155 |
| - @Override |
156 |
| - public Void run() throws Exception { |
157 |
| - updateClient(connectionProps); |
158 |
| - return null; |
159 |
| - } |
160 |
| - }); |
161 |
| - |
162 |
| - // Run few queries using the new client |
163 |
| - testBuilder() |
164 |
| - .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)") |
165 |
| - .unOrdered() |
166 |
| - .baselineColumns("session_user") |
167 |
| - .baselineValues(krbHelper.CLIENT_SHORT_NAME) |
168 |
| - .go(); |
169 |
| - |
170 |
| - // Check encrypted counters value |
171 |
| - assertTrue(0 == UserRpcMetrics.getInstance().getEncryptedConnectionCount()); |
172 |
| - assertTrue(0 == ControlRpcMetrics.getInstance().getEncryptedConnectionCount()); |
173 |
| - assertTrue(0 == DataRpcMetrics.getInstance().getEncryptedConnectionCount()); |
174 |
| - |
175 |
| - // Check unencrypted counters value |
176 |
| - assertTrue(1 == UserRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
177 |
| - assertTrue(0 == ControlRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
178 |
| - assertTrue(0 == DataRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
| 128 | + @Ignore("See DRILL-5387. This test works in isolation but not when sharing counters with other tests") |
| 129 | + public void testUnencryptedConnectionCounter() throws Exception { |
| 130 | + Subject clientSubject = JaasKrbUtil.loginUsingKeytab( |
| 131 | + krbHelper.CLIENT_PRINCIPAL, |
| 132 | + krbHelper.clientKeytab.getAbsoluteFile() |
| 133 | + ); |
| 134 | + |
| 135 | + try ( |
| 136 | + // Use a dedicated cluster fixture so that the tested RPC counters have a clean start. |
| 137 | + ClusterFixture cluster = defaultClusterConfig().build(); |
| 138 | + ClientFixture client = Subject.doAs( |
| 139 | + clientSubject, |
| 140 | + (PrivilegedExceptionAction<ClientFixture>) () -> cluster.clientBuilder() |
| 141 | + .property(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL) |
| 142 | + .property(DrillProperties.KERBEROS_FROM_SUBJECT, "true") |
| 143 | + .build() |
| 144 | + ) |
| 145 | + ) { |
| 146 | + client.testBuilder() |
| 147 | + .sqlQuery("SELECT session_user FROM (SELECT * FROM sys.drillbits LIMIT 1)") |
| 148 | + .unOrdered() |
| 149 | + .baselineColumns("session_user") |
| 150 | + .baselineValues(krbHelper.CLIENT_SHORT_NAME) |
| 151 | + .go(); |
| 152 | + |
| 153 | + RpcMetrics userMetrics = UserRpcMetrics.getInstance(), |
| 154 | + ctrlMetrics = ControlRpcMetrics.getInstance(), |
| 155 | + dataMetrics = DataRpcMetrics.getInstance(); |
| 156 | + |
| 157 | + // Check encrypted counters value |
| 158 | + assertEquals(0, userMetrics.getEncryptedConnectionCount()); |
| 159 | + assertEquals(0, ctrlMetrics.getEncryptedConnectionCount()); |
| 160 | + assertEquals(0, dataMetrics.getEncryptedConnectionCount()); |
| 161 | + |
| 162 | + // Check unencrypted counters value |
| 163 | + assertEquals(1, userMetrics.getUnEncryptedConnectionCount()); |
| 164 | + assertEquals(0, ctrlMetrics.getUnEncryptedConnectionCount()); |
| 165 | + assertEquals(0, dataMetrics.getUnEncryptedConnectionCount()); |
| 166 | + } |
179 | 167 | }
|
180 | 168 |
|
181 | 169 | @Test
|
182 |
| - public void testUnecryptedConnectionCounter_LocalControlMessage() throws Exception { |
183 |
| - final Properties connectionProps = new Properties(); |
184 |
| - connectionProps.setProperty(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL); |
185 |
| - connectionProps.setProperty(DrillProperties.KERBEROS_FROM_SUBJECT, "true"); |
186 |
| - final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(krbHelper.CLIENT_PRINCIPAL, |
187 |
| - krbHelper.clientKeytab.getAbsoluteFile()); |
188 |
| - |
189 |
| - Subject.doAs(clientSubject, new PrivilegedExceptionAction<Void>() { |
190 |
| - @Override |
191 |
| - public Void run() throws Exception { |
192 |
| - updateClient(connectionProps); |
193 |
| - return null; |
194 |
| - } |
195 |
| - }); |
196 |
| - |
197 |
| - // Run query on memory system table this sends remote fragments to all Drillbit and Drillbits then send data |
198 |
| - // using data channel. In this test we have only 1 Drillbit so there should not be any control connection but a |
199 |
| - // local data connections |
200 |
| - testSql("SELECT * FROM sys.memory"); |
201 |
| - |
202 |
| - // Check encrypted counters value |
203 |
| - assertTrue(0 == UserRpcMetrics.getInstance().getEncryptedConnectionCount()); |
204 |
| - assertTrue(0 == ControlRpcMetrics.getInstance().getEncryptedConnectionCount()); |
205 |
| - assertTrue(0 == DataRpcMetrics.getInstance().getEncryptedConnectionCount()); |
206 |
| - |
207 |
| - // Check unencrypted counters value |
208 |
| - assertTrue(1 == UserRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
209 |
| - assertTrue(0 == ControlRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
210 |
| - assertTrue(2 == DataRpcMetrics.getInstance().getUnEncryptedConnectionCount()); |
| 170 | + @Ignore("See DRILL-5387. This test works in isolation but not when sharing counters with other tests") |
| 171 | + public void testUnencryptedConnectionCounter_LocalControlMessage() throws Exception { |
| 172 | + Subject clientSubject = JaasKrbUtil.loginUsingKeytab( |
| 173 | + krbHelper.CLIENT_PRINCIPAL, |
| 174 | + krbHelper.clientKeytab.getAbsoluteFile() |
| 175 | + ); |
| 176 | + |
| 177 | + try ( |
| 178 | + // Use a dedicated cluster fixture so that the tested RPC counters have a clean start. |
| 179 | + ClusterFixture cluster = defaultClusterConfig().build(); |
| 180 | + ClientFixture client = Subject.doAs( |
| 181 | + clientSubject, |
| 182 | + (PrivilegedExceptionAction<ClientFixture>) () -> cluster.clientBuilder() |
| 183 | + .property(DrillProperties.SERVICE_PRINCIPAL, krbHelper.SERVER_PRINCIPAL) |
| 184 | + .property(DrillProperties.KERBEROS_FROM_SUBJECT, "true") |
| 185 | + .build() |
| 186 | + ) |
| 187 | + ) { |
| 188 | + // Run query on memory system table this sends remote fragments to all Drillbit and Drillbits then send data |
| 189 | + // using data channel. In this test we have only 1 Drillbit so there should not be any control connection but a |
| 190 | + // local data connections |
| 191 | + client.runSqlSilently("SELECT * FROM sys.memory"); |
| 192 | + |
| 193 | + RpcMetrics userMetrics = UserRpcMetrics.getInstance(), |
| 194 | + ctrlMetrics = ControlRpcMetrics.getInstance(), |
| 195 | + dataMetrics = DataRpcMetrics.getInstance(); |
| 196 | + |
| 197 | + // Check encrypted counters value |
| 198 | + assertEquals(0, userMetrics.getEncryptedConnectionCount()); |
| 199 | + assertEquals(0, ctrlMetrics.getEncryptedConnectionCount()); |
| 200 | + assertEquals(0, dataMetrics.getEncryptedConnectionCount()); |
| 201 | + |
| 202 | + // Check unencrypted counters value |
| 203 | + assertEquals(1, userMetrics.getUnEncryptedConnectionCount()); |
| 204 | + assertEquals(0, ctrlMetrics.getUnEncryptedConnectionCount()); |
| 205 | + assertEquals(2, dataMetrics.getUnEncryptedConnectionCount()); |
| 206 | + } |
211 | 207 | }
|
212 | 208 |
|
213 | 209 | @AfterClass
|
|
0 commit comments