[
https://issues.apache.org/jira/browse/HIVE-26071?focusedWorklogId=763303&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-763303
]
ASF GitHub Bot logged work on HIVE-26071:
-----------------------------------------
Author: ASF GitHub Bot
Created on: 28/Apr/22 06:01
Start Date: 28/Apr/22 06:01
Worklog Time Spent: 10m
Work Description: dengzhhu653 commented on code in PR #3233:
URL: https://github.com/apache/hive/pull/3233#discussion_r860513871
##########
standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestRemoteHiveMetastoreWithHttpJwt.java:
##########
@@ -0,0 +1,269 @@
+/*
+ * 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.hadoop.hive.metastore;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.metastore.annotation.MetastoreUnitTest;
+import org.apache.hadoop.hive.metastore.api.Database;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
+import org.apache.hadoop.hive.metastore.security.HadoopThriftAuthBridge;
+import org.apache.thrift.transport.TTransportException;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@Category(MetastoreUnitTest.class)
+public class TestRemoteHiveMetastoreWithHttpJwt {
+ private static final Map<String, String> DEFAULTS = new
HashMap<>(System.getenv());
+ private static Map<String, String> envMap;
+
+ private static String baseDir = System.getProperty("basedir");
+ private static final File jwtAuthorizedKeyFile =
+ new File(baseDir,"src/test/resources/auth/jwt/jwt-authorized-key.json");
+ private static final File jwtUnauthorizedKeyFile =
+ new
File(baseDir,"src/test/resources/auth/jwt/jwt-unauthorized-key.json");
+ private static final File jwtVerificationJWKSFile =
+ new
File(baseDir,"src/test/resources/auth/jwt/jwt-verification-jwks.json");
+
+ private static final String USER_1 = "HMS_TEST_USER_1";
+ private static final String TEST_DB_NAME_PREFIX = "HMS_JWT_AUTH_DB";
+ private static final Logger LOG =
LoggerFactory.getLogger(TestRemoteHiveMetastoreWithHttpJwt.class);
+ //private static MiniHS2 miniHS2;
+
+ private static final int MOCK_JWKS_SERVER_PORT = 8089;
+ @ClassRule
+ public static final WireMockRule MOCK_JWKS_SERVER = new
WireMockRule(MOCK_JWKS_SERVER_PORT);
+
+ /**
+ * This is a hack to make environment variables modifiable.
+ * Ref:
https://stackoverflow.com/questions/318239/how-do-i-set-environment-variables-from-java.
+ */
+ @BeforeClass
+ public static void makeEnvModifiable() throws Exception {
+ envMap = new HashMap<>();
+ Class<?> envClass = Class.forName("java.lang.ProcessEnvironment");
+ Field theEnvironmentField = envClass.getDeclaredField("theEnvironment");
+ Field theUnmodifiableEnvironmentField =
envClass.getDeclaredField("theUnmodifiableEnvironment");
+ removeStaticFinalAndSetValue(theEnvironmentField, envMap);
+ removeStaticFinalAndSetValue(theUnmodifiableEnvironmentField, envMap);
+ }
+
+ private static void removeStaticFinalAndSetValue(Field field, Object value)
throws Exception {
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(null, value);
+ }
+ private static int port;
+ private static Configuration conf = null;
+
+ public TestRemoteHiveMetastoreWithHttpJwt() {
+ // default constructor
+ }
+
+ @AfterClass
+ public static void stopServices() throws Exception {
+ System.getenv().remove("HMS_JWT");
+ }
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ conf = MetastoreConf.newMetastoreConf();
+
+ // set some values to use for getting conf. vars
+ MetastoreConf.setBoolVar(conf, ConfVars.METRICS_ENABLED, true);
+ conf.set("datanucleus.autoCreateTables", "false");
+ conf.set("hive.in.test", "true");
+ MetastoreConf.setVar(conf, ConfVars.METASTORE_METADATA_TRANSFORMER_CLASS,
" ");
+
+ MetaStoreTestUtils.setConfForStandloneMode(conf);
+ MetastoreConf.setLongVar(conf, ConfVars.BATCH_RETRIEVE_MAX, 2);
+ MetastoreConf.setLongVar(conf, ConfVars.LIMIT_PARTITION_REQUEST, 100);
+ MetastoreConf.setVar(conf, ConfVars.STORAGE_SCHEMA_READER_IMPL,
"no.such.class");
+
+ setupMockServer();
+ MetastoreConf.setBoolVar(conf, ConfVars.EXECUTE_SET_UGI, false);
+ MetastoreConf.setVar(conf, ConfVars.THRIFT_TRANSPORT_MODE, "http");
+ MetastoreConf.setVar(conf,
ConfVars.METASTORE_CLIENT_THRIFT_TRANSPORT_MODE, "http");
+
+ MetastoreConf.setVar(conf, ConfVars.METASTORE_CLIENT_AUTH_MODE, "JWT");
+ MetastoreConf.setVar(conf, ConfVars.THRIFT_METASTORE_AUTHENTICATION,
"JWT");
+ startMetastoreServer();
+ }
+
+ private static void startMetastoreServer() throws Exception {
+ port =
MetaStoreTestUtils.startMetaStoreWithRetry(HadoopThriftAuthBridge.getBridge(),
+ conf);
+ MetastoreConf.setVar(conf, ConfVars.THRIFT_URIS, "thrift://localhost:" +
port);
+ System.out.println("Starting MetaStore Server on port " + port);
+ }
+
+ @Before
+ public void initEnvMap() {
+ envMap.clear();
+ envMap.putAll(DEFAULTS);
+ }
+
+ private static void setupMockServer() throws Exception {
+ MOCK_JWKS_SERVER.stubFor(get("/jwks")
+ .willReturn(ok()
+ .withBody(Files.readAllBytes(jwtVerificationJWKSFile.toPath()))));
+ MetastoreConf.setVar(conf,
ConfVars.THRIFT_METASTORE_AUTHENTICATION_JWT_JWKS_URL,
+ "http://localhost:" + MOCK_JWKS_SERVER_PORT + "/jwks");
+ }
+
+ @Test
+ public void testValidJWT() throws Exception {
+ String validJwtToken = generateJWT(USER_1, jwtAuthorizedKeyFile.toPath(),
+ TimeUnit.MINUTES.toMillis(5));
+ System.getenv().put("HMS_JWT", validJwtToken);
+ String dbName = ("valid_jwt_" + TEST_DB_NAME_PREFIX + "_" +
UUID.randomUUID()).toLowerCase();
+ HiveMetaStoreClient client = new HiveMetaStoreClient(conf);
+ try {
+ Database createdDb = new Database();
+ createdDb.setName(dbName);
+ client.createDatabase(createdDb);
+ Database dbFromServer = client.getDatabase(dbName);
+ assertEquals(dbName, dbFromServer.getName());
+ } finally {
+ try {
+ client.dropDatabase(dbName);
+ } catch (Exception e) {
+ LOG.warn("Failed to drop database: " + dbName + ". Error message: " +
e);
+ }
+ try {
+ client.close();
+ } catch (Exception e) {
+ LOG.error("Failed to close metastore client");
+ }
+ }
+ }
+
+ @Test(expected = TTransportException.class)
+ public void testExpiredJWT() throws Exception {
+ String validJwtToken = generateJWT(USER_1, jwtAuthorizedKeyFile.toPath(),
+ TimeUnit.MILLISECONDS.toMillis(2));
+ System.getenv().put("HMS_JWT", validJwtToken);
+ String dbName = ("expired_jwt_" + TEST_DB_NAME_PREFIX + "_" +
UUID.randomUUID()).toLowerCase();
+ HiveMetaStoreClient client = new HiveMetaStoreClient(conf);
+ try {
+ Thread.sleep(TimeUnit.MILLISECONDS.toMillis(2));
+ Database createdDb = new Database();
+ createdDb.setName(dbName);
+ client.createDatabase(createdDb);
Review Comment:
maybe we should check the exception which is caused by expired token here
Issue Time Tracking
-------------------
Worklog Id: (was: 763303)
Time Spent: 50m (was: 40m)
> JWT authentication for Thrift over HTTP in HiveMetaStore
> --------------------------------------------------------
>
> Key: HIVE-26071
> URL: https://issues.apache.org/jira/browse/HIVE-26071
> Project: Hive
> Issue Type: New Feature
> Components: Standalone Metastore
> Reporter: Sourabh Goyal
> Assignee: Sourabh Goyal
> Priority: Major
> Labels: pull-request-available
> Time Spent: 50m
> Remaining Estimate: 0h
>
> HIVE-25575 recently added a support for JWT authentication in HS2. This Jira
> aims to add the same feature in HMS
--
This message was sent by Atlassian Jira
(v8.20.7#820007)