This is an automated email from the ASF dual-hosted git repository.
soumyakanti3578 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 710baba0027 HIVE-29939: Align data connector authorization and
DESCRIBE output with other metadata objects (#6849)
710baba0027 is described below
commit 710baba0027053de5fd9c19d35f0c6bafc6a5bdd
Author: Ruben Quesada Lopez <[email protected]>
AuthorDate: Mon Oct 5 23:56:47 2026 +0100
HIVE-29939: Align data connector authorization and DESCRIBE output with
other metadata objects (#6849)
---
.../org/apache/hadoop/hive/conf/Constants.java | 23 +++++
.../desc/DescDataConnectorFormatter.java | 29 +++++-
.../org/apache/hadoop/hive/ql/plan/PlanUtils.java | 13 ++-
.../plugin/metastore/HiveMetaStoreAuthorizer.java | 3 +
.../metastore/events/ReadDataConnectorEvent.java | 90 ++++++++++++++++++
.../plugin/sqlstd/Operation2Privilege.java | 6 +-
.../desc/TestDescDataConnectorFormatter.java | 101 +++++++++++++++++++++
.../metastore/TestHiveMetaStoreAuthorizer.java | 48 ++++++++++
.../TestOperation2PrivilegeDataConnector.java | 66 ++++++++++++++
.../clientnegative/dataconnector_authfail_desc.q | 15 +++
.../clientnegative/dataconnector_authfail_show.q | 15 +++
.../queries/clientpositive/dataconnector_props.q | 19 ++++
.../dataconnector_authfail_desc.q.out | 19 ++++
.../dataconnector_authfail_show.q.out | 19 ++++
.../clientpositive/llap/dataconnector.q.out | 6 +-
.../clientpositive/llap/dataconnector_auth.q.out | 6 +-
.../clientpositive/llap/dataconnector_props.q.out | 44 +++++++++
.../apache/hadoop/hive/metastore/HMSHandler.java | 5 +-
.../hive/metastore/events/PreEventContext.java | 1 +
.../events/PreReadDataConnectorEvent.java | 46 ++++++++++
20 files changed, 555 insertions(+), 19 deletions(-)
diff --git a/common/src/java/org/apache/hadoop/hive/conf/Constants.java
b/common/src/java/org/apache/hadoop/hive/conf/Constants.java
index ffb1afd954e..cdfa8ef4872 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/Constants.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/Constants.java
@@ -18,6 +18,10 @@
*/
package org.apache.hadoop.hive.conf;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import java.util.regex.Pattern;
public class Constants {
@@ -54,6 +58,25 @@ public class Constants {
public static final String JDBC_LOW_BOUND = JDBC_CONFIG_PREFIX +
".lowerBound";
public static final String JDBC_UPPER_BOUND = JDBC_CONFIG_PREFIX +
".upperBound";
+ /**
+ * The DBCP credentials a JDBC-backed table carries in TBLPROPERTIES, or a
data connector in
+ * DCPROPERTIES. Explain output drops these keys (HIVE-28838), and the
connector description
+ * withholds their values, so that they round-trip only through the
metastore rather than back to
+ * whoever asked. The keys that merely point at a credential -- {@link
#JDBC_PASSWORD_URI},
+ * {@link #JDBC_KEYSTORE} and {@link #JDBC_KEY} -- are deliberately not
included: they exist so
+ * that the password need not be stored here, and seeing where one resolves
from is exactly what
+ * an administrator needs.
+ */
+ public static final Set<String> JDBC_CONNECTION_CREDENTIALS =
Collections.unmodifiableSet(
+ new HashSet<>(Arrays.asList(JDBC_USERNAME, JDBC_PASSWORD)));
+
+ /**
+ * Stands in for a withheld {@link #JDBC_CONNECTION_CREDENTIALS} value where
a property map is
+ * listed back to the user. A property whose value is withheld keeps its
key, so that the listing
+ * says "this is set, but not shown here" rather than implying the property
is absent.
+ */
+ public static final String WITHHELD_VALUE = "(withheld)";
+
public static final String HIVE_SERVER2_JOB_CREDSTORE_PASSWORD_ENVVAR =
"HIVE_JOB_CREDSTORE_PASSWORD";
public static final String HADOOP_CREDENTIAL_PASSWORD_ENVVAR =
"HADOOP_CREDSTORE_PASSWORD";
public static final String HADOOP_CREDENTIAL_PROVIDER_PATH_CONFIG =
"hadoop.security.credential.provider.path";
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/DescDataConnectorFormatter.java
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/DescDataConnectorFormatter.java
index 0236e632ea4..8ffab3f8b80 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/DescDataConnectorFormatter.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/DescDataConnectorFormatter.java
@@ -20,6 +20,7 @@
package org.apache.hadoop.hive.ql.ddl.dataconnector.desc;
import org.apache.commons.collections4.MapUtils;
+import org.apache.hadoop.hive.conf.Constants;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.metastore.api.PrincipalType;
import org.apache.hadoop.hive.ql.ddl.ShowUtils;
@@ -33,6 +34,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;
+import java.util.TreeMap;
/**
* Formats DESC CONNECTOR results.
@@ -46,6 +48,23 @@ static DescDataConnectorFormatter getFormatter(HiveConf
conf) {
}
}
+ /**
+ * The DBCP credentials in DCPROPERTIES are not part of the connector
description. Explain output
+ * removes these keys outright (HIVE-28838); a description keeps them and
replaces only the value,
+ * because its purpose is to report what the connector is configured with --
dropping the key here
+ * would make a configured credential read as though none were set. Every
other connector
+ * parameter is left untouched.
+ */
+ private static Map<String, String> describableParams(Map<String, String>
params) {
+ if (MapUtils.isEmpty(params)) {
+ return params;
+ }
+ Map<String, String> described = new TreeMap<>(params);
+ described.replaceAll((key, value) ->
+ Constants.JDBC_CONNECTION_CREDENTIALS.contains(key) ?
Constants.WITHHELD_VALUE : value);
+ return described;
+ }
+
abstract void showDataConnectorDescription(DataOutputStream out, String
connector, String type, String url,
String ownerName, PrincipalType ownerType, String comment, Map<String,
String> params)
throws HiveException;
@@ -70,8 +89,9 @@ void showDataConnectorDescription(DataOutputStream out,
String connector, String
if (comment != null) {
builder.put("comment", comment);
}
- if (MapUtils.isNotEmpty(params)) {
- builder.put("params", params);
+ Map<String, String> describableParams = describableParams(params);
+ if (MapUtils.isNotEmpty(describableParams)) {
+ builder.put("params", describableParams);
}
ShowUtils.asJson(out, builder.build());
}
@@ -105,8 +125,9 @@ void showDataConnectorDescription(DataOutputStream out,
String connector, String
out.write(HiveStringUtils.escapeJava(comment).getBytes(StandardCharsets.UTF_8));
}
out.write(Utilities.tabCode);
- if (MapUtils.isNotEmpty(params)) {
- out.write(params.toString().getBytes(StandardCharsets.UTF_8));
+ Map<String, String> describableParams = describableParams(params);
+ if (MapUtils.isNotEmpty(describableParams)) {
+
out.write(describableParams.toString().getBytes(StandardCharsets.UTF_8));
}
out.write(Utilities.newLineCode);
} catch (IOException e) {
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java
b/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java
index 7083950a2a8..fb79c96f8eb 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/PlanUtils.java
@@ -20,11 +20,12 @@
package org.apache.hadoop.hive.ql.plan;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import static org.apache.hadoop.hive.conf.Constants.JDBC_PASSWORD;
-import static org.apache.hadoop.hive.conf.Constants.JDBC_USERNAME;
import static
org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_CTAS;
import static org.apache.hive.common.util.HiveStringUtils.quoteComments;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -41,6 +42,7 @@
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.common.JavaUtils;
import org.apache.hadoop.hive.common.StatsSetupConst;
+import org.apache.hadoop.hive.conf.Constants;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.llap.LlapOutputFormat;
@@ -1130,11 +1132,8 @@ public static Class<? extends AbstractSerDe>
getDefaultSerDe() {
return LazySimpleSerDe.class;
}
- private static final String[] FILTER_OUT_FROM_EXPLAIN = {
- TABLE_IS_CTAS,
- JDBC_USERNAME,
- JDBC_PASSWORD
- };
+ private static final Set<String> FILTER_OUT_FROM_EXPLAIN =
+ Sets.union(ImmutableSet.of(TABLE_IS_CTAS),
Constants.JDBC_CONNECTION_CREDENTIALS);
/**
* Get a Map of table or partition properties to be used in explain extended
output.
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/HiveMetaStoreAuthorizer.java
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/HiveMetaStoreAuthorizer.java
index c7f7c2d2b65..baca0b56a16 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/HiveMetaStoreAuthorizer.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/HiveMetaStoreAuthorizer.java
@@ -574,6 +574,9 @@ HiveMetaStoreAuthzInfo buildAuthzContext(PreEventContext
preEventContext) throws
case DROP_DATACONNECTOR:
authzEvent = new DropDataConnectorEvent(preEventContext);
break;
+ case READ_DATACONNECTOR:
+ authzEvent = new ReadDataConnectorEvent(preEventContext);
+ break;
case AUTHORIZATION_API_CALL:
case READ_ISCHEMA:
case CREATE_ISCHEMA:
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/events/ReadDataConnectorEvent.java
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/events/ReadDataConnectorEvent.java
new file mode 100644
index 00000000000..6d3f8ab8157
--- /dev/null
+++
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/events/ReadDataConnectorEvent.java
@@ -0,0 +1,90 @@
+/*
+ * 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.ql.security.authorization.plugin.metastore.events;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.hive.metastore.api.DataConnector;
+import org.apache.hadoop.hive.metastore.events.PreEventContext;
+import org.apache.hadoop.hive.metastore.events.PreReadDataConnectorEvent;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HiveAuthzContext;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.metastore.HiveMetaStoreAuthorizableEvent;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.metastore.HiveMetaStoreAuthzInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ Authorizable Event for HiveMetaStore operation GetDataConnector
+ */
+
+public class ReadDataConnectorEvent extends HiveMetaStoreAuthorizableEvent {
+ private static final Logger LOG =
LoggerFactory.getLogger(ReadDataConnectorEvent.class);
+
+ private String COMMAND_STR = "describe connector";
+
+ public ReadDataConnectorEvent(PreEventContext preEventContext) {
+ super(preEventContext);
+ }
+
+ @Override
+ public HiveMetaStoreAuthzInfo getAuthzContext() {
+ // Collecting the input objects is what completes COMMAND_STR with the
connector name, so the
+ // context has to be built afterwards for the two to agree.
+ List<HivePrivilegeObject> inputHObjs = getInputHObjs();
+ HiveAuthzContext authzContext = buildAuthzContext(COMMAND_STR);
+ HiveMetaStoreAuthzInfo ret = new HiveMetaStoreAuthzInfo(preEventContext,
HiveOperationType.DESCDATACONNECTOR,
+ inputHObjs, getOutputHObjs(), COMMAND_STR, authzContext);
+ LOG.debug("ReadDataConnectorEvent.getAuthzContext(): authzContext={}",
authzContext);
+ return ret;
+ }
+
+ private List<HivePrivilegeObject> getInputHObjs() {
+ LOG.debug("==> ReadDataConnectorEvent.getInputHObjs()");
+
+ List<HivePrivilegeObject> ret = new ArrayList<>();
+ PreReadDataConnectorEvent event = (PreReadDataConnectorEvent)
preEventContext;
+ DataConnector connector = event.getDataConnector();
+ ret.add(getHivePrivilegeObject(connector));
+ COMMAND_STR = buildCommandString(COMMAND_STR, connector);
+
+ LOG.debug("<== ReadDataConnectorEvent.getInputHObjs(): ret={}", ret);
+ return ret;
+ }
+
+ private List<HivePrivilegeObject> getOutputHObjs() {
+ return Collections.emptyList();
+ }
+
+ private String buildCommandString(String cmdStr, DataConnector connector) {
+ String ret = cmdStr;
+
+ if (connector != null) {
+ String dcName = connector.getName();
+ ret = ret + (StringUtils.isNotEmpty(dcName) ? " " + dcName : "");
+ }
+
+ return ret;
+ }
+}
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java
index 898a0c8c673..419df7b3e0b 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/Operation2Privilege.java
@@ -475,8 +475,12 @@ public HivePrivilegeObjectType getObjectType() {
op2Priv.put(HiveOperationType.ALTERDATACONNECTOR,
PrivRequirement.newIOPrivRequirement(null, ADMIN_PRIV_AR));
op2Priv.put(HiveOperationType.ALTERDATACONNECTOR_OWNER,
PrivRequirement.newIOPrivRequirement(null, ADMIN_PRIV_AR));
op2Priv.put(HiveOperationType.ALTERDATACONNECTOR_URL,
PrivRequirement.newIOPrivRequirement(null, ADMIN_PRIV_AR));
- op2Priv.put(HiveOperationType.DESCDATACONNECTOR,
PrivRequirement.newIOPrivRequirement(null, null));
+ // A connector definition carries the DBCP credentials for the remote
source, so rendering one
+ // requires the same privilege as creating, altering or dropping it. SHOW
CONNECTORS registers
+ // no entity of its own, so it is gated as a whole rather than per object.
+ op2Priv.put(HiveOperationType.DESCDATACONNECTOR,
PrivRequirement.newIOPrivRequirement(ADMIN_PRIV_AR, null));
op2Priv.put(HiveOperationType.SHOWDATACONNECTORS,
PrivRequirement.newIOPrivRequirement(null, null));
+ adminPrivOps.add(HiveOperationType.SHOWDATACONNECTORS);
op2Priv.put(HiveOperationType.CREATECATALOG,
PrivRequirement.newPrivRequirementList(
new PrivRequirement(INS_SEL_DEL_NOGRANT_AR,
HivePrivilegeObjectType.DFS_URI),
diff --git
a/ql/src/test/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/TestDescDataConnectorFormatter.java
b/ql/src/test/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/TestDescDataConnectorFormatter.java
new file mode 100644
index 00000000000..c3eb67554f9
--- /dev/null
+++
b/ql/src/test/org/apache/hadoop/hive/ql/ddl/dataconnector/desc/TestDescDataConnectorFormatter.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ql.ddl.dataconnector.desc;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.hadoop.hive.conf.Constants;
+import org.apache.hadoop.hive.metastore.api.PrincipalType;
+import org.junit.Test;
+
+/**
+ * Tests for the DESC CONNECTOR formatters.
+ *
+ * <p>The DBCP connection properties carried in DCPROPERTIES are the same keys
that
+ * {@code PlanUtils.getPropertiesForExplain} drops from explain output
(HIVE-28838).
+ * The formatters here render the connector parameter map, so they are
expected to keep
+ * these values out of it too -- by withholding the value rather than dropping
the key,
+ * since a description is meant to report what is configured.</p>
+ */
+public class TestDescDataConnectorFormatter {
+
+ private static final String CONNECTOR_NAME = "dc1";
+ private static final String CONNECTOR_TYPE = "mysql";
+ private static final String CONNECTOR_URL = "jdbc:mysql://example:3306/db1";
+ private static final String OWNER = "owner1";
+ private static final String COMMENT = "a connector";
+
+ private static final String USERNAME_VALUE = "etl_acct_9x";
+ private static final String PASSWORD_VALUE = "Zq7vNt2xKd";
+
+ private static Map<String, String> connectionParams() {
+ Map<String, String> params = new TreeMap<>();
+ params.put(Constants.JDBC_USERNAME, USERNAME_VALUE);
+ params.put(Constants.JDBC_PASSWORD, PASSWORD_VALUE);
+ params.put(Constants.JDBC_DATABASE_TYPE, "MYSQL");
+ return params;
+ }
+
+ private static String format(DescDataConnectorFormatter formatter) throws
Exception {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ try (DataOutputStream out = new DataOutputStream(bytes)) {
+ formatter.showDataConnectorDescription(out, CONNECTOR_NAME,
CONNECTOR_TYPE, CONNECTOR_URL,
+ OWNER, PrincipalType.USER, COMMENT, connectionParams());
+ }
+ return bytes.toString(StandardCharsets.UTF_8.name());
+ }
+
+ /**
+ * The connection property keys stay in the listing -- so it is still
apparent that they are
+ * configured -- while their values are reported as withheld rather than
rendered.
+ */
+ private static void assertValuesWithheld(String output) {
+ // Unrelated parameters are still expected in the extended output.
+ assertTrue("expected the non-connection parameters to be rendered",
+ output.contains(Constants.JDBC_DATABASE_TYPE));
+
+ assertTrue("expected the connection property keys to remain listed: " +
output,
+ output.contains(Constants.JDBC_USERNAME) &&
output.contains(Constants.JDBC_PASSWORD));
+ assertTrue("expected the connection property values to read as withheld: "
+ output,
+ output.contains(Constants.WITHHELD_VALUE));
+
+ assertFalse("DBCP password value rendered in DESC CONNECTOR EXTENDED
output: " + output,
+ output.contains(PASSWORD_VALUE));
+ assertFalse("DBCP username value rendered in DESC CONNECTOR EXTENDED
output: " + output,
+ output.contains(USERNAME_VALUE));
+ }
+
+ @Test
+ public void testTextExtendedOutputOmitsConnectionPropertyValues() throws
Exception {
+ assertValuesWithheld(format(new
DescDataConnectorFormatter.TextDescDataConnectorFormatter()));
+ }
+
+ @Test
+ public void testJsonExtendedOutputOmitsConnectionPropertyValues() throws
Exception {
+ assertValuesWithheld(format(new
DescDataConnectorFormatter.JsonDescDataConnectorFormatter()));
+ }
+}
diff --git
a/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/TestHiveMetaStoreAuthorizer.java
b/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/TestHiveMetaStoreAuthorizer.java
index 5c14511af30..dc3dcaf9f9a 100644
---
a/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/TestHiveMetaStoreAuthorizer.java
+++
b/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/metastore/TestHiveMetaStoreAuthorizer.java
@@ -59,6 +59,7 @@
import org.mockito.Mockito;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.File;
@@ -718,6 +719,53 @@ public void testU_DropDataConnector_authorizedUser() {
}
}
+ private static Map<String, String> connectorParams() {
+ Map<String, String> params = new HashMap<>();
+ params.put("hive.sql.dbcp.username", "etl_acct_9x");
+ params.put("hive.sql.dbcp.password", "Zq7vNt2xKd");
+ return params;
+ }
+
+ private void recreateDataConnector() throws Exception {
+ DropDataConnectorRequest dropDcReq = new DropDataConnectorRequest(dcName);
+ dropDcReq.setIfNotExists(true);
+ dropDcReq.setCheckReferences(false);
+ hmsHandler.drop_dataconnector_req(dropDcReq);
+
+ DataConnector connector = new DataConnector(dcName, "mysql",
"jdbc:mysql://localhost:3306/hive");
+ connector.setParameters(connectorParams());
+ hmsHandler.create_dataconnector_req(new
CreateDataConnectorRequest(connector));
+ }
+
+ @Test
+ public void testV1_GetDataConnector_unAuthorizedUser() throws Exception {
+
UserGroupInformation.setLoginUser(UserGroupInformation.createRemoteUser(authorizedUser));
+ recreateDataConnector();
+
+
UserGroupInformation.setLoginUser(UserGroupInformation.createRemoteUser(unAuthorizedUser));
+ try {
+ hmsHandler.get_dataconnector_req(new GetDataConnectorRequest(dcName));
+ fail("get_dataconnector_req() was served for user:" + unAuthorizedUser);
+ } catch (Exception e) {
+ assertTrue("unexpected failure for user:" + unAuthorizedUser + " - " +
e.getMessage(),
+ e.getMessage() != null && e.getMessage().contains("not allowed for
user:" + unAuthorizedUser));
+ }
+ }
+
+ @Test
+ public void testV2_GetDataConnector_authorizedUser() throws Exception {
+
UserGroupInformation.setLoginUser(UserGroupInformation.createRemoteUser(authorizedUser));
+ recreateDataConnector();
+
+ try {
+ DataConnector connector = hmsHandler.get_dataconnector_req(new
GetDataConnectorRequest(dcName));
+ assertTrue("unexpected connector returned: " + connector.getName(),
+ dcName.equalsIgnoreCase(connector.getName()));
+ assertEquals(connectorParams(), connector.getParameters());
+ } catch (Exception e) {
+ fail("testV2_GetDataConnector_authorizedUser() failed with " + e);
+ }
+ }
/**
* Captures and returns the privilege objects for Alter Partition
diff --git
a/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/TestOperation2PrivilegeDataConnector.java
b/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/TestOperation2PrivilegeDataConnector.java
new file mode 100644
index 00000000000..653c6a571ba
--- /dev/null
+++
b/ql/src/test/org/apache/hadoop/hive/ql/security/authorization/plugin/sqlstd/TestOperation2PrivilegeDataConnector.java
@@ -0,0 +1,66 @@
+/*
+ * 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.ql.security.authorization.plugin.sqlstd;
+
+import static org.junit.Assert.assertTrue;
+
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HiveOperationType;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.HivePrivilegeObject.HivePrivilegeObjectType;
+import
org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.Operation2Privilege.IOType;
+import org.junit.Test;
+
+/**
+ * Privilege requirements the SQL standard authorizer applies to the data
connector
+ * operations.
+ *
+ * <p>Connector definitions carry the DBCP connection properties for the
remote source,
+ * and CREATE / ALTER / DROP CONNECTOR are all admin-only. The operations that
render a
+ * connector definition are expected to carry a requirement of their own
rather than
+ * resolving to an empty privilege set.</p>
+ */
+public class TestOperation2PrivilegeDataConnector {
+
+ private static final String CONNECTOR_NAME = "dc1";
+
+ private static HivePrivilegeObject connectorObject() {
+ return new HivePrivilegeObject(HivePrivilegeObjectType.DATACONNECTOR,
CONNECTOR_NAME);
+ }
+
+ @Test
+ public void testDescribeConnectorHasAnInputRequirement() {
+ RequiredPrivileges required =
+
Operation2Privilege.getRequiredPrivs(HiveOperationType.DESCDATACONNECTOR,
connectorObject(), IOType.INPUT);
+
+ assertTrue("DESCDATACONNECTOR resolves to an empty input privilege set",
+ !required.getRequiredPrivilegeSet().isEmpty()
+ ||
Operation2Privilege.isAdminPrivOperation(HiveOperationType.DESCDATACONNECTOR));
+ }
+
+ @Test
+ public void testShowConnectorsHasAnInputRequirement() {
+ RequiredPrivileges required =
+
Operation2Privilege.getRequiredPrivs(HiveOperationType.SHOWDATACONNECTORS,
connectorObject(), IOType.INPUT);
+
+ assertTrue("SHOWDATACONNECTORS resolves to an empty input privilege set",
+ !required.getRequiredPrivilegeSet().isEmpty()
+ ||
Operation2Privilege.isAdminPrivOperation(HiveOperationType.SHOWDATACONNECTORS));
+ }
+}
diff --git a/ql/src/test/queries/clientnegative/dataconnector_authfail_desc.q
b/ql/src/test/queries/clientnegative/dataconnector_authfail_desc.q
new file mode 100644
index 00000000000..b743668d1ac
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/dataconnector_authfail_desc.q
@@ -0,0 +1,15 @@
+-- CREATE IF NOT EXISTS already
+CREATE CONNECTOR IF NOT EXISTS mysql_auth_desc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1");
+
+-- test data connector authorization feature
+SET hive.security.authorization.enabled=true;
+
+-- DESCRIBE fail: reading a connector definition is expected to carry the same
+-- requirement as the create / alter / drop counterparts
+DESCRIBE CONNECTOR EXTENDED mysql_auth_desc;
diff --git a/ql/src/test/queries/clientnegative/dataconnector_authfail_show.q
b/ql/src/test/queries/clientnegative/dataconnector_authfail_show.q
new file mode 100644
index 00000000000..406a0227e7e
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/dataconnector_authfail_show.q
@@ -0,0 +1,15 @@
+-- CREATE IF NOT EXISTS already
+CREATE CONNECTOR IF NOT EXISTS mysql_auth_show
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1");
+
+-- test data connector authorization feature
+SET hive.security.authorization.enabled=true;
+
+-- SHOW fail: enumerating connectors is expected to carry the same requirement
as the
+-- create / alter / drop counterparts
+SHOW CONNECTORS;
diff --git a/ql/src/test/queries/clientpositive/dataconnector_props.q
b/ql/src/test/queries/clientpositive/dataconnector_props.q
new file mode 100644
index 00000000000..6c35f2ae2ba
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/dataconnector_props.q
@@ -0,0 +1,19 @@
+-- DESCRIBE CONNECTOR EXTENDED renders the connector parameter map.
+-- DCPROPERTIES carries the DBCP connection properties for the remote source;
these are
+-- the same keys that are dropped from explain output (HIVE-28838), alongside
ordinary
+-- connector tuning parameters that are expected to round-trip.
+CREATE CONNECTOR IF NOT EXISTS mysql_props_dc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1",
+"hive.connector.autoReconnect"="true",
+"hive.connector.maxReconnects"="3");
+
+DESCRIBE CONNECTOR mysql_props_dc;
+DESCRIBE CONNECTOR EXTENDED mysql_props_dc;
+
+-- clean up so it won't affect other tests
+DROP CONNECTOR mysql_props_dc;
diff --git
a/ql/src/test/results/clientnegative/dataconnector_authfail_desc.q.out
b/ql/src/test/results/clientnegative/dataconnector_authfail_desc.q.out
new file mode 100644
index 00000000000..b0d4081f88f
--- /dev/null
+++ b/ql/src/test/results/clientnegative/dataconnector_authfail_desc.q.out
@@ -0,0 +1,19 @@
+PREHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_auth_desc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1")
+PREHOOK: type: CREATEDATACONNECTOR
+PREHOOK: Output: connector:mysql_auth_desc
+POSTHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_auth_desc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1")
+POSTHOOK: type: CREATEDATACONNECTOR
+POSTHOOK: Output: connector:mysql_auth_desc
+FAILED: HiveAccessControlException Permission denied: Principal
[name=hive_test_user, type=USER] does not have following privileges for
operation DESCDATACONNECTOR [[ADMIN PRIVILEGE] on Object [type=DATACONNECTOR,
name=mysql_auth_desc]]
diff --git
a/ql/src/test/results/clientnegative/dataconnector_authfail_show.q.out
b/ql/src/test/results/clientnegative/dataconnector_authfail_show.q.out
new file mode 100644
index 00000000000..6785500058a
--- /dev/null
+++ b/ql/src/test/results/clientnegative/dataconnector_authfail_show.q.out
@@ -0,0 +1,19 @@
+PREHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_auth_show
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1")
+PREHOOK: type: CREATEDATACONNECTOR
+PREHOOK: Output: connector:mysql_auth_show
+POSTHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_auth_show
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1")
+POSTHOOK: type: CREATEDATACONNECTOR
+POSTHOOK: Output: connector:mysql_auth_show
+FAILED: HiveAccessControlException Permission denied: Principal
[name=hive_test_user, type=USER] does not have following privileges for
operation SHOWDATACONNECTORS [ADMIN PRIVILEGE on INPUT, ADMIN PRIVILEGE on
OUTPUT]
diff --git a/ql/src/test/results/clientpositive/llap/dataconnector.q.out
b/ql/src/test/results/clientpositive/llap/dataconnector.q.out
index 3582a519ee5..5da89320a51 100644
--- a/ql/src/test/results/clientpositive/llap/dataconnector.q.out
+++ b/ql/src/test/results/clientpositive/llap/dataconnector.q.out
@@ -152,7 +152,7 @@ PREHOOK: Input: connector:mysql_test
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_test
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_test
-mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_test_user USER test connector {hive.sql.dbcp.password=hive1,
hive.sql.dbcp.username=hive1}
+mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_test_user USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: alter connector mysql_test set
DCPROPERTIES("hive.sql.dbcp.username"="hive2","hive.sql.dbcp.password"="hive2")
PREHOOK: type: ALTERDATACONNECTOR
PREHOOK: Output: connector:mysql_test
@@ -165,7 +165,7 @@ PREHOOK: Input: connector:mysql_test
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_test
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_test
-mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_test_user USER test connector {hive.sql.dbcp.password=hive2,
hive.sql.dbcp.username=hive2}
+mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_test_user USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: alter connector mysql_test set OWNER USER newuser
PREHOOK: type: ALTERDATABASE_OWNER
PREHOOK: Output: connector:mysql_test
@@ -178,7 +178,7 @@ PREHOOK: Input: connector:mysql_test
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_test
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_test
-mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2 newuser
USER test connector {hive.sql.dbcp.password=hive2,
hive.sql.dbcp.username=hive2}
+mysql_test mysql jdbc:mysql://nightly1.apache.org:3306/hive2 newuser
USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: DROP DATABASE db_derby
PREHOOK: type: DROPDATABASE
PREHOOK: Input: database:db_derby
diff --git a/ql/src/test/results/clientpositive/llap/dataconnector_auth.q.out
b/ql/src/test/results/clientpositive/llap/dataconnector_auth.q.out
index 8d7973622a2..3d2b218e6a9 100644
--- a/ql/src/test/results/clientpositive/llap/dataconnector_auth.q.out
+++ b/ql/src/test/results/clientpositive/llap/dataconnector_auth.q.out
@@ -37,7 +37,7 @@ PREHOOK: Input: connector:mysql_auth_dc
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_auth_dc
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_auth_dc
-mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_admin_user USER test connector {hive.sql.dbcp.password=hive1,
hive.sql.dbcp.username=hive1}
+mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_admin_user USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: alter connector mysql_auth_dc set
DCPROPERTIES("hive.sql.dbcp.username"="hive2","hive.sql.dbcp.password"="hive2")
PREHOOK: type: ALTERDATACONNECTOR
PREHOOK: Output: connector:mysql_auth_dc
@@ -50,7 +50,7 @@ PREHOOK: Input: connector:mysql_auth_dc
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_auth_dc
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_auth_dc
-mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_admin_user USER test connector {hive.sql.dbcp.password=hive2,
hive.sql.dbcp.username=hive2}
+mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2
hive_admin_user USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: alter connector mysql_auth_dc set OWNER USER newuser
PREHOOK: type: ALTERDATABASE_OWNER
PREHOOK: Output: connector:mysql_auth_dc
@@ -63,7 +63,7 @@ PREHOOK: Input: connector:mysql_auth_dc
POSTHOOK: query: DESCRIBE CONNECTOR extended mysql_auth_dc
POSTHOOK: type: DESCDATACONNECTOR
POSTHOOK: Input: connector:mysql_auth_dc
-mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2 newuser
USER test connector {hive.sql.dbcp.password=hive2,
hive.sql.dbcp.username=hive2}
+mysql_auth_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive2 newuser
USER test connector {hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
PREHOOK: query: CREATE REMOTE DATABASE db_mysql_auth USING mysql_auth_dc with
DBPROPERTIES("connector.remoteDbName"="hive1")
PREHOOK: type: CREATEDATABASE
PREHOOK: Input: connector:mysql_auth_dc
diff --git a/ql/src/test/results/clientpositive/llap/dataconnector_props.q.out
b/ql/src/test/results/clientpositive/llap/dataconnector_props.q.out
new file mode 100644
index 00000000000..7891eb96ecb
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/dataconnector_props.q.out
@@ -0,0 +1,44 @@
+PREHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_props_dc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1",
+"hive.connector.autoReconnect"="true",
+"hive.connector.maxReconnects"="3")
+PREHOOK: type: CREATEDATACONNECTOR
+PREHOOK: Output: connector:mysql_props_dc
+POSTHOOK: query: CREATE CONNECTOR IF NOT EXISTS mysql_props_dc
+TYPE 'mysql'
+URL 'jdbc:mysql://nightly1.apache.org:3306/hive1'
+COMMENT 'test connector'
+WITH DCPROPERTIES (
+"hive.sql.dbcp.username"="hive1",
+"hive.sql.dbcp.password"="hive1",
+"hive.connector.autoReconnect"="true",
+"hive.connector.maxReconnects"="3")
+POSTHOOK: type: CREATEDATACONNECTOR
+POSTHOOK: Output: connector:mysql_props_dc
+PREHOOK: query: DESCRIBE CONNECTOR mysql_props_dc
+PREHOOK: type: DESCDATACONNECTOR
+PREHOOK: Input: connector:mysql_props_dc
+POSTHOOK: query: DESCRIBE CONNECTOR mysql_props_dc
+POSTHOOK: type: DESCDATACONNECTOR
+POSTHOOK: Input: connector:mysql_props_dc
+mysql_props_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive1
hive_test_user USER test connector
+PREHOOK: query: DESCRIBE CONNECTOR EXTENDED mysql_props_dc
+PREHOOK: type: DESCDATACONNECTOR
+PREHOOK: Input: connector:mysql_props_dc
+POSTHOOK: query: DESCRIBE CONNECTOR EXTENDED mysql_props_dc
+POSTHOOK: type: DESCDATACONNECTOR
+POSTHOOK: Input: connector:mysql_props_dc
+mysql_props_dc mysql jdbc:mysql://nightly1.apache.org:3306/hive1
hive_test_user USER test connector {hive.connector.autoReconnect=true,
hive.connector.maxReconnects=3, hive.sql.dbcp.password=(withheld),
hive.sql.dbcp.username=(withheld)}
+PREHOOK: query: DROP CONNECTOR mysql_props_dc
+PREHOOK: type: DROPDATACONNECTOR
+PREHOOK: Input: connector:mysql_props_dc
+PREHOOK: Output: connector:mysql_props_dc
+POSTHOOK: query: DROP CONNECTOR mysql_props_dc
+POSTHOOK: type: DROPDATACONNECTOR
+POSTHOOK: Input: connector:mysql_props_dc
+POSTHOOK: Output: connector:mysql_props_dc
diff --git
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index e5c8d4aa322..246a627fba3 100644
---
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -632,15 +632,18 @@ public DataConnector get_dataconnector_core(final String
name) throws NoSuchObje
public DataConnector get_dataconnector_req(GetDataConnectorRequest request)
throws NoSuchObjectException, MetaException {
startFunction("get_dataconnector", ": " + request.getConnectorName());
DataConnector connector = null;
+ boolean success = false;
Exception ex = null;
try {
connector = get_dataconnector_core(request.getConnectorName());
+ firePreEvent(new PreReadDataConnectorEvent(connector, this));
+ success = true;
} catch (Exception e) {
ex = e;
throw handleException(e).throwIfInstance(MetaException.class,
NoSuchObjectException.class)
.defaultRuntimeException();
} finally {
- endFunction("get_dataconnector", connector != null, ex);
+ endFunction("get_dataconnector", success, ex);
}
return connector;
}
diff --git
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreEventContext.java
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreEventContext.java
index 3f93bbdb987..ef44becfa8c 100644
---
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreEventContext.java
+++
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreEventContext.java
@@ -59,6 +59,7 @@ public enum PreEventType {
CREATE_DATACONNECTOR,
DROP_DATACONNECTOR,
ALTER_DATACONNECTOR,
+ READ_DATACONNECTOR,
CREATE_FUNCTION,
DROP_FUNCTION
}
diff --git
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreReadDataConnectorEvent.java
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreReadDataConnectorEvent.java
new file mode 100644
index 00000000000..659f60a56b1
--- /dev/null
+++
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/events/PreReadDataConnectorEvent.java
@@ -0,0 +1,46 @@
+/*
+ * 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.events;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.hive.metastore.IHMSHandler;
+import org.apache.hadoop.hive.metastore.api.DataConnector;
+
+/**
+ * Data connector read event.
+ */
[email protected]
[email protected]
+public class PreReadDataConnectorEvent extends PreEventContext {
+ private final DataConnector connector;
+
+ public PreReadDataConnectorEvent(DataConnector connector, IHMSHandler
handler) {
+ super(PreEventType.READ_DATACONNECTOR, handler);
+ this.connector = connector;
+ }
+
+ /**
+ * @return the connector
+ */
+ public DataConnector getDataConnector() {
+ return connector;
+ }
+}