|
46 | 46 | import org.apache.hadoop.hbase.rest.model.CellModel; |
47 | 47 | import org.apache.hadoop.hbase.rest.model.CellSetModel; |
48 | 48 | import org.apache.hadoop.hbase.rest.model.RowModel; |
| 49 | +import org.apache.hadoop.hbase.rest.model.ScannerModel; |
49 | 50 | import org.apache.hadoop.hbase.security.HBaseKerberosUtils; |
50 | 51 | import org.apache.hadoop.hbase.security.access.AccessControlClient; |
51 | 52 | import org.apache.hadoop.hbase.security.access.AccessControlConstants; |
|
70 | 71 | import org.apache.http.client.CredentialsProvider; |
71 | 72 | import org.apache.http.client.config.AuthSchemes; |
72 | 73 | import org.apache.http.client.methods.CloseableHttpResponse; |
| 74 | +import org.apache.http.client.methods.HttpDelete; |
73 | 75 | import org.apache.http.client.methods.HttpGet; |
| 76 | +import org.apache.http.client.methods.HttpPost; |
74 | 77 | import org.apache.http.client.methods.HttpPut; |
75 | 78 | import org.apache.http.client.protocol.HttpClientContext; |
76 | 79 | import org.apache.http.config.Registry; |
@@ -110,6 +113,7 @@ public class TestSecureRESTServer { |
110 | 113 |
|
111 | 114 | private static final String HOSTNAME = "localhost"; |
112 | 115 | private static final String CLIENT_PRINCIPAL = "client"; |
| 116 | + private static final String CLIENT_PRINCIPAL2 = "client2"; |
113 | 117 | private static final String WHEEL_PRINCIPAL = "wheel"; |
114 | 118 | // The principal for accepting SPNEGO authn'ed requests (*must* be HTTP/fqdn) |
115 | 119 | private static final String SPNEGO_SERVICE_PRINCIPAL = "HTTP/" + HOSTNAME; |
@@ -156,7 +160,7 @@ public static void setupServer() throws Exception { |
156 | 160 | * Start KDC |
157 | 161 | */ |
158 | 162 | KDC = TEST_UTIL.setupMiniKdc(serviceKeytab); |
159 | | - KDC.createPrincipal(clientKeytab, CLIENT_PRINCIPAL); |
| 163 | + KDC.createPrincipal(clientKeytab, CLIENT_PRINCIPAL, CLIENT_PRINCIPAL2); |
160 | 164 | KDC.createPrincipal(wheelKeytab, WHEEL_PRINCIPAL); |
161 | 165 | KDC.createPrincipal(serviceKeytab, SERVICE_PRINCIPAL); |
162 | 166 | // REST server's keytab contains keys for both principals REST uses |
@@ -189,7 +193,7 @@ public static void setupServer() throws Exception { |
189 | 193 | updateKerberosConfiguration(conf, REST_SERVER_PRINCIPAL, SPNEGO_SERVICE_PRINCIPAL, |
190 | 194 | restServerKeytab); |
191 | 195 |
|
192 | | - // Start HDFS |
| 196 | + // Start HBase |
193 | 197 | TEST_UTIL.startMiniCluster( |
194 | 198 | StartMiniClusterOption.builder().numMasters(1).numRegionServers(1).numZkServers(1).build()); |
195 | 199 |
|
@@ -330,10 +334,10 @@ public Void run() throws Exception { |
330 | 334 | }); |
331 | 335 | } |
332 | 336 |
|
333 | | - public void testProxy(String extraArgs, String PRINCIPAL, File keytab, int responseCode) |
| 337 | + private void testProxy(String extraArgs, String PRINCIPAL, File keytab, int responseCode) |
334 | 338 | throws Exception { |
335 | | - UserGroupInformation superuser = UserGroupInformation |
336 | | - .loginUserFromKeytabAndReturnUGI(SERVICE_PRINCIPAL, serviceKeytab.getAbsolutePath()); |
| 339 | + UserGroupInformation.loginUserFromKeytabAndReturnUGI(SERVICE_PRINCIPAL, |
| 340 | + serviceKeytab.getAbsolutePath()); |
337 | 341 | final TableName table = TableName.valueOf("publicTable"); |
338 | 342 |
|
339 | 343 | // Read that row as the client |
@@ -417,6 +421,80 @@ public Void run() throws Exception { |
417 | 421 | }); |
418 | 422 | } |
419 | 423 |
|
| 424 | + @Test |
| 425 | + public void testScanWithDifferentClients() throws Exception { |
| 426 | + Pair<CloseableHttpClient, HttpClientContext> pair = getClient(); |
| 427 | + CloseableHttpClient client = pair.getFirst(); |
| 428 | + HttpClientContext context = pair.getSecond(); |
| 429 | + |
| 430 | + UserGroupInformation ugi = UserGroupInformation |
| 431 | + .loginUserFromKeytabAndReturnUGI(CLIENT_PRINCIPAL, clientKeytab.getAbsolutePath()); |
| 432 | + |
| 433 | + ObjectMapper mapper = new JacksonJaxbJsonProvider().locateMapper(ScannerModel.class, |
| 434 | + MediaType.APPLICATION_JSON_TYPE); |
| 435 | + TableName table = TableName.valueOf("publicTable"); |
| 436 | + ScannerModel model = new ScannerModel(); |
| 437 | + StringEntity entity = |
| 438 | + new StringEntity(mapper.writeValueAsString(model), ContentType.APPLICATION_JSON); |
| 439 | + HttpPost post = |
| 440 | + new HttpPost("http://localhost:" + REST_TEST.getServletPort() + "/" + table + "/scanner"); |
| 441 | + post.setEntity(entity); |
| 442 | + String scannerURI = ugi.doAs(new PrivilegedExceptionAction<String>() { |
| 443 | + |
| 444 | + @Override |
| 445 | + public String run() throws Exception { |
| 446 | + try (CloseableHttpResponse response = client.execute(post, context)) { |
| 447 | + final int statusCode = response.getStatusLine().getStatusCode(); |
| 448 | + assertEquals(HttpURLConnection.HTTP_CREATED, statusCode); |
| 449 | + return response.getFirstHeader("Location").getValue(); |
| 450 | + } |
| 451 | + } |
| 452 | + }); |
| 453 | + |
| 454 | + Pair<CloseableHttpClient, HttpClientContext> pair2 = getClient(); |
| 455 | + CloseableHttpClient client2 = pair2.getFirst(); |
| 456 | + HttpClientContext context2 = pair2.getSecond(); |
| 457 | + |
| 458 | + UserGroupInformation ugi2 = UserGroupInformation |
| 459 | + .loginUserFromKeytabAndReturnUGI(CLIENT_PRINCIPAL2, clientKeytab.getAbsolutePath()); |
| 460 | + ugi2.doAs(new PrivilegedExceptionAction<Void>() { |
| 461 | + |
| 462 | + @Override |
| 463 | + public Void run() throws Exception { |
| 464 | + HttpGet get = new HttpGet(scannerURI + "?n=1"); |
| 465 | + try (CloseableHttpResponse response = client2.execute(get, context2)) { |
| 466 | + final int statusCode = response.getStatusLine().getStatusCode(); |
| 467 | + assertEquals(HttpURLConnection.HTTP_FORBIDDEN, statusCode); |
| 468 | + } |
| 469 | + HttpDelete delete = new HttpDelete(scannerURI); |
| 470 | + try (CloseableHttpResponse response = client2.execute(delete, context2)) { |
| 471 | + final int statusCode = response.getStatusLine().getStatusCode(); |
| 472 | + assertEquals(HttpURLConnection.HTTP_FORBIDDEN, statusCode); |
| 473 | + } |
| 474 | + return null; |
| 475 | + } |
| 476 | + }); |
| 477 | + |
| 478 | + ugi.doAs(new PrivilegedExceptionAction<Void>() { |
| 479 | + |
| 480 | + @Override |
| 481 | + public Void run() throws Exception { |
| 482 | + HttpGet get = new HttpGet(scannerURI + "?n=1"); |
| 483 | + try (CloseableHttpResponse response = client.execute(get, context)) { |
| 484 | + final int statusCode = response.getStatusLine().getStatusCode(); |
| 485 | + assertEquals(HttpURLConnection.HTTP_OK, statusCode); |
| 486 | + } |
| 487 | + HttpDelete delete = new HttpDelete(scannerURI); |
| 488 | + try (CloseableHttpResponse response = client.execute(delete, context)) { |
| 489 | + final int statusCode = response.getStatusLine().getStatusCode(); |
| 490 | + assertEquals(HttpURLConnection.HTTP_OK, statusCode); |
| 491 | + } |
| 492 | + return null; |
| 493 | + } |
| 494 | + }); |
| 495 | + |
| 496 | + } |
| 497 | + |
420 | 498 | private Pair<CloseableHttpClient, HttpClientContext> getClient() { |
421 | 499 | HttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(); |
422 | 500 | HttpHost host = new HttpHost("localhost", REST_TEST.getServletPort()); |
|
0 commit comments