From commits-return-11376-apmail-sentry-commits-archive=sentry.apache.org@sentry.apache.org Fri Jun 24 06:00:32 2016 Return-Path: X-Original-To: apmail-sentry-commits-archive@minotaur.apache.org Delivered-To: apmail-sentry-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8765D19EB0 for ; Fri, 24 Jun 2016 06:00:32 +0000 (UTC) Received: (qmail 30455 invoked by uid 500); 24 Jun 2016 06:00:32 -0000 Delivered-To: apmail-sentry-commits-archive@sentry.apache.org Received: (qmail 30358 invoked by uid 500); 24 Jun 2016 06:00:32 -0000 Mailing-List: contact commits-help@sentry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sentry.apache.org Delivered-To: mailing list commits@sentry.apache.org Received: (qmail 29348 invoked by uid 99); 24 Jun 2016 06:00:31 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 24 Jun 2016 06:00:31 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 04870E38B1; Fri, 24 Jun 2016 06:00:31 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: colin@apache.org To: commits@sentry.apache.org Date: Fri, 24 Jun 2016 06:00:47 -0000 Message-Id: <6d0d8b5ca63842749bbdf8af36a0b6e0@git.apache.org> In-Reply-To: <69ce40b9667f4711b5187933d6e3aa2f@git.apache.org> References: <69ce40b9667f4711b5187933d6e3aa2f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [18/44] sentry git commit: SENTRY-1287: Create sentry-service-server module(Colin Ma, reviewed by Dapeng Sun) http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStoreSchemaInfo.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStoreSchemaInfo.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStoreSchemaInfo.java new file mode 100644 index 0000000..223cc87 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStoreSchemaInfo.java @@ -0,0 +1,143 @@ +/** + * 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.sentry.provider.db.service.persistent; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.sentry.core.common.exception.SentryUserException; + +public class SentryStoreSchemaInfo { + private static final String SQL_FILE_EXTENSION = ".sql"; + private static final String UPGRADE_FILE_PREFIX = "upgrade-"; + private static final String INIT_FILE_PREFIX = "sentry-"; + private static final String VERSION_UPGRADE_LIST = "upgrade.order"; + private final String dbType; + private final String sentrySchemaVersions[]; + private final String sentryScriptDir; + + private static final String SENTRY_VERSION = "1.8.0"; + + public SentryStoreSchemaInfo(String sentryScriptDir, String dbType) + throws SentryUserException { + this.sentryScriptDir = sentryScriptDir; + this.dbType = dbType; + // load upgrade order for the given dbType + List upgradeOrderList = new ArrayList(); + String upgradeListFile = getSentryStoreScriptDir() + File.separator + + VERSION_UPGRADE_LIST + "." + dbType; + try (BufferedReader bfReader = new BufferedReader(new FileReader(upgradeListFile))) { + String currSchemaVersion; + while ((currSchemaVersion = bfReader.readLine()) != null) { + upgradeOrderList.add(currSchemaVersion.trim()); + } + } catch (FileNotFoundException e) { + throw new SentryUserException("File " + upgradeListFile + " not found ", e); + } catch (IOException e) { + throw new SentryUserException("Error reading " + upgradeListFile, e); + } + sentrySchemaVersions = upgradeOrderList.toArray(new String[0]); + } + + public String getSentrySchemaVersion() { + return SENTRY_VERSION; + } + + public List getUpgradeScripts(String fromSchemaVer) + throws SentryUserException { + List upgradeScriptList = new ArrayList(); + + // check if we are already at current schema level + if (getSentryVersion().equals(fromSchemaVer)) { + return upgradeScriptList; + } + + // Find the list of scripts to execute for this upgrade + int firstScript = sentrySchemaVersions.length; + for (int i = 0; i < sentrySchemaVersions.length; i++) { + String fromVersion = sentrySchemaVersions[i].split("-to-")[0]; + if (fromVersion.equals(fromSchemaVer)) { + firstScript = i; + break; + } + } + if (firstScript == sentrySchemaVersions.length) { + throw new SentryUserException("Unknown version specified for upgrade " + + fromSchemaVer + " Metastore schema may be too old or newer"); + } + + for (int i = firstScript; i < sentrySchemaVersions.length; i++) { + String scriptFile = generateUpgradeFileName(sentrySchemaVersions[i]); + upgradeScriptList.add(scriptFile); + } + return upgradeScriptList; + } + + /*** + * Get the name of the script to initialize the schema for given version + * + * @param toVersion + * Target version. If it's null, then the current server version is + * used + * @return + * @throws SentryUserException + */ + public String generateInitFileName(String toVersion) + throws SentryUserException { + String version = toVersion; + if (version == null) { + version = getSentryVersion(); + } + String initScriptName = INIT_FILE_PREFIX + dbType + "-" + version + + SQL_FILE_EXTENSION; + // check if the file exists + if (!(new File(getSentryStoreScriptDir() + File.separatorChar + + initScriptName).exists())) { + throw new SentryUserException( + "Unknown version specified for initialization: " + version); + } + return initScriptName; + } + + /** + * Find the directory of sentry store scripts + * + * @return + */ + public String getSentryStoreScriptDir() { + return sentryScriptDir; + } + + // format the upgrade script name eg upgrade-x-y-dbType.sql + private String generateUpgradeFileName(String fileVersion) { + return INIT_FILE_PREFIX + UPGRADE_FILE_PREFIX + dbType + "-" + + fileVersion + SQL_FILE_EXTENSION; + } + + // Current hive version, in majorVersion.minorVersion.changeVersion format + // TODO: store the version using the build script + public static String getSentryVersion() { + return SENTRY_VERSION; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceRegister.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceRegister.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceRegister.java new file mode 100644 index 0000000..79dfe48 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/ServiceRegister.java @@ -0,0 +1,52 @@ +/** + * 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.sentry.provider.db.service.persistent; + +import org.apache.curator.x.discovery.ServiceDiscoveryBuilder; +import org.apache.curator.x.discovery.ServiceInstance; +import org.apache.curator.x.discovery.details.InstanceSerializer; + +public class ServiceRegister { + + private HAContext haContext; + + public ServiceRegister(HAContext haContext) { + this.haContext = haContext; + } + + public void regService(String host, int port) throws Exception { + + haContext.startCuratorFramework(); + ServiceInstance serviceInstance = ServiceInstance.builder() + .address(host) + .port(port) + .name(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) + .build(); + + InstanceSerializer instanceSerializer = new FixedJsonInstanceSerializer(Void.class); + ServiceDiscoveryBuilder.builder(Void.class) + .basePath(HAContext.SENTRY_SERVICE_REGISTER_NAMESPACE) + .client(haContext.getCuratorFramework()) + .serializer(instanceSerializer) + .thisInstance(serviceInstance) + .build() + .start(); + } + +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/ConfServlet.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/ConfServlet.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/ConfServlet.java new file mode 100644 index 0000000..9e7fca8 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/ConfServlet.java @@ -0,0 +1,69 @@ +package org.apache.sentry.provider.db.service.thrift; + +/** + * 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. + */ + +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.hadoop.conf.Configuration; + +/** + * Servlet to print out all sentry configuration. + */ +public class ConfServlet extends HttpServlet { + public static final String CONF_CONTEXT_ATTRIBUTE = "sentry.conf"; + public static final String FORMAT_JSON = "json"; + public static final String FORMAT_XML = "xml"; + public static final String FORMAT_PARAM = "format"; + private static final long serialVersionUID = 1L; + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String format = request.getParameter(FORMAT_PARAM); + if (format == null) { + format = FORMAT_XML; + } + + if (FORMAT_XML.equals(format)) { + response.setContentType("text/xml; charset=utf-8"); + } else if (FORMAT_JSON.equals(format)) { + response.setContentType("application/json; charset=utf-8"); + } + + Configuration conf = (Configuration)getServletContext().getAttribute( + CONF_CONTEXT_ATTRIBUTE); + assert conf != null; + + Writer out = response.getWriter(); + if (FORMAT_JSON.equals(format)) { + Configuration.dumpConfiguration(conf, out); + } else if (FORMAT_XML.equals(format)) { + conf.writeXml(out); + } else { + response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Bad format: " + format); + } + out.close(); + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java new file mode 100644 index 0000000..b1a4b7f --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java @@ -0,0 +1,79 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.provider.db.service.persistent.CommitContext; + +/** + * Users wishing to be notified when a metadata changing event occurs + * should extend this abstract class. All methods which modify the underlying + * metadata in SentryPolicyStoreProcessor will have a corresponding method + * on this class. Each method will contain a copy of the request and response + * object. Therefore any change to the request or response object will be ignored. + * Additionally each method will be passed a CommitContext. + * + * Sub-classes should be thread-safe. + */ +public abstract class NotificationHandler { + + private final Configuration config; + + public NotificationHandler(Configuration config) throws Exception { + this.config = config; + } + + protected Configuration getConf() { + return config; + } + + public void create_sentry_role(CommitContext context, + TCreateSentryRoleRequest request, TCreateSentryRoleResponse response) { + } + + public void drop_sentry_role(CommitContext context, TDropSentryRoleRequest request, + TDropSentryRoleResponse response) { + } + + public void alter_sentry_role_grant_privilege(CommitContext context, TAlterSentryRoleGrantPrivilegeRequest request, + TAlterSentryRoleGrantPrivilegeResponse response) { + } + + public void alter_sentry_role_revoke_privilege(CommitContext context, TAlterSentryRoleRevokePrivilegeRequest request, + TAlterSentryRoleRevokePrivilegeResponse response) { + } + + public void alter_sentry_role_add_groups(CommitContext context, + TAlterSentryRoleAddGroupsRequest request, + TAlterSentryRoleAddGroupsResponse response) { + } + + public void alter_sentry_role_delete_groups( + CommitContext context, TAlterSentryRoleDeleteGroupsRequest request, + TAlterSentryRoleDeleteGroupsResponse response) { + } + + public void alter_sentry_role_add_users(CommitContext context, + TAlterSentryRoleAddUsersRequest request, TAlterSentryRoleAddUsersResponse response) { + } + + public void alter_sentry_role_delete_users(CommitContext context, + TAlterSentryRoleDeleteUsersRequest request, TAlterSentryRoleDeleteUsersResponse response) { + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java new file mode 100644 index 0000000..856ef9a --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java @@ -0,0 +1,176 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import java.util.List; + +import org.apache.hadoop.conf.Configuration; +import org.apache.sentry.provider.db.service.persistent.CommitContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; + +/** + * Invokes configured instances of NotificationHandler. Importantly + * NotificationHandler's each receive a copy of the request and + * response thrift objects from each successful request. + */ +public class NotificationHandlerInvoker extends NotificationHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(NotificationHandlerInvoker.class); + + private final ImmutableList handlers; + + public NotificationHandlerInvoker(Configuration conf, NotificationHandler handler) + throws Exception { + this(conf, ImmutableList.of(handler)); + } + + public NotificationHandlerInvoker(Configuration conf, List handlers) + throws Exception { + super(conf); + this.handlers = ImmutableList.copyOf(handlers); + } + + @Override + public void create_sentry_role(CommitContext context, + TCreateSentryRoleRequest request, TCreateSentryRoleResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.create_sentry_role(context, new TCreateSentryRoleRequest(request), + new TCreateSentryRoleResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void drop_sentry_role(CommitContext context, TDropSentryRoleRequest request, + TDropSentryRoleResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.drop_sentry_role(context, new TDropSentryRoleRequest(request), + new TDropSentryRoleResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void alter_sentry_role_grant_privilege(CommitContext context, + TAlterSentryRoleGrantPrivilegeRequest request, + TAlterSentryRoleGrantPrivilegeResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_grant_privilege(context, + new TAlterSentryRoleGrantPrivilegeRequest(request), + new TAlterSentryRoleGrantPrivilegeResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void alter_sentry_role_revoke_privilege(CommitContext context, + TAlterSentryRoleRevokePrivilegeRequest request, + TAlterSentryRoleRevokePrivilegeResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_revoke_privilege(context, + new TAlterSentryRoleRevokePrivilegeRequest(request), + new TAlterSentryRoleRevokePrivilegeResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void alter_sentry_role_add_groups(CommitContext context, + TAlterSentryRoleAddGroupsRequest request, + TAlterSentryRoleAddGroupsResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_add_groups(context, new TAlterSentryRoleAddGroupsRequest(request), + new TAlterSentryRoleAddGroupsResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void alter_sentry_role_delete_groups( + CommitContext context, TAlterSentryRoleDeleteGroupsRequest request, + TAlterSentryRoleDeleteGroupsResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_delete_groups(context, new TAlterSentryRoleDeleteGroupsRequest(request), + new TAlterSentryRoleDeleteGroupsResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + + request + ", Response: " + response, ex); + } + } + } + + @Override + public void alter_sentry_role_add_users(CommitContext context, + TAlterSentryRoleAddUsersRequest request, TAlterSentryRoleAddUsersResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_add_users(context, new TAlterSentryRoleAddUsersRequest(request), + new TAlterSentryRoleAddUsersResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + request + ", Response: " + + response, ex); + } + } + } + + @Override + public void alter_sentry_role_delete_users(CommitContext context, + TAlterSentryRoleDeleteUsersRequest request, TAlterSentryRoleDeleteUsersResponse response) { + for (NotificationHandler handler : handlers) { + try { + LOGGER.debug("Calling " + handler); + handler.alter_sentry_role_delete_users(context, new TAlterSentryRoleDeleteUsersRequest( + request), new TAlterSentryRoleDeleteUsersResponse(response)); + } catch (Exception ex) { + LOGGER.error("Unexpected error in " + handler + ". Request: " + request + ", Response: " + + response, ex); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java new file mode 100644 index 0000000..8cf1c1a --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java @@ -0,0 +1,32 @@ +/** + * 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.sentry.provider.db.service.thrift; + +public final class PolicyStoreConstants { + public static final String SENTRY_GENERIC_POLICY_NOTIFICATION = "sentry.generic.policy.notification"; + public static final String SENTRY_GENERIC_POLICY_STORE = "sentry.generic.policy.store"; + public static final String SENTRY_GENERIC_POLICY_STORE_DEFAULT = + "org.apache.sentry.provider.db.generic.service.persistent.DelegateSentryStore"; + public static class PolicyStoreServerConfig { + public static final String NOTIFICATION_HANDLERS = "sentry.policy.store.notification.handlers"; + } + + private PolicyStoreConstants() { + // Make constructor private to avoid instantiation + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryAuthFilter.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryAuthFilter.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryAuthFilter.java new file mode 100644 index 0000000..c1cfc1b --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryAuthFilter.java @@ -0,0 +1,92 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Properties; +import java.util.Set; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.hadoop.security.authentication.server.AuthenticationFilter; +import org.apache.hadoop.util.StringUtils; +import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; + +/** + * SentryAuthFilter is a subclass of AuthenticationFilter, + * add authorization: Only allowed users could connect the web server. + */ +public class SentryAuthFilter extends AuthenticationFilter { + + private static final Logger LOG = LoggerFactory.getLogger(SentryAuthFilter.class); + + public static final String ALLOW_WEB_CONNECT_USERS = ServerConfig.SENTRY_WEB_SECURITY_ALLOW_CONNECT_USERS; + + private Set allowUsers; + + @Override + protected void doFilter(FilterChain filterChain, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + String userName = request.getRemoteUser(); + LOG.debug("Authenticating user: " + userName + " from request."); + if (!allowUsers.contains(userName)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, + "Unauthorized user status code: " + HttpServletResponse.SC_FORBIDDEN); + throw new ServletException(userName + " is unauthorized. status code: " + HttpServletResponse.SC_FORBIDDEN); + } + super.doFilter(filterChain, request, response); + } + + /** + * Override getConfiguration to get ALLOW_WEB_CONNECT_USERS. + */ + @Override + protected Properties getConfiguration(String configPrefix, FilterConfig filterConfig) throws ServletException { + Properties props = new Properties(); + Enumeration names = filterConfig.getInitParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + if (name.startsWith(configPrefix)) { + String value = filterConfig.getInitParameter(name); + if (ALLOW_WEB_CONNECT_USERS.equals(name)) { + allowUsers = parseConnectUsersFromConf(value); + } else { + props.put(name.substring(configPrefix.length()), value); + } + } + } + return props; + } + + private static Set parseConnectUsersFromConf(String value) { + String lcValue = value; + if (lcValue != null) { + lcValue = lcValue.toLowerCase(); + } + return Sets.newHashSet(StringUtils.getStrings(lcValue)); + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java new file mode 100644 index 0000000..8822c2e --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryHealthCheckServletContextListener.java @@ -0,0 +1,35 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import com.codahale.metrics.health.HealthCheckRegistry; +import com.codahale.metrics.servlets.HealthCheckServlet; + +/** + * Use this class's registry to register health checks: Can be some tests which make sure Sentry service is healthy + */ +public class SentryHealthCheckServletContextListener extends HealthCheckServlet.ContextListener { + + //This is just a place holder for health check registry, with out this AdminServlet throws out an error + public static final HealthCheckRegistry HEALTH_CHECK_REGISTRY = new HealthCheckRegistry(); + + @Override + protected HealthCheckRegistry getHealthCheckRegistry() { + return HEALTH_CHECK_REGISTRY; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java new file mode 100644 index 0000000..c6d4d02 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetrics.java @@ -0,0 +1,162 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import com.codahale.metrics.ConsoleReporter; +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Histogram; +import com.codahale.metrics.JmxReporter; +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.MetricSet; +import com.codahale.metrics.Timer; +import com.codahale.metrics.jvm.BufferPoolMetricSet; +import com.codahale.metrics.jvm.GarbageCollectorMetricSet; +import com.codahale.metrics.jvm.MemoryUsageGaugeSet; +import com.codahale.metrics.jvm.ThreadStatesGaugeSet; +import org.apache.sentry.provider.db.service.persistent.SentryStore; + +import java.lang.management.ManagementFactory; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * A singleton class which holds metrics related utility functions as well as the list of metrics + */ +public final class SentryMetrics { + private static SentryMetrics sentryMetrics = null; + private boolean reportingInitialized = false; + private boolean gaugesAdded = false; + + public final Timer createRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "create-role")); + public final Timer dropRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "drop-role")); + public final Timer grantRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "grant-role")); + public final Timer revokeRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "revoke-role")); + public final Timer grantTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "grant-privilege")); + public final Timer revokeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "revoke-privilege")); + + public final Timer dropPrivilegeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "drop-privilege")); + public final Timer renamePrivilegeTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "rename-privilege")); + + public final Timer listRolesByGroupTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-roles-by-group")); + public final Timer listPrivilegesByRoleTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-by-role")); + public final Timer listPrivilegesForProviderTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-for-provider")); + public final Timer listPrivilegesByAuthorizableTimer = SentryMetricsServletContextListener.METRIC_REGISTRY.timer( + MetricRegistry.name(SentryPolicyStoreProcessor.class, "list-privileges-by-authorizable")); + + /** + * Return a Timer with name. + */ + public Timer getTimer(String name) { + return SentryMetricsServletContextListener.METRIC_REGISTRY.timer(name); + } + + /** + * Return a Histogram with name. + */ + public Histogram getHistogram(String name) { + return SentryMetricsServletContextListener.METRIC_REGISTRY.histogram(name); + } + + /** + * Return a Counter with name. + */ + public Counter getCounter(String name) { + return SentryMetricsServletContextListener.METRIC_REGISTRY.counter(name); + } + + private SentryMetrics() { + registerMetricSet("gc", new GarbageCollectorMetricSet(), SentryMetricsServletContextListener.METRIC_REGISTRY); + registerMetricSet("buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()), + SentryMetricsServletContextListener.METRIC_REGISTRY); + registerMetricSet("memory", new MemoryUsageGaugeSet(), SentryMetricsServletContextListener.METRIC_REGISTRY); + registerMetricSet("threads", new ThreadStatesGaugeSet(), SentryMetricsServletContextListener.METRIC_REGISTRY); + } + + public static synchronized SentryMetrics getInstance() { + if (sentryMetrics == null) { + sentryMetrics = new SentryMetrics(); + } + return sentryMetrics; + } + + public void addSentryStoreGauges(SentryStore sentryStore) { + if(!gaugesAdded) { + addGauge(SentryStore.class, "role_count", sentryStore.getRoleCountGauge()); + addGauge(SentryStore.class, "privilege_count", sentryStore.getPrivilegeCountGauge()); + addGauge(SentryStore.class, "group_count", sentryStore.getGroupCountGauge()); + gaugesAdded = true; + } + } + + + /* Should be only called once to initialize the reporters + */ + public synchronized void initReporting(Reporting reporting) { + if(!reportingInitialized) { + switch(reporting) { + case CONSOLE: + final ConsoleReporter consoleReporter = ConsoleReporter.forRegistry(SentryMetricsServletContextListener.METRIC_REGISTRY) + .convertRatesTo(TimeUnit.SECONDS) + .convertDurationsTo(TimeUnit.MILLISECONDS) + .build(); + consoleReporter.start(1, TimeUnit.SECONDS); + break; + case JMX: + final JmxReporter jmxReporter = JmxReporter.forRegistry(SentryMetricsServletContextListener.METRIC_REGISTRY) + .convertRatesTo(TimeUnit.SECONDS) + .convertDurationsTo(TimeUnit.MILLISECONDS) + .build(); + jmxReporter.start(); + break; + } + } + } + + private void addGauge(Class tClass, String gaugeName, Gauge gauge) { + SentryMetricsServletContextListener.METRIC_REGISTRY.register( + MetricRegistry.name(tClass, gaugeName), gauge); + } + + private void registerMetricSet(String prefix, MetricSet metricSet, MetricRegistry registry) { + for (Map.Entry entry : metricSet.getMetrics().entrySet()) { + if (entry.getValue() instanceof MetricSet) { + registerMetricSet(prefix + "." + entry.getKey(), (MetricSet) entry.getValue(), registry); + } else { + registry.register(prefix + "." + entry.getKey(), entry.getValue()); + } + } + } + + public enum Reporting { + JMX, + CONSOLE; + } +} http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java new file mode 100644 index 0000000..6692197 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryMetricsServletContextListener.java @@ -0,0 +1,32 @@ +/** + * 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.sentry.provider.db.service.thrift; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.servlets.MetricsServlet; + +public class SentryMetricsServletContextListener extends MetricsServlet.ContextListener { + + public static final MetricRegistry METRIC_REGISTRY = new MetricRegistry(); + + @Override + protected MetricRegistry getMetricRegistry() { + return METRIC_REGISTRY; + } + +}