Java tutorial
/* * 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.binding.hive.authz; import java.lang.reflect.Constructor; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeys; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; import org.apache.hadoop.hive.ql.metadata.AuthorizationException; import org.apache.hadoop.hive.ql.plan.HiveOperation; import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.sentry.binding.hive.conf.HiveAuthzConf; import org.apache.sentry.binding.hive.conf.HiveAuthzConf.AuthzConfVars; import org.apache.sentry.core.Action; import org.apache.sentry.core.Authorizable; import org.apache.sentry.core.AuthorizationProvider; import org.apache.sentry.core.NoAuthorizationProvider; import org.apache.sentry.core.Server; import org.apache.sentry.core.Subject; import org.apache.sentry.core.Authorizable.AuthorizableType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; public class HiveAuthzBinding { private static final Logger LOG = LoggerFactory.getLogger(HiveAuthzBinding.class); private static final Map<String, HiveAuthzBinding> authzBindingMap = new ConcurrentHashMap<String, HiveAuthzBinding>(); private static final AtomicInteger queryID = new AtomicInteger(); public static final String HIVE_BINDING_TAG = "hive.authz.bindings.tag"; private final HiveAuthzConf authzConf; private final Server authServer; private final AuthorizationProvider authProvider; public HiveAuthzBinding(HiveConf hiveConf, HiveAuthzConf authzConf) throws Exception { this.authzConf = authzConf; this.authServer = new Server(authzConf.get(AuthzConfVars.AUTHZ_SERVER_NAME.getVar())); this.authProvider = getAuthProvider(hiveConf, authServer.getName()); } /** * Retrieve the HiveAuthzBinding if the tag is saved in the given configuration * @param conf * @return HiveAuthzBinding or null */ public static HiveAuthzBinding get(Configuration conf) { String tagName = conf.get(HIVE_BINDING_TAG); if (tagName == null) { return null; } else { return authzBindingMap.get(tagName); } } /** * store the HiveAuthzBinding in the authzBindingMap and save a tag in the given configuration * @param conf */ public void set(Configuration conf) { String tagName = SessionState.get().getSessionId() + "_" + queryID.incrementAndGet(); authzBindingMap.put(tagName, this); conf.set(HIVE_BINDING_TAG, tagName); } /** * remove the authzBindingMap entry for given tag * @param conf */ public void clear(Configuration conf) { String tagName = conf.get(HIVE_BINDING_TAG); if (tagName == null) { authzBindingMap.remove(tagName); } } // Instantiate the configured authz provider private AuthorizationProvider getAuthProvider(HiveConf hiveConf, String serverName) throws Exception { boolean isTestingMode = Boolean.parseBoolean( Strings.nullToEmpty(authzConf.get(AuthzConfVars.ACCESS_TESTING_MODE.getVar())).trim()); LOG.debug("Testing mode is " + isTestingMode); if (!isTestingMode) { String authMethod = Strings.nullToEmpty(hiveConf.getVar(ConfVars.HIVE_SERVER2_AUTHENTICATION)).trim(); if ("none".equalsIgnoreCase(authMethod)) { LOG.error("HiveServer2 authentication method cannot be set to none unless testing mode is enabled"); return new NoAuthorizationProvider(); } boolean impersonation = hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_KERBEROS_IMPERSONATION); boolean allowImpersonation = Boolean.parseBoolean(Strings .nullToEmpty(authzConf.get(AuthzConfVars.AUTHZ_ALLOW_HIVE_IMPERSONATION.getVar())).trim()); if (impersonation && !allowImpersonation) { LOG.error("Role based authorization does not work with HiveServer2 impersonation"); return new NoAuthorizationProvider(); } } String defaultUmask = hiveConf.get(CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY); if ("077".equalsIgnoreCase(defaultUmask)) { LOG.error("HiveServer2 required a default umask of 077"); return new NoAuthorizationProvider(); } // get the provider class and resources from the authz config String authProviderName = authzConf.get(AuthzConfVars.AUTHZ_PROVIDER.getVar()); String resourceName = authzConf.get(AuthzConfVars.AUTHZ_PROVIDER_RESOURCE.getVar()); LOG.debug("Using authorization provide " + authProviderName + " with resource " + resourceName); // load the authz provider class Constructor<?> constrctor = Class.forName(authProviderName).getDeclaredConstructor(String.class, String.class); constrctor.setAccessible(true); return (AuthorizationProvider) constrctor.newInstance(new Object[] { resourceName, serverName }); } /** * Validate the privilege for the given operation for the given subject * @param hiveOp * @param stmtAuthPrivileges * @param subject * @param currDB * @param inputEntities * @param outputEntities * @throws AuthorizationException */ public void authorize(HiveOperation hiveOp, HiveAuthzPrivileges stmtAuthPrivileges, Subject subject, List<List<Authorizable>> inputHierarchyList, List<List<Authorizable>> outputHierarchyList) throws AuthorizationException { boolean isDebug = LOG.isDebugEnabled(); if (isDebug) { LOG.debug("Going to authorize statement " + hiveOp.name() + " for subject " + subject.getName()); } /* for each read and write entity captured by the compiler - * check if that object type is part of the input/output privilege list * If it is, then validate the access. * Note the hive compiler gathers information on additional entities like partitions, * etc which are not of our interest at this point. Hence its very * much possible that the we won't be validating all the entities in the given list */ // Check read entities Map<AuthorizableType, EnumSet<Action>> requiredInputPrivileges = stmtAuthPrivileges.getInputPrivileges(); for (List<Authorizable> inputHierarchy : inputHierarchyList) { if (isDebug) { LOG.debug("requiredInputPrivileges = " + requiredInputPrivileges); LOG.debug("inputHierarchy = " + inputHierarchy); LOG.debug("getAuthzType(inputHierarchy) = " + getAuthzType(inputHierarchy)); } if (requiredInputPrivileges.containsKey(getAuthzType(inputHierarchy))) { EnumSet<Action> inputPrivSet = requiredInputPrivileges.get(getAuthzType(inputHierarchy)); if (!authProvider.hasAccess(subject, inputHierarchy, inputPrivSet)) { throw new AuthorizationException( "User " + subject.getName() + " does not have privileges for " + hiveOp.name()); } } } // Check write entities Map<AuthorizableType, EnumSet<Action>> requiredOutputPrivileges = stmtAuthPrivileges.getOutputPrivileges(); for (List<Authorizable> outputHierarchy : outputHierarchyList) { if (isDebug) { LOG.debug("requiredOutputPrivileges = " + requiredOutputPrivileges); LOG.debug("outputHierarchy = " + outputHierarchy); LOG.debug("getAuthzType(outputHierarchy) = " + getAuthzType(outputHierarchy)); } if (requiredOutputPrivileges.containsKey(getAuthzType(outputHierarchy))) { EnumSet<Action> outputPrivSet = requiredOutputPrivileges.get(getAuthzType(outputHierarchy)); if (!authProvider.hasAccess(subject, outputHierarchy, outputPrivSet)) { throw new AuthorizationException( "User " + subject.getName() + " does not have priviliedges for " + hiveOp.name()); } } } } public Server getAuthServer() { return authServer; } private AuthorizableType getAuthzType(List<Authorizable> hierarchy) { return hierarchy.get(hierarchy.size() - 1).getAuthzType(); } }