http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessor.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessor.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessor.java deleted file mode 100644 index 1cc4b1b..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessor.java +++ /dev/null @@ -1,829 +0,0 @@ -/** - * 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.api.generic.thrift; - -import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_JOINER; -import static org.apache.sentry.core.common.utils.SentryConstants.KV_JOINER; - -import java.lang.reflect.Constructor; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.api.common.ThriftConstants; -import org.apache.sentry.core.common.exception.SentryUserException; -import org.apache.sentry.core.common.Authorizable; -import org.apache.sentry.core.common.utils.SentryConstants; -import org.apache.sentry.core.common.exception.SentrySiteConfigurationException; -import org.apache.sentry.core.model.db.AccessConstants; -import org.apache.sentry.core.common.utils.KeyValue; -import org.apache.sentry.provider.common.AuthorizationComponent; -import org.apache.sentry.core.common.exception.SentryAccessDeniedException; -import org.apache.sentry.core.common.exception.SentryAlreadyExistsException; -import org.apache.sentry.core.common.exception.SentryInvalidInputException; -import org.apache.sentry.core.common.exception.SentryNoSuchObjectException; -import org.apache.sentry.core.common.exception.SentryThriftAPIMismatchException; -import org.apache.sentry.provider.db.generic.service.persistent.DelegateSentryStore; -import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject; -import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder; -import org.apache.sentry.provider.db.generic.service.persistent.SentryStoreLayer; -import org.apache.sentry.provider.db.log.entity.JsonLogEntityFactory; -import org.apache.sentry.provider.db.log.util.Constants; -import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege; -import org.apache.sentry.provider.db.service.model.MSentryRole; -import org.apache.sentry.core.common.utils.PolicyStoreConstants; -import org.apache.sentry.api.service.thrift.SentryPolicyStoreProcessor; -import org.apache.sentry.service.common.ServiceConstants.ServerConfig; -import org.apache.sentry.api.common.Status; -import org.apache.sentry.service.thrift.TSentryResponseStatus; -import org.apache.thrift.TException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Splitter; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -public class SentryGenericPolicyProcessor implements SentryGenericPolicyService.Iface { - private static final Logger LOGGER = LoggerFactory.getLogger(SentryGenericPolicyProcessor.class); - private static final Logger AUDIT_LOGGER = LoggerFactory - .getLogger(Constants.AUDIT_LOGGER_NAME_GENERIC); - private final Configuration conf; - private final ImmutableSet<String> adminGroups; - private final SentryStoreLayer store; - private final NotificationHandlerInvoker handerInvoker; - - private static final String ACCESS_DENIAL_MESSAGE = "Access denied to "; - - SentryGenericPolicyProcessor(Configuration conf) throws Exception { - this.store = new DelegateSentryStore(conf); - this.handerInvoker = new NotificationHandlerInvoker(createHandlers(conf)); - this.conf = conf; - adminGroups = ImmutableSet.copyOf((Sets.newHashSet(conf.getStrings( - ServerConfig.ADMIN_GROUPS, new String[]{})))); - } - - @VisibleForTesting - SentryGenericPolicyProcessor(Configuration conf, SentryStoreLayer store) throws Exception { - this.store = store; - this.handerInvoker = new NotificationHandlerInvoker(createHandlers(conf)); - this.conf = conf; - adminGroups = ImmutableSet.copyOf(toTrimmed(Sets.newHashSet(conf.getStrings( - ServerConfig.ADMIN_GROUPS, new String[]{})))); - } - - private void authorize(String requestorUser, Set<String> requestorGroups) - throws SentryAccessDeniedException { - if (!inAdminGroups(requestorGroups)) { - String msg = "User: " + requestorUser + " is part of " + requestorGroups + - " which does not, intersect admin groups " + adminGroups; - LOGGER.warn(msg); - throw new SentryAccessDeniedException(ACCESS_DENIAL_MESSAGE + requestorUser); - } - } - - private Set<String> toTrimmedLower(Set<String> s) { - if (s == null) { - return Collections.emptySet(); - } - Set<String> result = new HashSet<>(s.size()); - for (String v : s) { - result.add(v.trim().toLowerCase()); - } - return result; - } - - private Set<String> toTrimmed(Set<String> s) { - if (s == null) { - return Collections.emptySet(); - } - Set<String> result = new HashSet<>(s.size()); - for (String v : s) { - result.add(v.trim()); - } - return result; - } - - private String toTrimmedLower(String s) { - if (Strings.isNullOrEmpty(s)){ - return ""; - } - return s.trim().toLowerCase(); - } - - private static Set<String> getRequestorGroups(Configuration conf, String userName) throws SentryUserException { - return SentryPolicyStoreProcessor.getGroupsFromUserName(conf, userName); - } - - private boolean inAdminGroups(Set<String> requestorGroups) { - return !Sets.intersection(adminGroups, requestorGroups).isEmpty(); - } - - static List<NotificationHandler> createHandlers(Configuration conf) throws SentrySiteConfigurationException { - - List<NotificationHandler> handlers = Lists.newArrayList(); - Iterable<String> notificationHandlers = Splitter.onPattern("[\\s,]").trimResults() - .omitEmptyStrings().split(conf.get(PolicyStoreConstants.SENTRY_GENERIC_POLICY_NOTIFICATION, "")); - try { - for (String notificationHandler : notificationHandlers) { - handlers.add(createInstance(notificationHandler, conf, NotificationHandler.class)); - } - } catch (Exception e) { - throw new SentrySiteConfigurationException("Create notificationHandlers error: " + e.getMessage(), e); - } - return handlers; - } - - @SuppressWarnings("unchecked") - private static <T> T createInstance(String className, Configuration conf, Class<T> iface) throws Exception { - T result; - try { - Class<?> clazz = Class.forName(className); - if (!iface.isAssignableFrom(clazz)) { - throw new IllegalArgumentException("Class " + clazz + " is not a " + - iface.getName()); - } - Constructor<T> meth = (Constructor<T>)clazz.getDeclaredConstructor(Configuration.class); - meth.setAccessible(true); - result = meth.newInstance(new Object[]{conf}); - } catch (Exception e) { - throw new RuntimeException(e); - } - return result; - } - - private <T> Response<T> requestHandle(RequestHandler<T> handler) { - Response<T> response = new Response<T>(); - try { - response = handler.handle(); - } catch (SentryAccessDeniedException e) { - String msg = "Sentry access denied: " + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.AccessDenied(e.getMessage(), e); - } catch (SentryAlreadyExistsException e) { - String msg = "Sentry object already exists: " + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.AlreadyExists(e.getMessage(), e); - } catch (SentryNoSuchObjectException e) { - String msg = "Sentry object doesn't exist: " + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.NoSuchObject(e.getMessage(), e); - } catch (SentryInvalidInputException e) { - String msg = "Invalid input privilege object: " + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.InvalidInput(msg, e); - } catch (SentryThriftAPIMismatchException e) { - String msg = "Sentry thrift API mismatch error: " + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.THRIFT_VERSION_MISMATCH(e.getMessage(), e); - } catch (Exception e) { - String msg = "Unknown error:" + e.getMessage(); - LOGGER.error(msg, e); - response.status = Status.RuntimeError(msg, e); - } - return response; - } - - private PrivilegeObject toPrivilegeObject(TSentryPrivilege tSentryPrivilege) { - Boolean grantOption; - if (tSentryPrivilege.getGrantOption().equals(TSentryGrantOption.TRUE)) { - grantOption = true; - } else if (tSentryPrivilege.getGrantOption().equals(TSentryGrantOption.FALSE)) { - grantOption = false; - } else { - grantOption = null; - } - return new Builder().setComponent(tSentryPrivilege.getComponent()) - .setService(tSentryPrivilege.getServiceName()) - .setAuthorizables(toAuthorizables(tSentryPrivilege.getAuthorizables())) - .setAction(tSentryPrivilege.getAction()) - .withGrantOption(grantOption) - .build(); - } - - private TSentryPrivilege fromPrivilegeObject(PrivilegeObject privilege) { - - TSentryPrivilege tPrivilege = new TSentryPrivilege(privilege.getComponent(), privilege.getService(), - fromAuthorizable(privilege.getAuthorizables()), - privilege.getAction()); - if (privilege.getGrantOption() == null) { - tPrivilege.setGrantOption(TSentryGrantOption.UNSET); - } else if (privilege.getGrantOption()) { - tPrivilege.setGrantOption(TSentryGrantOption.TRUE); - } else { - tPrivilege.setGrantOption(TSentryGrantOption.FALSE); - } - return tPrivilege; - } - - private List<TAuthorizable> fromAuthorizable(List<? extends Authorizable> authorizables) { - List<TAuthorizable> tAuthorizables = Lists.newArrayList(); - for (Authorizable authorizable : authorizables) { - tAuthorizables.add(new TAuthorizable(authorizable.getTypeName(), authorizable.getName())); - } - return tAuthorizables; - } - - private String fromAuthorizableToStr(List<? extends Authorizable> authorizables) { - if (authorizables != null && !authorizables.isEmpty()) { - List<String> privileges = Lists.newArrayList(); - - for (Authorizable authorizable : authorizables) { - - privileges.add(SentryConstants.KV_JOINER.join(authorizable.getTypeName(), - authorizable.getName())); - } - - return SentryConstants.AUTHORIZABLE_JOINER.join(privileges); - } else { - return ""; - } - } - - private List<? extends Authorizable> toAuthorizables(List<TAuthorizable> tAuthorizables) { - List<Authorizable> authorizables = Lists.newArrayList(); - if (tAuthorizables == null) { - return authorizables; - } - for (final TAuthorizable tAuthorizable : tAuthorizables) { - authorizables.add(new Authorizable() { - @Override - public String getTypeName() { - return tAuthorizable.getType(); - } - @Override - public String getName() { - return tAuthorizable.getName(); - } - }); - } - return authorizables; - } - - private List<? extends Authorizable> toAuthorizables(String privilegeStr) { - List<Authorizable> authorizables = Lists.newArrayList(); - if (privilegeStr == null) { - return authorizables; - } - - for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.split(privilegeStr)) { - KeyValue tempKV = new KeyValue(authorizable); - final String key = tempKV.getKey(); - final String value = tempKV.getValue(); - - authorizables.add(new Authorizable() { - @Override - public String getTypeName() { - return key; - } - - @Override - public String getName() { - return value; - } - }); - } - - return authorizables; - } - - // Construct the role to set of privileges mapping based on the - // MSentryGMPrivilege information. - private TSentryPrivilegeMap toTSentryPrivilegeMap(Set<MSentryGMPrivilege> mPrivileges) { - - // Mapping of <Role, Set<Privilege>>. - Map<String, Set<TSentryPrivilege>> tPrivilegeMap = Maps.newTreeMap(); - - for (MSentryGMPrivilege mPrivilege : mPrivileges) { - for (MSentryRole role : mPrivilege.getRoles()) { - - TSentryPrivilege tPrivilege = toTSentryPrivilege(mPrivilege); - - if (tPrivilegeMap.containsKey(role.getRoleName())) { - tPrivilegeMap.get(role.getRoleName()).add(tPrivilege); - } else { - Set<TSentryPrivilege> tPrivilegeSet = Sets.newTreeSet(); - tPrivilegeSet.add(tPrivilege); - tPrivilegeMap.put(role.getRoleName(), tPrivilegeSet); - } - } - } - - return new TSentryPrivilegeMap(tPrivilegeMap); - } - - // Construct TSentryPrivilege based on MSentryGMPrivilege information. - private TSentryPrivilege toTSentryPrivilege(MSentryGMPrivilege mPrivilege) { - - TSentryPrivilege tPrivilege = new TSentryPrivilege(mPrivilege.getComponentName(), - mPrivilege.getServiceName(), fromAuthorizable(mPrivilege.getAuthorizables()), mPrivilege.getAction()); - - if (mPrivilege.getGrantOption() == null) { - tPrivilege.setGrantOption(TSentryGrantOption.UNSET); - } else if (mPrivilege.getGrantOption()) { - tPrivilege.setGrantOption(TSentryGrantOption.TRUE); - } else { - tPrivilege.setGrantOption(TSentryGrantOption.FALSE); - } - - return tPrivilege; - } - - private Set<String> buildPermissions(Set<PrivilegeObject> privileges) { - Set<String> permissions = Sets.newHashSet(); - for (PrivilegeObject privilege : privileges) { - List<String> hierarchy = Lists.newArrayList(); - if (hasComponentServerPrivilege(privilege.getComponent())) { - hierarchy.add(KV_JOINER.join("server", privilege.getService())); - } - for (Authorizable authorizable : privilege.getAuthorizables()) { - hierarchy.add(KV_JOINER.join(authorizable.getTypeName(),authorizable.getName())); - } - hierarchy.add(KV_JOINER.join("action", privilege.getAction())); - permissions.add(AUTHORIZABLE_JOINER.join(hierarchy)); - } - return permissions; - } - - private boolean hasComponentServerPrivilege(String component) { - //judge the component whether has the server privilege, for example: sqoop has the privilege on the server - return AuthorizationComponent.SQOOP.equalsIgnoreCase(component); - } - - @Override - public TCreateSentryRoleResponse create_sentry_role( - final TCreateSentryRoleRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.createRole(request.getComponent(), request.getRoleName(), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TCreateSentryRoleResponse tResponse = new TCreateSentryRoleResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.create_sentry_role(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for create role: " + e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TDropSentryRoleResponse drop_sentry_role(final TDropSentryRoleRequest request) - throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.dropRole(request.getComponent(), request.getRoleName(), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TDropSentryRoleResponse tResponse = new TDropSentryRoleResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.drop_sentry_role(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for drop role: " + e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TAlterSentryRoleGrantPrivilegeResponse alter_sentry_role_grant_privilege( - final TAlterSentryRoleGrantPrivilegeRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - store.alterRoleGrantPrivilege(request.getComponent(), - request.getRoleName(), - toPrivilegeObject(request.getPrivilege()), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TAlterSentryRoleGrantPrivilegeResponse tResponse = new TAlterSentryRoleGrantPrivilegeResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.alter_sentry_role_grant_privilege(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for grant privilege to role: " + e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TAlterSentryRoleRevokePrivilegeResponse alter_sentry_role_revoke_privilege( - final TAlterSentryRoleRevokePrivilegeRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - store.alterRoleRevokePrivilege(request.getComponent(), - request.getRoleName(), - toPrivilegeObject(request.getPrivilege()), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TAlterSentryRoleRevokePrivilegeResponse tResponse = - new TAlterSentryRoleRevokePrivilegeResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.alter_sentry_role_revoke_privilege(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for revoke privilege from role: " + e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TAlterSentryRoleAddGroupsResponse alter_sentry_role_add_groups( - final TAlterSentryRoleAddGroupsRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.alterRoleAddGroups(request.getComponent(), - request.getRoleName(), - request.getGroups(), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TAlterSentryRoleAddGroupsResponse tResponse = - new TAlterSentryRoleAddGroupsResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.alter_sentry_role_add_groups(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for add role to group: " + e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TAlterSentryRoleDeleteGroupsResponse alter_sentry_role_delete_groups( - final TAlterSentryRoleDeleteGroupsRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.alterRoleDeleteGroups(request.getComponent(), - request.getRoleName(), - request.getGroups(), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TAlterSentryRoleDeleteGroupsResponse tResponse = - new TAlterSentryRoleDeleteGroupsResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.alter_sentry_role_delete_groups(request, tResponse); - } - - try { - AUDIT_LOGGER.info(JsonLogEntityFactory.getInstance() - .createJsonLogEntity(request, tResponse, conf).toJsonFormatLog()); - } catch (Exception e) { - // if any exception, log the exception. - String msg = "Error in creating audit log for delete role from group: " + - e.getMessage(); - LOGGER.error(msg, e); - } - return tResponse; - } - - @Override - public TListSentryRolesResponse list_sentry_roles_by_group( - final TListSentryRolesRequest request) throws TException { - Response<Set<TSentryRole>> respose = requestHandle(new RequestHandler<Set<TSentryRole>>() { - @Override - public Response<Set<TSentryRole>> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - Set<String> groups = getRequestorGroups(conf, request.getRequestorUserName()); - if (!AccessConstants.ALL.equalsIgnoreCase(request.getGroupName())) { - boolean admin = inAdminGroups(groups); - //Only admin users can list all roles in the system ( groupname = null) - //Non admin users are only allowed to list only groups which they belong to - if(!admin && (request.getGroupName() == null || !groups.contains(request.getGroupName()))) { - throw new SentryAccessDeniedException(ACCESS_DENIAL_MESSAGE + request.getRequestorUserName()); - } - groups.clear(); - groups.add(request.getGroupName()); - } - - Set<String> roleNames = store.getRolesByGroups(request.getComponent(), groups); - Set<TSentryRole> tSentryRoles = Sets.newHashSet(); - for (String roleName : roleNames) { - Set<String> groupsForRoleName = store.getGroupsByRoles(request.getComponent(), Sets.newHashSet(roleName)); - tSentryRoles.add(new TSentryRole(roleName, groupsForRoleName)); - } - return new Response<Set<TSentryRole>>(Status.OK(), tSentryRoles); - } - }); - TListSentryRolesResponse tResponse = new TListSentryRolesResponse(); - tResponse.setStatus(respose.status); - tResponse.setRoles(respose.content); - return tResponse; - } - - @Override - public TListSentryPrivilegesResponse list_sentry_privileges_by_role( - final TListSentryPrivilegesRequest request) throws TException { - Response<Set<TSentryPrivilege>> respose = requestHandle(new RequestHandler<Set<TSentryPrivilege>>() { - @Override - public Response<Set<TSentryPrivilege>> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - Set<String> groups = getRequestorGroups(conf, request.getRequestorUserName()); - if (!inAdminGroups(groups)) { - Set<String> roleNamesForGroups = toTrimmedLower(store.getRolesByGroups(request.getComponent(), groups)); - if (!roleNamesForGroups.contains(toTrimmedLower(request.getRoleName()))) { - throw new SentryAccessDeniedException(ACCESS_DENIAL_MESSAGE + request.getRequestorUserName()); - } - } - Set<PrivilegeObject> privileges = store.getPrivilegesByProvider(request.getComponent(), - request.getServiceName(), - Sets.newHashSet(request.getRoleName()), - null, toAuthorizables(request.getAuthorizables())); - Set<TSentryPrivilege> tSentryPrivileges = Sets.newHashSet(); - for (PrivilegeObject privilege : privileges) { - tSentryPrivileges.add(fromPrivilegeObject(privilege)); - } - return new Response<Set<TSentryPrivilege>>(Status.OK(), tSentryPrivileges); - } - }); - TListSentryPrivilegesResponse tResponse = new TListSentryPrivilegesResponse(); - tResponse.setStatus(respose.status); - tResponse.setPrivileges(respose.content); - return tResponse; - } - - @Override - public TListSentryPrivilegesForProviderResponse list_sentry_privileges_for_provider( - final TListSentryPrivilegesForProviderRequest request) throws TException { - Response<Set<String>> respose = requestHandle(new RequestHandler<Set<String>>() { - @Override - public Response<Set<String>> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - Set<String> activeRoleNames = toTrimmedLower(request.getRoleSet().getRoles()); - Set<String> roleNamesForGroups = store.getRolesByGroups(request.getComponent(), request.getGroups()); - Set<String> rolesToQuery = request.getRoleSet().isAll() ? roleNamesForGroups : Sets.intersection(activeRoleNames, roleNamesForGroups); - Set<PrivilegeObject> privileges = store.getPrivilegesByProvider(request.getComponent(), - request.getServiceName(), - rolesToQuery, null, - toAuthorizables(request.getAuthorizables())); - return new Response<Set<String>>(Status.OK(), buildPermissions(privileges)); - } - }); - TListSentryPrivilegesForProviderResponse tResponse = new TListSentryPrivilegesForProviderResponse(); - tResponse.setStatus(respose.status); - tResponse.setPrivileges(respose.content); - return tResponse; - } - - @Override - public TListSentryPrivilegesByAuthResponse list_sentry_privileges_by_authorizable(TListSentryPrivilegesByAuthRequest request) throws TException { - - TListSentryPrivilegesByAuthResponse response = new TListSentryPrivilegesByAuthResponse(); - Map<String, TSentryPrivilegeMap> authRoleMap = Maps.newHashMap(); - - // Group names are case sensitive. - Set<String> requestedGroups = request.getGroups(); - String subject = request.getRequestorUserName(); - TSentryActiveRoleSet activeRoleSet = request.getRoleSet(); - Set<String> validActiveRoles = Sets.newHashSet(); - - try { - validateClientVersion(request.getProtocol_version()); - Set<String> memberGroups = getRequestorGroups(conf, subject); - - // Disallow non-admin users to lookup groups that - // they are not part of. - if(!inAdminGroups(memberGroups)) { - - if (requestedGroups != null && !requestedGroups.isEmpty()) { - for (String requestedGroup : requestedGroups) { - - // If user doesn't belong to one of the requested groups, - // then raise security exception. - if (!memberGroups.contains(requestedGroup)) { - throw new SentryAccessDeniedException(ACCESS_DENIAL_MESSAGE + subject); - } - } - } else { - // Non-admin's search is limited to its own groups. - requestedGroups = memberGroups; - } - - Set<String> grantedRoles = toTrimmedLower(store.getRolesByGroups(request.getComponent(), requestedGroups)); - - // If activeRoleSet is not null, disallow non-admin to lookup roles that they are not part of. - if (activeRoleSet != null && !activeRoleSet.isAll()) { - - Set<String> activeRoleNames = toTrimmedLower(activeRoleSet.getRoles()); - for (String activeRole : activeRoleNames) { - if (!grantedRoles.contains(activeRole)) { - throw new SentryAccessDeniedException(ACCESS_DENIAL_MESSAGE - + subject); - } - } - - // For non-admin, valid active roles are intersection of active roles and granted roles. - validActiveRoles.addAll(activeRoleSet.isAll() ? grantedRoles : Sets.intersection(activeRoleNames, grantedRoles)); - } else { - // For non-admin, if activeRoleSet is null, valid active roles would be the granted roles. - validActiveRoles.addAll(grantedRoles); - } - } else { - // For admin, if requestedGroups are empty, requested roles will be all roles. - Set<String> requestedRoles = toTrimmedLower(store.getAllRoleNames()); - if (requestedGroups != null && !requestedGroups.isEmpty()) { - requestedRoles = toTrimmedLower(store.getRolesByGroups(request.getComponent(), requestedGroups)); - } - - // If activeRoleSet (which is optional) is not null, valid active role will be intersection - // of active roles and requested roles. Otherwise, valid active roles are the requested roles. - if (activeRoleSet != null && !activeRoleSet.isAll()) { - validActiveRoles.addAll(Sets.intersection(toTrimmedLower(activeRoleSet.getRoles()), requestedRoles)); - } else { - validActiveRoles.addAll(requestedRoles); - } - } - - // If user is not part of any group.. return empty response - if (request.getAuthorizablesSet() != null) { - for (String authorizablesStr : request.getAuthorizablesSet()) { - - List<? extends Authorizable> authorizables = toAuthorizables(authorizablesStr); - Set<MSentryGMPrivilege> sentryPrivileges = store.getPrivilegesByAuthorizable(request.getComponent(), request.getServiceName(), validActiveRoles, authorizables); - authRoleMap.put(fromAuthorizableToStr(authorizables), toTSentryPrivilegeMap(sentryPrivileges)); - } - } - - response.setPrivilegesMapByAuth(authRoleMap); - response.setStatus(Status.OK()); - } catch (SentryAccessDeniedException e) { - LOGGER.error(e.getMessage(), e); - response.setStatus(Status.AccessDenied(e.getMessage(), e)); - } catch (SentryThriftAPIMismatchException e) { - LOGGER.error(e.getMessage(), e); - response.setStatus(Status.THRIFT_VERSION_MISMATCH(e.getMessage(), e)); - } catch (Exception e) { - String msg = "Unknown error for request: " + request + ", message: " - + e.getMessage(); - LOGGER.error(msg, e); - response.setStatus(Status.RuntimeError(msg, e)); - } - - return response; - } - - @Override - public TDropPrivilegesResponse drop_sentry_privilege( - final TDropPrivilegesRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.dropPrivilege(request.getComponent(), - toPrivilegeObject(request.getPrivilege()), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TDropPrivilegesResponse tResponse = new TDropPrivilegesResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.drop_sentry_privilege(request, tResponse); - } - return tResponse; - } - - @Override - public TRenamePrivilegesResponse rename_sentry_privilege( - final TRenamePrivilegesRequest request) throws TException { - Response<Void> respose = requestHandle(new RequestHandler<Void>() { - @Override - public Response<Void> handle() throws Exception { - validateClientVersion(request.getProtocol_version()); - authorize(request.getRequestorUserName(), - getRequestorGroups(conf, request.getRequestorUserName())); - store.renamePrivilege(request.getComponent(), request.getServiceName(), - toAuthorizables(request.getOldAuthorizables()), - toAuthorizables(request.getNewAuthorizables()), - request.getRequestorUserName()); - return new Response<Void>(Status.OK()); - } - }); - - TRenamePrivilegesResponse tResponse = new TRenamePrivilegesResponse(respose.status); - if (Status.OK.getCode() == respose.status.getValue()) { - handerInvoker.rename_sentry_privilege(request, tResponse); - } - return tResponse; - } - - private static class Response<T> { - private TSentryResponseStatus status; - private T content; - - Response() { - } - - Response(TSentryResponseStatus status) { - this(status, null); - } - - Response(TSentryResponseStatus status, T content) { - this.status = status; - this.content = content; - } - } - private interface RequestHandler <T>{ - Response<T> handle() throws Exception ; - } - - private static void validateClientVersion(int protocolVersion) throws SentryThriftAPIMismatchException { - if (ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT != protocolVersion) { - String msg = "Sentry thrift API protocol version mismatch: Client thrift version " + - "is: " + protocolVersion + " , server thrift version " + - "is " + ThriftConstants.TSENTRY_SERVICE_VERSION_CURRENT; - throw new SentryThriftAPIMismatchException(msg); - } - } -}
http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessorFactory.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessorFactory.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessorFactory.java deleted file mode 100644 index 311b020..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/generic/thrift/SentryGenericPolicyProcessorFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 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.api.generic.thrift; - -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.api.common.ApiConstants.SentryPolicyServiceConstants; -import org.apache.sentry.provider.db.service.persistent.SentryStore; -import org.apache.sentry.service.thrift.ProcessorFactory; -import org.apache.thrift.TMultiplexedProcessor; -import org.apache.thrift.TProcessor; - -public class SentryGenericPolicyProcessorFactory extends ProcessorFactory { - - public SentryGenericPolicyProcessorFactory(Configuration conf) { - super(conf); - } - - @Override - public boolean register(TMultiplexedProcessor multiplexedProcessor, - SentryStore _) throws Exception { - SentryGenericPolicyProcessor processHandler = new SentryGenericPolicyProcessor(conf); - TProcessor processor = new SentryGenericPolicyProcessorWrapper<SentryGenericPolicyService.Iface>( - processHandler); - multiplexedProcessor.registerProcessor( - SentryPolicyServiceConstants.SENTRY_GENERIC_SERVICE_NAME, processor); - return true; - } - -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/ConfServlet.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/ConfServlet.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/ConfServlet.java deleted file mode 100644 index 8625487..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/ConfServlet.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.apache.sentry.api.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; - -import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; - -/** - * 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: " + escapeHtml(format)); - } - out.close(); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/LogLevelServlet.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/LogLevelServlet.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/LogLevelServlet.java deleted file mode 100644 index af81d6f..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/LogLevelServlet.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.api.service.thrift; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; - -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; - -public class LogLevelServlet extends HttpServlet { - private static final String LF = "\n"; - private static final String BR = "<br />"; - private static final String B_BR = "<b>%s</b><br />"; - private static final String FORMS_HEAD = - "<h1>" + "Log Level" + "</h1>" - + LF + BR + "<hr /><h3>Results</h3>" - + LF + " Submitted Log Name: " + B_BR; - private static final String FORMS_CONTENT_GET = - LF + " Effective level: " + B_BR; - private static final String FORMS_CONTENT_SET = - LF + " Submitted Level: " + B_BR - + LF + " Setting Level to %s" + BR - + LF + " Effective level: " + B_BR; - private static final String FORMS_END = - LF + BR + "<hr /><h3>Get / Set</h3>" - + LF + "<form>Log: <input type='text' size='50' name='log' /> " - + "<input type='submit' value='Get Log Level' />" + "</form>" - + LF + "<form>Log: <input type='text' size='50' name='log' /> " - + "Level: <input type='text' name='level' /> " - + "<input type='submit' value='Set Log Level' />" + "</form>"; - private static final String FORMS_GET = FORMS_HEAD + FORMS_CONTENT_GET; - private static final String FORMS_SET = FORMS_HEAD + FORMS_CONTENT_SET; - - /** - * Return parameter on servlet request for the given name - * - * @param request: Servlet request - * @param name: Name of parameter in servlet request - * @return Parameter in servlet request for the given name, return null if can't find parameter. - */ - private String getParameter(ServletRequest request, String name) { - String s = request.getParameter(name); - if (s == null) { - return null; - } - s = s.trim(); - return s.length() == 0 ? null : s; - } - - /** - * Check the validity of the log level. - * @param level: The log level to be checked - * @return - * true: The log level is valid - * false: The log level is invalid - */ - private boolean isLogLevelValid(String level) { - return level.equals(Level.toLevel(level).toString()); - } - - /** - * Parse the class name and log level in the http servlet request. - * If the request contains only class name, return the log level in the response message. - * If the request contains both class name and level, set the log level to the requested level - * and return the setting result in the response message. - */ - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String logName = getParameter(request, "log"); - String level = getParameter(request, "level"); - response.setContentType("text/html;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - PrintWriter out = response.getWriter(); - - if (logName != null) { - Logger logInstance = LogManager.getLogger(logName); - if (level == null) { - out.write(String.format(FORMS_GET, - escapeHtml(logName), - logInstance.getEffectiveLevel().toString())); - } else if (isLogLevelValid(level)) { - logInstance.setLevel(Level.toLevel(level)); - out.write(String.format(FORMS_SET, - escapeHtml(logName), - escapeHtml(level), - escapeHtml(level), - logInstance.getEffectiveLevel().toString())); - } else { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid log level: " + escapeHtml(level)); - return; - } - } - out.write(FORMS_END); - out.close(); - response.flushBuffer(); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/PubSubServlet.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/PubSubServlet.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/PubSubServlet.java deleted file mode 100644 index 8da35f1..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/PubSubServlet.java +++ /dev/null @@ -1,128 +0,0 @@ -/** - * 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 - * <p> - * http://www.apache.org/licenses/LICENSE-2.0 - * <p> - * 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.api.service.thrift; - -import org.apache.sentry.core.common.utils.PubSub; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; - -import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; - -/** - * This servlet facilitates sending {topic, message } tuples to Servlet components - * subscribed to specific topics. - * <p> - * It uses publish-subscribe mechanism implemented by PubSub class. - * The form generated by this servlet consists of the following elements: - * <p> - * a) Topic: pull-down menu of existing topics, i.e. the topics registered with - * PubSub by calling PubSub.subscribe() API. This prevents entering invalid topic. - * <p> - * b) Message: text field for entering a message - * <p> - * c) Submit: button to submit (topic, message) tuple - * <p> - * d) Status: text area printing status of the request or help information. - */ -public class PubSubServlet extends HttpServlet { - - private static final Logger LOGGER = LoggerFactory.getLogger(PubSubServlet.class); - - private static final String FORM_GET = - "<!DOCTYPE html>" + - "<html>" + - "<body>" + - "<form>" + - "<br><br><b>Topic:</b><br><br>" + - "<select name='topic'/>%s</select>" + - "<br><br><b>Message:</b><br><br>" + - "<input type='text' size='50' name='message'/>" + - "<br><br>" + - "<input type='submit' value='Submit'/>" + - "</form>" + - "<br><br><b>Status:</b><br><br>" + - "<textarea rows='4' cols='50'>%s</textarea>" + - "</body>" + - "</html>"; - - /** - * Return parameter on servlet request for the given name - * - * @param request: Servlet request - * @param name: Name of parameter in servlet request - * @return Parameter in servlet request for the given name, return null if can't find parameter. - */ - private static String getParameter(ServletRequest request, String name) { - String s = request.getParameter(name); - if (s == null) { - return null; - } - s = s.trim(); - return s.isEmpty() ? null : s; - } - - /** - * Parse the topic and message values and submit them via PubSub.submit() API. - * Reject request for unknown topic, i.e. topic no one is subscribed to. - */ - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String topic = getParameter(request, "topic"); - String message = getParameter(request, "message"); - response.setContentType("text/html;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - PrintWriter out = response.getWriter(); - - String msg = "Topic is required, Message is optional.\nValid topics: " + PubSub.getInstance().getTopics(); - if (topic != null) { - LOGGER.info("Submitting topic " + topic + ", message " + message); - try { - PubSub.getInstance().publish(PubSub.Topic.fromString(topic), message); - msg = "Submitted topic " + topic + ", message " + message; - } catch (Exception e) { - msg = "Failed to submit topic " + topic + ", message " + message + " - " + e.getMessage(); - LOGGER.error(msg); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); - return; - } - } - - StringBuilder topics = new StringBuilder(); - for (PubSub.Topic t : PubSub.getInstance().getTopics()) { - topics.append("<option>").append(t.getName()).append("</option>"); - } - - String output = String.format(FORM_GET, topics.toString(), escapeHtml(msg)); - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("HTML Page: " + output); - } - out.write(output); - out.close(); - response.flushBuffer(); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAdminServlet.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAdminServlet.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAdminServlet.java deleted file mode 100644 index 5dc6cd6..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAdminServlet.java +++ /dev/null @@ -1,132 +0,0 @@ -/** - * 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.api.service.thrift; - -import com.google.gson.Gson; -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.provider.db.service.persistent.SentryStore; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.Writer; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Admin Servlet is only used when SENTRY_WEB_ADMIN_SERVLET_ENABLED is true. - */ -public class SentryAdminServlet extends HttpServlet { - private static final String SHOW_ALL = "/showAll"; - // Here we use the same way as in com.codahale.metrics.servlets.AdminServlet, and just - // use the TEMPLATE as a static html with some links referenced to other debug pages. - private static final String TEMPLATE = "<!DOCTYPE HTML>\n"+ - "<html lang=\"en\">\n"+ - "<head>\n"+ - " <meta charset=\"utf-8\">\n"+ - " <title>Sentry Service Admin</title>\n"+ - " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"+ - " <meta name=\"description\" content=\"\">\n"+ - " <link href=\"css/bootstrap.min.css\" rel=\"stylesheet\">\n"+ - " <link href=\"css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n"+ - " <link href=\"css/sentry.css\" rel=\"stylesheet\">\n"+ - "</head>\n"+ - "<body>\n"+ - "<nav class=\"navbar navbar-default navbar-fixed-top\">\n"+ - " <div class=\"container\">\n"+ - " <div class=\"navbar-header\">\n"+ - " <a class=\"navbar-brand\" href=\"#\"><img src=\"sentry.png\" alt=\"Sentry Logo\"/></a>\n"+ - " </div>\n"+ - " <div class=\"collapse navbar-collapse\">\n"+ - " <ul class=\"nav navbar-nav\">\n"+ - " <li class=\"active\"><a href=\"#\">Admin</a></li>\n"+ - " <li><a href=\"/metrics?pretty=true\">Metrics</a></li>\n"+ - " <li><a href=\"/threads\">Threads</a></li>\n"+ - " <li><a href=\"/conf\">Configuration</a></li>\n"+ - " <li><a href=\"/admin/showAll\">ShowAllRoles</a></li>\n"+ - " </ul>\n"+ - " </div>\n"+ - " </div>\n"+ - "</nav>\n"+ - "<div class=\"container\">\n"+ - " <ul>\n"+ - " <li><a href=\"/metrics?pretty=true\">Metrics</a></li>\n"+ - " <li><a href=\"/threads\">Threads</a></li>\n"+ - " <li><a href=\"/conf\">Configuration</a></li>\n"+ - " <li><a href=\"/admin/showAll\">ShowAllRoles</a></li>\n"+ - " </ul>\n"+ - "</div>\n"+ - "</body>\n"+ - "</html>"; - - @Override - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - String uri = request.getPathInfo(); - if(uri != null && !uri.equals("/")) { - if (uri.equals(SHOW_ALL)) { - showAll(response); - } else { - response.sendError(404); - } - } else { - response.setStatus(200); - response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - response.setContentType("text/html"); - PrintWriter writer = response.getWriter(); - try { - writer.println(TEMPLATE); - } finally { - writer.close(); - } - } - } - - /** - * Print out all the roles and privileges information as json format. - */ - private void showAll(HttpServletResponse response) - throws ServletException, IOException { - Configuration conf = (Configuration)getServletContext().getAttribute( - ConfServlet.CONF_CONTEXT_ATTRIBUTE); - assert conf != null; - - Writer out = response.getWriter(); - try { - SentryStore sentrystore = new SentryStore(conf); - Map<String, Set<TSentryPrivilege>> roleMap = new HashMap<>(); - Set<String> roleSet = sentrystore.getAllRoleNames(); - for (String roleName: roleSet) { - roleMap.put(roleName, sentrystore.getAllTSentryPrivilegesByRoleName(roleName)); - } - String json = new Gson().toJson(roleMap); - response.setContentType("application/json"); - response.setCharacterEncoding("UTF-8"); - out.write(json); - } catch (Exception e) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); - } - out.close(); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAuthFilter.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAuthFilter.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAuthFilter.java deleted file mode 100644 index 23121ec..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryAuthFilter.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * 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.api.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.common.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<String> 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 <code>getConfiguration<code> to get <code>ALLOW_WEB_CONNECT_USERS<code>. - */ - @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<String> parseConnectUsersFromConf(String value) { - //Removed the logic to convert the allowed users to lower case, as user names need to be case sensitive - return Sets.newHashSet(StringUtils.getStrings(value)); - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryHealthCheckServletContextListener.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryHealthCheckServletContextListener.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryHealthCheckServletContextListener.java deleted file mode 100644 index eb11c19..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryHealthCheckServletContextListener.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 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.api.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/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetrics.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetrics.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetrics.java deleted file mode 100644 index 80a6343..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetrics.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * 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.api.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.Slf4jReporter; -import com.codahale.metrics.Timer; -import com.codahale.metrics.json.MetricsModule; -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 com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import org.apache.hadoop.conf.Configuration; -import org.apache.sentry.provider.db.service.persistent.SentryStore; -import org.apache.sentry.service.thrift.SentryService; -import org.apache.sentry.api.common.SentryServiceUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedWriter; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import static com.codahale.metrics.MetricRegistry.name; -import static org.apache.sentry.api.service.thrift.SentryMetricsServletContextListener.METRIC_REGISTRY; -import static org.apache.sentry.service.common.ServiceConstants.ServerConfig; - -/** - * A singleton class which holds metrics related utility functions as well as the list of metrics. - */ -public final class SentryMetrics { - public enum Reporting { - JMX, - CONSOLE, - LOG, - JSON, - } - - private static final Logger LOGGER = LoggerFactory - .getLogger(SentryMetrics.class); - - private static SentryMetrics sentryMetrics = null; - private final AtomicBoolean reportingInitialized = new AtomicBoolean(); - private boolean gaugesAdded = false; - private boolean sentryServiceGaugesAdded = false; - - final Timer createRoleTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "create-role")); - final Timer dropRoleTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "drop-role")); - final Timer grantRoleTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "grant-role")); - final Timer revokeRoleTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "revoke-role")); - final Timer grantTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "grant-privilege")); - final Timer revokeTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "revoke-privilege")); - - final Timer dropPrivilegeTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "drop-privilege")); - final Timer renamePrivilegeTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "rename-privilege")); - - final Timer listRolesByGroupTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "list-roles-by-group")); - final Timer listPrivilegesByRoleTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "list-privileges-by-role")); - final Timer listPrivilegesForProviderTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "list-privileges-for-provider")); - final Timer listPrivilegesByAuthorizableTimer = METRIC_REGISTRY.timer( - name(SentryPolicyStoreProcessor.class, "list-privileges-by-authorizable")); - - /** - * Return a Timer with name. - */ - public Timer getTimer(String name) { - return METRIC_REGISTRY.timer(name); - } - - /** - * Return a Histogram with name. - */ - public Histogram getHistogram(String name) { - return METRIC_REGISTRY.histogram(name); - } - - /** - * Return a Counter with name. - */ - public Counter getCounter(String name) { - return METRIC_REGISTRY.counter(name); - } - - private SentryMetrics() { - registerMetricSet("gc", new GarbageCollectorMetricSet(), METRIC_REGISTRY); - registerMetricSet("buffers", - new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()), - METRIC_REGISTRY); - registerMetricSet("memory", new MemoryUsageGaugeSet(), METRIC_REGISTRY); - registerMetricSet("threads", new ThreadStatesGaugeSet(), METRIC_REGISTRY); - } - - /** - * Get singleton instance. - */ - public static synchronized SentryMetrics getInstance() { - if (sentryMetrics == null) { - sentryMetrics = new SentryMetrics(); - } - return sentryMetrics; - } - - 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()); - addGauge(SentryStore.class, "hms.waiters", sentryStore.getHMSWaitersCountGauge()); - addGauge(SentryStore.class, "hms.notification.id", - sentryStore.getLastNotificationIdGauge()); - addGauge(SentryStore.class, "hms.snapshot.paths.id", - sentryStore.getLastPathsSnapshotIdGauge()); - addGauge(SentryStore.class, "hms.perm.change.id", - sentryStore.getPermChangeIdGauge()); - addGauge(SentryStore.class, "hms.psth.change.id", - sentryStore.getPathChangeIdGauge()); - gaugesAdded = true; - } - } - - /** - * Add gauges for the SentryService class. - * @param sentryservice - */ - public void addSentryServiceGauges(SentryService sentryservice) { - if (!sentryServiceGaugesAdded) { - addGauge(SentryService.class, "is_active", sentryservice.getIsActiveGauge()); - addGauge(SentryService.class, "activated", sentryservice.getBecomeActiveCount()); - sentryServiceGaugesAdded = true; - } - } - - /** - * Initialize reporters. Only initializes once.<p> - * - * Available reporters: - * <ul> - * <li>console</li> - * <li>log</li> - * <li>jmx</li> - * </ul> - * - * <p><For console reporter configre it to report every - * <em>SENTRY_REPORTER_INTERVAL_SEC</em> seconds. - * - * <p>Method is thread safe. - */ - @SuppressWarnings("squid:S2095") - void initReporting(Configuration conf) { - final String reporter = conf.get(ServerConfig.SENTRY_REPORTER); - if ((reporter == null) || reporter.isEmpty() || reportingInitialized.getAndSet(true)) { - // Nothing to do, just return - return; - } - - final int reportInterval = - conf.getInt(ServerConfig.SENTRY_REPORTER_INTERVAL_SEC, - ServerConfig.SENTRY_REPORTER_INTERVAL_DEFAULT); - - // Get list of configured reporters - Set<String> reporters = new HashSet<>(); - for (String r: reporter.split(",")) { - reporters.add(r.trim().toUpperCase()); - } - - // In case there are no reporters, configure JSON reporter - if (reporters.isEmpty()) { - reporters.add(Reporting.JSON.toString()); - } - - // Configure all reporters - for (String r: reporters) { - switch (SentryMetrics.Reporting.valueOf(r)) { - case CONSOLE: - LOGGER.info("Enabled console metrics reporter with {} seconds interval", - reportInterval); - final ConsoleReporter consoleReporter = - ConsoleReporter.forRegistry(METRIC_REGISTRY) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS) - .build(); - consoleReporter.start(reportInterval, TimeUnit.SECONDS); - break; - case JMX: - LOGGER.info("Enabled JMX metrics reporter"); - final JmxReporter jmxReporter = JmxReporter.forRegistry(METRIC_REGISTRY) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS) - .build(); - jmxReporter.start(); - break; - case LOG: - LOGGER.info("Enabled Log4J metrics reporter with {} seconds interval", - reportInterval); - final Slf4jReporter logReporter = Slf4jReporter.forRegistry(METRIC_REGISTRY) - .outputTo(LOGGER) - .convertRatesTo(TimeUnit.SECONDS) - .convertDurationsTo(TimeUnit.MILLISECONDS) - .build(); - logReporter.start(reportInterval, TimeUnit.SECONDS); - break; - case JSON: - LOGGER.info("Enabled JSON metrics reporter with {} seconds interval", reportInterval); - JsonFileReporter jsonReporter = new JsonFileReporter(conf, - reportInterval, TimeUnit.SECONDS); - jsonReporter.start(); - break; - default: - LOGGER.warn("Invalid metrics reporter {}", reporter); - break; - } - } - } - - private <T, V> void addGauge(Class<T> tClass, String gaugeName, Gauge<V> gauge) { - METRIC_REGISTRY.register( - name(tClass, gaugeName), gauge); - } - - private void registerMetricSet(String prefix, MetricSet metricSet, MetricRegistry registry) { - for (Map.Entry<String, Metric> 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()); - } - } - } - - /** - * Custom reporter that writes metrics as a JSON file. - * This class originated from Apache Hive JSON reporter. - */ - private static class JsonFileReporter implements AutoCloseable, Runnable { - // - // Implementation notes. - // - // 1. Since only local file systems are supported, there is no need to use Hadoop - // version of Path class. - // 2. java.nio package provides modern implementation of file and directory operations - // which is better then the traditional java.io, so we are using it here. - // In particular, it supports atomic creation of temporary files with specified - // permissions in the specified directory. This also avoids various attacks possible - // when temp file name is generated first, followed by file creation. - // See http://www.oracle.com/technetwork/articles/javase/nio-139333.html for - // the description of NIO API and - // http://docs.oracle.com/javase/tutorial/essential/io/legacy.html for the - // description of interoperability between legacy IO api vs NIO API. - // 3. To avoid race conditions with readers of the metrics file, the implementation - // dumps metrics to a temporary file in the same directory as the actual metrics - // file and then renames it to the destination. Since both are located on the same - // filesystem, this rename is likely to be atomic (as long as the underlying OS - // support atomic renames. - // - - // Permissions for the metrics file - private static final FileAttribute<Set<PosixFilePermission>> FILE_ATTRS = - PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-r--r--")); - private static final String JSON_REPORTER_THREAD_NAME = "json-reporter"; - - private ScheduledExecutorService executor = null; - private final ObjectMapper jsonMapper = - new ObjectMapper().registerModule(new MetricsModule(TimeUnit.SECONDS, - TimeUnit.MILLISECONDS, - false)); - private final Configuration conf; - /** Destination file name. */ - // Location of JSON file - private final Path path; - // tmpdir is the dirname(path) - private final Path tmpDir; - private final long interval; - private final TimeUnit unit; - - JsonFileReporter(Configuration conf, long interval, TimeUnit unit) { - this.conf = conf; - String pathString = conf.get(ServerConfig.SENTRY_JSON_REPORTER_FILE, - ServerConfig.SENTRY_JSON_REPORTER_FILE_DEFAULT); - path = Paths.get(pathString).toAbsolutePath(); - LOGGER.info("Reporting metrics to {}", path); - // We want to use tmpDir i the same directory as the destination file to support atomic - // move of temp file to the destination metrics file - tmpDir = path.getParent(); - this.interval = interval; - this.unit = unit; - } - - private void start() { - executor = Executors.newScheduledThreadPool(1, - new ThreadFactoryBuilder().setNameFormat(JSON_REPORTER_THREAD_NAME).build()); - executor.scheduleAtFixedRate(this, 0, interval, unit); - } - - @Override - public void run() { - Path tmpFile = null; - try { - String json = null; - try { - json = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(METRIC_REGISTRY); - } catch (JsonProcessingException e) { - LOGGER.error("Error converting metrics to JSON", e); - return; - } - // Metrics are first dumped to a temp file which is then renamed to the destination - try { - tmpFile = Files.createTempFile(tmpDir, "smetrics", "json", FILE_ATTRS); - } catch (IOException e) { - LOGGER.error("failed to create temp file for JSON metrics", e); - return; - } catch (SecurityException e) { - // This shouldn't ever happen - LOGGER.error("failed to create temp file for JSON metrics: no permissions", e); - return; - } catch (UnsupportedOperationException e) { - // This shouldn't ever happen - LOGGER.error("failed to create temp file for JSON metrics: operartion not supported", e); - return; - } - - try (BufferedWriter bw = new BufferedWriter(new FileWriter(tmpFile.toFile()))) { - bw.write(json); - } - - // Move temp file to the destination file - try { - Files.move(tmpFile, path, StandardCopyOption.ATOMIC_MOVE); - } catch (Exception e) { - LOGGER.error("Failed to move temp metrics file to {}: {}", path, e.getMessage()); - } - } catch (Throwable t) { - // catch all errors (throwable and execptions to prevent subsequent tasks from being suppressed) - LOGGER.error("Error executing scheduled task ", t); - } finally { - // If something happened and we were not able to rename the temp file, attempt to remove it - if (tmpFile != null && tmpFile.toFile().exists()) { - // Attempt to delete temp file, if this fails, not much can be done about it. - try { - Files.delete(tmpFile); - } catch (Exception e) { - LOGGER.error("failed to delete yemporary metrics file {}", tmpFile, e); - } - } - } - } - - @Override - public void close() { - if (executor != null) { - SentryServiceUtil.shutdownAndAwaitTermination(executor, - JSON_REPORTER_THREAD_NAME, 1, TimeUnit.MINUTES, LOGGER); - executor = null; - } - try { - Files.delete(path); - } catch (IOException e) { - LOGGER.error("Unable to delete {}", path, e); - } - } - } -} http://git-wip-us.apache.org/repos/asf/sentry/blob/9351d19d/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetricsServletContextListener.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetricsServletContextListener.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetricsServletContextListener.java deleted file mode 100644 index 253e54f..0000000 --- a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/api/service/thrift/SentryMetricsServletContextListener.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * 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.api.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; - } - -}
