http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java new file mode 100644 index 0000000..3058650 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/CommandUtil.java @@ -0,0 +1,233 @@ +/** + * 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.log.util; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Enumeration; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleGrantPrivilegeRequest; +import org.apache.sentry.provider.db.service.thrift.TAlterSentryRoleRevokePrivilegeRequest; +import org.apache.sentry.provider.db.service.thrift.TSentryGrantOption; +import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege; +import org.apache.sentry.service.thrift.ServiceConstants.PrivilegeScope; + +import com.google.common.annotations.VisibleForTesting; + +public final class CommandUtil { + + public CommandUtil() { + // Make constructor private to avoid instantiation + } + + public static String createCmdForCreateOrDropRole(String roleName, + boolean isCreate) { + if (isCreate) { + return "CREATE ROLE " + roleName; + } + return "DROP ROLE " + roleName; + } + + public static String createCmdForRoleAddGroup(String roleName, String groups) { + return createCmdForRoleGrant(roleName, groups, true, true); + } + + public static String createCmdForRoleDeleteGroup(String roleName, String groups) { + return createCmdForRoleGrant(roleName, groups, false, true); + } + + private static String createCmdForRoleGrant(String roleName, String principals, + boolean isGrant, boolean isGroup) { + StringBuilder sb = new StringBuilder(); + if (isGrant) { + sb.append("GRANT ROLE "); + } else { + sb.append("REVOKE ROLE "); + } + sb.append(roleName); + if (isGrant) { + sb.append(" TO "); + } else { + sb.append(" FROM "); + } + + String principalType = isGroup ? "GROUP" : "USER"; + if (!StringUtils.isEmpty(principals)) { + sb.append(principalType).append(" ").append(principals); + } else { + sb = new StringBuilder("Missing " + principalType + " information."); + } + + return sb.toString(); + } + + public static String createCmdForRoleAddUser(String roleName, String users) { + return createCmdForRoleGrant(roleName, users, true, false); + } + + public static String createCmdForRoleDeleteUser(String roleName, String users) { + return createCmdForRoleGrant(roleName, users, false, false); + } + + public static String createCmdForGrantPrivilege( + TAlterSentryRoleGrantPrivilegeRequest request) { + return createCmdForGrantOrRevokePrivileges(request.getRoleName(), + request.getPrivileges(), true); + } + + public static String createCmdForRevokePrivilege( + TAlterSentryRoleRevokePrivilegeRequest request) { + return createCmdForGrantOrRevokePrivileges(request.getRoleName(), + request.getPrivileges(), false); + } + + private static String createCmdForGrantOrRevokePrivileges(String roleName, + Set<TSentryPrivilege> privileges, boolean isGrant) { + StringBuilder sb = new StringBuilder(); + if (privileges != null) { + for (TSentryPrivilege privilege : privileges) { + sb.append(createCmdForGrantOrRevokePrivilege(roleName, privilege, isGrant)); + } + } + return sb.toString(); + } + + private static String createCmdForGrantOrRevokePrivilege(String roleName, + TSentryPrivilege privilege, boolean isGrant) { + StringBuilder sb = new StringBuilder(); + if (isGrant) { + sb.append("GRANT "); + } else { + sb.append("REVOKE "); + } + + String action = privilege.getAction(); + String privilegeScope = privilege.getPrivilegeScope(); + if (AccessConstants.ALL.equalsIgnoreCase(action)) { + sb.append("ALL"); + } else { + if (action != null) { + action = action.toUpperCase(); + } + sb.append(action); + } + + sb.append(" ON ").append(privilege.getPrivilegeScope()).append(" "); + if (PrivilegeScope.DATABASE.name().equalsIgnoreCase(privilegeScope)) { + sb.append(privilege.getDbName()); + } else if (PrivilegeScope.TABLE.name().equalsIgnoreCase(privilegeScope)) { + sb.append(privilege.getTableName()); + } else if (PrivilegeScope.SERVER.name().equalsIgnoreCase(privilegeScope)) { + sb.append(privilege.getServerName()); + } else if (PrivilegeScope.URI.name().equalsIgnoreCase(privilegeScope)) { + sb.append(privilege.getURI()); + } + + if (isGrant) { + sb.append(" TO ROLE "); + } else { + sb.append(" FROM ROLE "); + } + sb.append(roleName); + + if (privilege.getGrantOption() == TSentryGrantOption.TRUE) { + sb.append(" WITH GRANT OPTION"); + } + + return sb.toString(); + } + + public static String createCmdForGrantGMPrivilege( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest request) { + return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(), true); + } + + public static String createCmdForRevokeGMPrivilege( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest request) { + return createCmdForGrantOrRevokeGMPrivilege(request.getRoleName(), request.getPrivilege(), + false); + } + + private static String createCmdForGrantOrRevokeGMPrivilege(String roleName, + org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege privilege, + boolean isGrant) { + StringBuilder sb = new StringBuilder(); + if (isGrant) { + sb.append("GRANT "); + } else { + sb.append("REVOKE "); + } + + String action = privilege.getAction(); + if (AccessConstants.ALL.equalsIgnoreCase(action)) { + sb.append("ALL"); + } else { + if (action != null) { + action = action.toUpperCase(); + } + sb.append(action); + } + + sb.append(" ON"); + + List<TAuthorizable> authorizables = privilege.getAuthorizables(); + if (authorizables != null) { + for (TAuthorizable authorizable : authorizables) { + sb.append(" ").append(authorizable.getType()).append(" ").append(authorizable.getName()); + } + } + + if (isGrant) { + sb.append(" TO ROLE "); + } else { + sb.append(" FROM ROLE "); + } + sb.append(roleName); + + if (privilege.getGrantOption() == org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption.TRUE) { + sb.append(" WITH GRANT OPTION"); + } + + return sb.toString(); + } + + // Check if the given IP is one of the local IP. + @VisibleForTesting + public static boolean assertIPInAuditLog(String ipInAuditLog) throws Exception { + if (ipInAuditLog == null) { + return false; + } + Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces(); + while (netInterfaces.hasMoreElements()) { + NetworkInterface ni = netInterfaces.nextElement(); + Enumeration<InetAddress> ips = ni.getInetAddresses(); + while (ips.hasMoreElements()) { + if (ipInAuditLog.indexOf(ips.nextElement().getHostAddress()) != -1) { + return true; + } + } + } + return false; + } +}
http://git-wip-us.apache.org/repos/asf/sentry/blob/e72e6eac/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.java new file mode 100644 index 0000000..2e71ce0 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/log/util/Constants.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.log.util; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.sentry.provider.db.service.thrift.*; + +public final class Constants { + public final static String AUDIT_LOGGER_NAME = "sentry.hive.authorization.ddl.logger"; + public final static String AUDIT_LOGGER_NAME_GENERIC = "sentry.generic.authorization.ddl.logger"; + + public final static String LOG_FIELD_SERVICE_NAME = "serviceName"; + public final static String LOG_FIELD_USER_NAME = "userName"; + public final static String LOG_FIELD_IMPERSONATOR = "impersonator"; + public final static String LOG_FIELD_IP_ADDRESS = "ipAddress"; + public final static String LOG_FIELD_OPERATION = "operation"; + public final static String LOG_FIELD_EVENT_TIME = "eventTime"; + public final static String LOG_FIELD_OPERATION_TEXT = "operationText"; + public final static String LOG_FIELD_ALLOWED = "allowed"; + public final static String LOG_FIELD_DATABASE_NAME = "databaseName"; + public final static String LOG_FIELD_TABLE_NAME = "tableName"; + public final static String LOG_FIELD_COLUMN_NAME = "column"; + public final static String LOG_FIELD_RESOURCE_PATH = "resourcePath"; + public final static String LOG_FIELD_OBJECT_TYPE = "objectType"; + public final static String LOG_FIELD_COMPONENT = "component"; + + public final static String OPERATION_CREATE_ROLE = "CREATE_ROLE"; + public final static String OPERATION_DROP_ROLE = "DROP_ROLE"; + public final static String OPERATION_ADD_ROLE = "ADD_ROLE_TO_GROUP"; + public final static String OPERATION_DELETE_ROLE = "DELETE_ROLE_FROM_GROUP"; + public final static String OPERATION_ADD_ROLE_USER = "ADD_ROLE_TO_USER"; + public final static String OPERATION_DELETE_ROLE_USER = "DELETE_ROLE_FROM_USER"; + public final static String OPERATION_GRANT_PRIVILEGE = "GRANT_PRIVILEGE"; + public final static String OPERATION_REVOKE_PRIVILEGE = "REVOKE_PRIVILEGE"; + + public final static String OBJECT_TYPE_PRINCIPAL = "PRINCIPAL"; + public final static String OBJECT_TYPE_ROLE = "ROLE"; + + public final static String TRUE = "true"; + public final static String FALSE = "false"; + + public static final Map<String, String> requestTypeToOperationMap = new HashMap<String, String>(); + public static final Map<String, String> requestTypeToObjectTypeMap = new HashMap<String, String>(); + + static { + // for hive audit log + requestTypeToOperationMap.put(TCreateSentryRoleRequest.class.getName(), + Constants.OPERATION_CREATE_ROLE); + requestTypeToOperationMap.put( + TAlterSentryRoleGrantPrivilegeRequest.class.getName(), + Constants.OPERATION_GRANT_PRIVILEGE); + requestTypeToOperationMap.put( + TAlterSentryRoleRevokePrivilegeRequest.class.getName(), + Constants.OPERATION_REVOKE_PRIVILEGE); + requestTypeToOperationMap.put(TDropSentryRoleRequest.class.getName(), + Constants.OPERATION_DROP_ROLE); + requestTypeToOperationMap.put( + TAlterSentryRoleAddGroupsRequest.class.getName(), + Constants.OPERATION_ADD_ROLE); + requestTypeToOperationMap.put( + TAlterSentryRoleDeleteGroupsRequest.class.getName(), + Constants.OPERATION_DELETE_ROLE); + requestTypeToOperationMap.put( + TAlterSentryRoleAddUsersRequest.class.getName(), + Constants.OPERATION_ADD_ROLE_USER); + requestTypeToOperationMap.put( + TAlterSentryRoleDeleteUsersRequest.class.getName(), + Constants.OPERATION_DELETE_ROLE_USER); + + // for generic model audit log + requestTypeToOperationMap.put( + org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class + .getName(), Constants.OPERATION_CREATE_ROLE); + requestTypeToOperationMap + .put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class + .getName(), Constants.OPERATION_DROP_ROLE); + requestTypeToOperationMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class + .getName(), Constants.OPERATION_GRANT_PRIVILEGE); + requestTypeToOperationMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class + .getName(), Constants.OPERATION_REVOKE_PRIVILEGE); + requestTypeToOperationMap.put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class + .getName(), Constants.OPERATION_ADD_ROLE); + requestTypeToOperationMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class + .getName(), Constants.OPERATION_DELETE_ROLE); + + // for hive audit log + requestTypeToObjectTypeMap.put(TCreateSentryRoleRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put(TDropSentryRoleRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleAddGroupsRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleDeleteGroupsRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleAddUsersRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleDeleteUsersRequest.class.getName(), + Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleGrantPrivilegeRequest.class.getName(), + Constants.OBJECT_TYPE_PRINCIPAL); + requestTypeToObjectTypeMap.put( + TAlterSentryRoleRevokePrivilegeRequest.class.getName(), + Constants.OBJECT_TYPE_PRINCIPAL); + // for generic model audit log + requestTypeToObjectTypeMap.put( + org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest.class + .getName(), Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap + .put(org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest.class + .getName(), Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap.put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest.class + .getName(), Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest.class + .getName(), Constants.OBJECT_TYPE_ROLE); + requestTypeToObjectTypeMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest.class + .getName(), Constants.OBJECT_TYPE_PRINCIPAL); + requestTypeToObjectTypeMap + .put( + org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest.class + .getName(), Constants.OBJECT_TYPE_PRINCIPAL); + } + + private Constants() { + // 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/model/MSentryGMPrivilege.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java new file mode 100644 index 0000000..55b61ac --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGMPrivilege.java @@ -0,0 +1,497 @@ +/** +vim * 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.model; + +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.Field; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.jdo.annotations.PersistenceCapable; +import org.apache.sentry.core.common.Authorizable; +import org.apache.sentry.core.model.db.AccessConstants; + +import com.google.common.base.Strings; +import com.google.common.collect.Lists; + +/** + * Database backed Sentry Generic Privilege for new authorization Model + * Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ +@PersistenceCapable +public class MSentryGMPrivilege { + private static final String PREFIX_RESOURCE_NAME = "resourceName"; + private static final String PREFIX_RESOURCE_TYPE = "resourceType"; + private static final String NULL_COL = "__NULL__"; + private static final String SERVICE_SCOPE = "Server"; + private static final int AUTHORIZABLE_LEVEL = 4; + /** + * The authorizable List has been stored into resourceName and resourceField columns + * We assume that the generic model privilege for any component(hive/impala or solr) doesn't exceed four level. + * This generic model privilege currently can support maximum 4 level. + **/ + private String resourceName0 = NULL_COL; //NOPMD + private String resourceType0 = NULL_COL; //NOPMD + private String resourceName1 = NULL_COL; //NOPMD + private String resourceType1 = NULL_COL; //NOPMD + private String resourceName2 = NULL_COL; //NOPMD + private String resourceType2 = NULL_COL; //NOPMD + private String resourceName3 = NULL_COL; //NOPMD + private String resourceType3 = NULL_COL; //NOPMD + + + private String serviceName; + private String componentName; + private String action; + private String scope; + + private Boolean grantOption = false; + // roles this privilege is a part of + private Set<MSentryRole> roles; + private long createTime; + + public MSentryGMPrivilege() { + this.roles = new HashSet<MSentryRole>(); + } + + public MSentryGMPrivilege(String componentName, String serviceName, + List<? extends Authorizable> authorizables, + String action, Boolean grantOption) { + this.componentName = componentName; + this.serviceName = serviceName; + this.action = action; + this.grantOption = grantOption; + this.roles = new HashSet<MSentryRole>(); + this.createTime = System.currentTimeMillis(); + setAuthorizables(authorizables); + } + + public MSentryGMPrivilege(MSentryGMPrivilege copy) { + this.action = copy.action; + this.componentName = copy.componentName; + this.serviceName = copy.serviceName; + this.grantOption = copy.grantOption; + this.scope = copy.scope; + this.createTime = copy.createTime; + setAuthorizables(copy.getAuthorizables()); + this.roles = new HashSet<MSentryRole>(); + for (MSentryRole role : copy.roles) { + roles.add(role); + } + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getComponentName() { + return componentName; + } + + public void setComponentName(String componentName) { + this.componentName = componentName; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public Boolean getGrantOption() { + return grantOption; + } + + public void setGrantOption(Boolean grantOption) { + this.grantOption = grantOption; + } + + public Set<MSentryRole> getRoles() { + return roles; + } + + public void setRoles(Set<MSentryRole> roles) { + this.roles = roles; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getScope() { + return scope; + } + + public List<? extends Authorizable> getAuthorizables() { + List<Authorizable> authorizables = Lists.newArrayList(); + //construct atuhorizable lists + for (int i = 0; i < AUTHORIZABLE_LEVEL; i++) { + final String resourceName = (String) getField(this, PREFIX_RESOURCE_NAME + String.valueOf(i)); + final String resourceTYpe = (String) getField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i)); + + if (notNULL(resourceName) && notNULL(resourceTYpe)) { + authorizables.add(new Authorizable() { + @Override + public String getTypeName() { + return resourceTYpe; + } + @Override + public String getName() { + return resourceName; + } + }); + } + } + return authorizables; + } + + /** + * Only allow strict hierarchies. That is, can level =1 be not null when level = 0 is null + * @param authorizables + */ + public void setAuthorizables(List<? extends Authorizable> authorizables) { + if (authorizables == null || authorizables.isEmpty()) { + //service scope + scope = SERVICE_SCOPE; + return; + } + if (authorizables.size() > AUTHORIZABLE_LEVEL) { + throw new IllegalStateException("This generic privilege model only supports maximum 4 level."); + } + + for (int i = 0; i < authorizables.size(); i++) { + Authorizable authorizable = authorizables.get(i); + if (authorizable == null) { + String msg = String.format("The authorizable can't be null. Please check authorizables[%d]:", i); + throw new IllegalStateException(msg); + } + String resourceName = authorizable.getName(); + String resourceTYpe = authorizable.getTypeName(); + if (isNULL(resourceName) || isNULL(resourceTYpe)) { + String msg = String.format("The name and type of authorizable can't be empty or null.Please check authorizables[%d]", i); + throw new IllegalStateException(msg); + } + setField(this, PREFIX_RESOURCE_NAME + String.valueOf(i), toNULLCol(resourceName)); + setField(this, PREFIX_RESOURCE_TYPE + String.valueOf(i), toNULLCol(resourceTYpe)); + scope = resourceTYpe; + } + } + + public void appendRole(MSentryRole role) { + if (roles.add(role)) { + role.appendGMPrivilege(this); + } + } + + public void removeRole(MSentryRole role) { + if(roles.remove(role)) { + role.removeGMPrivilege(this); + } + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((componentName == null) ? 0 : componentName.hashCode()); + result = prime * result + ((serviceName == null) ? 0 : serviceName.hashCode()); + result = prime * result + ((grantOption == null) ? 0 : grantOption.hashCode()); + result = prime * result + ((scope == null) ? 0 : scope.hashCode()); + + for (Authorizable authorizable : getAuthorizables()) { + result = prime * result + authorizable.getName().hashCode(); + result = prime * result + authorizable.getTypeName().hashCode(); + } + + return result; + } + + @Override + public String toString() { + List<String> unifiedNames = Lists.newArrayList(); + for (Authorizable auth : getAuthorizables()) { + unifiedNames.add(KV_JOINER.join(auth.getTypeName(),auth.getName())); + } + + return "MSentryGMPrivilege [" + + "serverName=" + serviceName + ", componentName=" + componentName + + ", authorizables=" + AUTHORIZABLE_JOINER.join(unifiedNames)+ ", scope=" + scope + + ", action=" + action + ", roles=[...]" + ", createTime=" + + createTime + ", grantOption=" + grantOption +"]"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MSentryGMPrivilege other = (MSentryGMPrivilege) obj; + if (action == null) { + if (other.action != null) { + return false; + } + } else if (!action.equalsIgnoreCase(other.action)) { + return false; + } + if (scope == null) { + if (other.scope != null) { + return false; + } + } else if (!scope.equals(other.scope)) { + return false; + } + if (serviceName == null) { + if (other.serviceName != null) { + return false; + } + } else if (!serviceName.equals(other.serviceName)) { + return false; + } + if (componentName == null) { + if (other.componentName != null) { + return false; + } + } else if (!componentName.equals(other.componentName)) { + return false; + } + if (grantOption == null) { + if (other.grantOption != null) { + return false; + } + } else if (!grantOption.equals(other.grantOption)) { + return false; + } + + List<? extends Authorizable> authorizables = getAuthorizables(); + List<? extends Authorizable> otherAuthorizables = other.getAuthorizables(); + + if (authorizables.size() != otherAuthorizables.size()) { + return false; + } + for (int i = 0; i < authorizables.size(); i++) { + String o1 = KV_JOINER.join(authorizables.get(i).getTypeName(), + authorizables.get(i).getName()); + String o2 = KV_JOINER.join(otherAuthorizables.get(i).getTypeName(), + otherAuthorizables.get(i).getName()); + if (!o1.equals(o2)) { + return false; + } + } + return true; + } + + /** + * Return true if this privilege implies request privilege + * Otherwise, return false + * @param other, other privilege + */ + public boolean implies(MSentryGMPrivilege request) { + //component check + if (!componentName.equals(request.getComponentName())) { + return false; + } + //service check + if (!serviceName.equals(request.getServiceName())) { + return false; + } + // check action implies + if (!action.equalsIgnoreCase(AccessConstants.ALL) + && !action.equalsIgnoreCase(request.getAction()) + && !action.equalsIgnoreCase(AccessConstants.ACTION_ALL)) { + return false; + } + //check authorizable list implies + Iterator<? extends Authorizable> existIterator = getAuthorizables().iterator(); + Iterator<? extends Authorizable> requestIterator = request.getAuthorizables().iterator(); + while (existIterator.hasNext() && requestIterator.hasNext()) { + Authorizable existAuth = existIterator.next(); + Authorizable requestAuth = requestIterator.next(); + //check authorizable type + if (!existAuth.getTypeName().equals(requestAuth.getTypeName())) { + return false; + } + //check authorizable name + if (!existAuth.getName().equals(requestAuth.getName())) { + /**The persistent authorizable isn't equal the request authorizable + * but the following situations are pass check + * The name of persistent authorizable is ALL or "*" + */ + if (existAuth.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL) + || existAuth.getName().equalsIgnoreCase(AccessConstants.ALL)) { + continue; + } else { + return false; + } + } + } + + if ( !existIterator.hasNext() && !requestIterator.hasNext() ){ + /** + * The persistent privilege has the same authorizables size as the requested privilege + * The check is pass + */ + return true; + + } else if (existIterator.hasNext()) { + /** + * The persistent privilege has much more authorizables than request privilege,so its scope is less + * than the requested privilege. + * There is a situation that the check is pass, the name of the exceeding authorizables is ALL or "*". + * Take the Solr for example,the exist privilege is collection=c1->field=*->action=query + * the request privilege is collection=c1->action=query, the check is pass + */ + while (existIterator.hasNext()) { + Authorizable existAuthorizable = existIterator.next(); + if (existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ALL) + || existAuthorizable.getName().equalsIgnoreCase(AccessConstants.ACTION_ALL)) { + continue; + } else { + return false; + } + } + } else { + /** + * The requested privilege has much more authorizables than persistent privilege, so its scope is less + * than the persistent privilege + * The check is pass + */ + return true; + } + + return true; + } + + public static String toNULLCol(String col) { + return Strings.isNullOrEmpty(col) ? NULL_COL : col; + } + + public static boolean notNULL(String s) { + return !(Strings.isNullOrEmpty(s) || NULL_COL.equals(s)); + } + + public static boolean isNULL(String s) { + return !notNULL(s); + } + + public static <T> void setField(Object obj, String fieldName, T fieldValue) { + try { + Class<?> clazz = obj.getClass(); + Field field=clazz.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(obj, fieldValue); + } catch (Exception e) { + throw new RuntimeException("setField error: " + e.getMessage(), e); + } + } + + @SuppressWarnings("unchecked") + public static <T> T getField(Object obj, String fieldName) { + try { + Class<?> clazz = obj.getClass(); + Field field=clazz.getDeclaredField(fieldName); + field.setAccessible(true); + return (T)field.get(obj); + } catch (Exception e) { + throw new RuntimeException("getField error: " + e.getMessage(), e); + } + } + + /** + * return the query to execute in JDO for search the given privilege + * @param privilege + * @return query + */ + public static String toQuery(MSentryGMPrivilege privilege) { + StringBuilder query = new StringBuilder(); + query.append("serviceName == \"" + toNULLCol(privilege.getServiceName()) + "\" "); + query.append("&& componentName == \"" + toNULLCol(privilege.getComponentName()) + "\" "); + query.append("&& scope == \"" + toNULLCol(privilege.getScope()) + "\" "); + query.append("&& action == \"" + toNULLCol(privilege.getAction()) + "\""); + if (privilege.getGrantOption() == null) { + query.append("&& this.grantOption == null "); + } else if (privilege.getGrantOption()) { + query.append("&& grantOption "); + } else { + query.append("&& !grantOption "); + } + List<? extends Authorizable> authorizables = privilege.getAuthorizables(); + for (int i = 0; i < AUTHORIZABLE_LEVEL; i++) { + String resourceName = PREFIX_RESOURCE_NAME + String.valueOf(i); + String resourceType = PREFIX_RESOURCE_TYPE + String.valueOf(i); + + if (i >= authorizables.size()) { + query.append("&& " + resourceName + " == \"" + NULL_COL + "\" "); + query.append("&& " + resourceType + " == \"" + NULL_COL + "\" "); + } else { + query.append("&& " + resourceName + " == \"" + authorizables.get(i).getName() + "\" "); + query.append("&& " + resourceType + " == \"" + authorizables.get(i).getTypeName() + "\" "); + } + } + return query.toString(); + } + + /** + * Get the query to execute in the JDO deducing privileges include the scope of according to the given privilege + * The query was used in three privilege operations: + * 1.revoking privilege + * 2.renaming privilege + * 3.dropping privilege + * Take the Solr for example, if there exists three privileges such as p1:Collection=c1->action=query, + * p2:Collection=c1->Field=f1->action=query and p3:Collection=c1->Field=f2->action=query. + * When the revoking operation happens, the request privilege is p4:Collection=c1->action=query. + * The result is that not only p1 should be revoked, but also p2 and p3 should be revoked together. + * So the populateIncludePrivilegesQuery should be Collection=c1 + * @param privilege + * @return query + */ + public static String populateIncludePrivilegesQuery(MSentryGMPrivilege privilege) { + StringBuilder query = new StringBuilder(); + query.append("serviceName == \"" + toNULLCol(privilege.getServiceName()) + "\" "); + query.append("&& componentName == \"" + toNULLCol(privilege.getComponentName()) + "\" "); + List<? extends Authorizable> authorizables = privilege.getAuthorizables(); + for (int i= 0 ; i < authorizables.size(); i++) { + String resourceName = PREFIX_RESOURCE_NAME + String.valueOf(i); + String resourceType = PREFIX_RESOURCE_TYPE + String.valueOf(i); + query.append("&& " + resourceName + " == \"" + authorizables.get(i).getName() + "\" "); + query.append("&& " + resourceType + " == \"" + authorizables.get(i).getTypeName() + "\" "); + } + return query.toString(); + } +} 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/model/MSentryGroup.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java new file mode 100644 index 0000000..7e41c93 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java @@ -0,0 +1,116 @@ +/** + * 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.model; + +import java.util.Set; + +import javax.jdo.annotations.PersistenceCapable; + +/** + * Database backed Sentry Group. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ +@PersistenceCapable +public class MSentryGroup { + + /** + * Group name is unique + */ + private String groupName; + // set of roles granted to this group + private Set<MSentryRole> roles; + private long createTime; + + public MSentryGroup(String groupName, long createTime, Set<MSentryRole> roles) { + this.setGroupName(groupName); + this.createTime = createTime; + this.roles = roles; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public Set<MSentryRole> getRoles() { + return roles; + } + + public String getGroupName() { + return groupName; + } + + public void setGroupName(String groupName) { + this.groupName = groupName; + } + + public void appendRole(MSentryRole role) { + if (roles.add(role)) { + role.appendGroup(this); + } + } + + public void removeRole(MSentryRole role) { + if (roles.remove(role)) { + role.removeGroup(this); + } + } + + @Override + public String toString() { + return "MSentryGroup [groupName=" + groupName + ", roles=[...]" + + ", createTime=" + createTime + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((groupName == null) ? 0 : groupName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MSentryGroup other = (MSentryGroup) obj; + if (createTime != other.createTime) { + return false; + } + if (groupName == null) { + if (other.groupName != null) { + return false; + } + } else if (!groupName.equals(other.groupName)) { + return false; + } + return true; + } +} 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/model/MSentryPrivilege.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java new file mode 100644 index 0000000..4c3af79 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java @@ -0,0 +1,332 @@ +/** + * 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.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.jdo.annotations.PersistenceCapable; + +import org.apache.sentry.core.common.utils.PathUtils; +import org.apache.sentry.core.model.db.AccessConstants; +import org.apache.sentry.provider.db.service.persistent.SentryStore; + +/** + * Database backed Sentry Privilege. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ +@PersistenceCapable +public class MSentryPrivilege { + + private String privilegeScope; + /** + * Privilege name is unique + */ + private String serverName = ""; + private String dbName = ""; + private String tableName = ""; + private String columnName = ""; + private String URI = ""; + private String action = ""; + private Boolean grantOption = false; + // roles this privilege is a part of + private Set<MSentryRole> roles; + private long createTime; + + public MSentryPrivilege() { + this.roles = new HashSet<MSentryRole>(); + } + + public MSentryPrivilege(String privilegeScope, + String serverName, String dbName, String tableName, String columnName, + String URI, String action, Boolean grantOption) { + this.privilegeScope = privilegeScope; + this.serverName = serverName; + this.dbName = SentryStore.toNULLCol(dbName); + this.tableName = SentryStore.toNULLCol(tableName); + this.columnName = SentryStore.toNULLCol(columnName); + this.URI = SentryStore.toNULLCol(URI); + this.action = SentryStore.toNULLCol(action); + this.grantOption = grantOption; + this.roles = new HashSet<MSentryRole>(); + } + + public MSentryPrivilege(String privilegeScope, + String serverName, String dbName, String tableName, String columnName, + String URI, String action) { + this(privilegeScope, serverName, dbName, tableName, + columnName, URI, action, false); + } + + public MSentryPrivilege(MSentryPrivilege other) { + this.privilegeScope = other.privilegeScope; + this.serverName = other.serverName; + this.dbName = SentryStore.toNULLCol(other.dbName); + this.tableName = SentryStore.toNULLCol(other.tableName); + this.columnName = SentryStore.toNULLCol(other.columnName); + this.URI = SentryStore.toNULLCol(other.URI); + this.action = SentryStore.toNULLCol(other.action); + this.grantOption = other.grantOption; + this.roles = new HashSet<MSentryRole>(); + for (MSentryRole role : other.roles) { + roles.add(role); + } + } + + public String getServerName() { + return serverName; + } + + public void setServerName(String serverName) { + this.serverName = (serverName == null) ? "" : serverName; + } + + public String getDbName() { + return dbName; + } + + public void setDbName(String dbName) { + this.dbName = (dbName == null) ? "" : dbName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = (tableName == null) ? "" : tableName; + } + + public String getColumnName() { + return columnName; + } + + public void setColumnName(String columnName) { + this.columnName = (columnName == null) ? "" : columnName; + } + + public String getURI() { + return URI; + } + + public void setURI(String uRI) { + URI = (uRI == null) ? "" : uRI; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = (action == null) ? "" : action; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getPrivilegeScope() { + return privilegeScope; + } + + public void setPrivilegeScope(String privilegeScope) { + this.privilegeScope = privilegeScope; + } + + public Boolean getGrantOption() { + return grantOption; + } + + public void setGrantOption(Boolean grantOption) { + this.grantOption = grantOption; + } + + public void appendRole(MSentryRole role) { + roles.add(role); + } + + public Set<MSentryRole> getRoles() { + return roles; + } + + public void removeRole(MSentryRole role) { + roles.remove(role); + role.removePrivilege(this); + } + + @Override + public String toString() { + return "MSentryPrivilege [privilegeScope=" + privilegeScope + + ", serverName=" + serverName + ", dbName=" + dbName + + ", tableName=" + tableName + ", columnName=" + columnName + + ", URI=" + URI + ", action=" + action + ", roles=[...]" + + ", createTime=" + createTime + ", grantOption=" + grantOption +"]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((URI == null) ? 0 : URI.hashCode()); + result = prime * result + ((action == null) ? 0 : action.hashCode()); + result = prime * result + ((dbName == null) ? 0 : dbName.hashCode()); + result = prime * result + + ((serverName == null) ? 0 : serverName.hashCode()); + result = prime * result + ((tableName == null) ? 0 : tableName.hashCode()); + result = prime * result + + ((columnName == null) ? 0 : columnName.hashCode()); + result = prime * result + + ((grantOption == null) ? 0 : grantOption.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MSentryPrivilege other = (MSentryPrivilege) obj; + if (URI == null) { + if (other.URI != null) { + return false; + } + } else if (!URI.equals(other.URI)) { + return false; + } + if (action == null) { + if (other.action != null) { + return false; + } + } else if (!action.equals(other.action)) { + return false; + } + if (dbName == null) { + if (other.dbName != null) { + return false; + } + } else if (!dbName.equals(other.dbName)) { + return false; + } + if (serverName == null) { + if (other.serverName != null) { + return false; + } + } else if (!serverName.equals(other.serverName)) { + return false; + } + if (tableName == null) { + if (other.tableName != null) { + return false; + } + } else if (!tableName.equals(other.tableName)) { + return false; + } + if (columnName == null) { + if (other.columnName != null) { + return false; + } + } else if (!columnName.equals(other.columnName)) { + return false; + } + if (grantOption == null) { + if (other.grantOption != null) { + return false; + } + } else if (!grantOption.equals(other.grantOption)) { + return false; + } + return true; + } + + /** + * Return true if this privilege implies other privilege + * Otherwise, return false + * @param other, other privilege + */ + public boolean implies(MSentryPrivilege other) { + // serverName never be null + if (isNULL(serverName) || isNULL(other.serverName)) { + return false; + } else if (!serverName.equals(other.serverName)) { + return false; + } + + // check URI implies + if (!isNULL(URI) && !isNULL(other.URI)) { + if (!PathUtils.impliesURI(URI, other.URI)) { + return false; + } + // if URI is NULL, check dbName and tableName + } else if (isNULL(URI) && isNULL(other.URI)) { + if (!isNULL(dbName)) { + if (isNULL(other.dbName)) { + return false; + } else if (!dbName.equals(other.dbName)) { + return false; + } + } + if (!isNULL(tableName)) { + if (isNULL(other.tableName)) { + return false; + } else if (!tableName.equals(other.tableName)) { + return false; + } + } + if (!isNULL(columnName)) { + if (isNULL(other.columnName)) { + return false; + } else if (!columnName.equals(other.columnName)) { + return false; + } + } + // if URI is not NULL, but other's URI is NULL, return false + } else if (!isNULL(URI) && isNULL(other.URI)){ + return false; + } + + // check action implies + if (!action.equalsIgnoreCase(AccessConstants.ALL) + && !action.equalsIgnoreCase(other.action) + && !action.equalsIgnoreCase(AccessConstants.ACTION_ALL)) { + return false; + } + + return true; + } + + private boolean isNULL(String s) { + return SentryStore.isNULL(s); + } + + public boolean isActionALL() { + return AccessConstants.ACTION_ALL.equalsIgnoreCase(action) + || AccessConstants.ALL.equals(action); + } + +} 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/model/MSentryRole.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java new file mode 100644 index 0000000..0484eaa --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java @@ -0,0 +1,216 @@ +/** + * 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.model; + +import java.util.HashSet; +import java.util.Set; + +import javax.jdo.annotations.PersistenceCapable; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; + +/** + * Database backed Sentry Role. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ +@PersistenceCapable +public class MSentryRole { + + private String roleName; + // set of privileges granted to this role + private Set<MSentryPrivilege> privileges; + // set of generic model privileges grant ro this role + private Set<MSentryGMPrivilege> gmPrivileges; + + // set of groups this role belongs to + private Set<MSentryGroup> groups; + // set of users this role belongs to + private Set<MSentryUser> users; + private long createTime; + + public MSentryRole(String roleName, long createTime) { + this.roleName = roleName; + this.createTime = createTime; + privileges = new HashSet<MSentryPrivilege>(); + gmPrivileges = new HashSet<MSentryGMPrivilege>(); + groups = new HashSet<MSentryGroup>(); + users = new HashSet<MSentryUser>(); + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public void setPrivileges(Set<MSentryPrivilege> privileges) { + this.privileges = privileges; + } + + public Set<MSentryPrivilege> getPrivileges() { + return privileges; + } + + public Set<MSentryGMPrivilege> getGmPrivileges() { + return gmPrivileges; + } + + public void setGmPrivileges(Set<MSentryGMPrivilege> gmPrivileges) { + this.gmPrivileges = gmPrivileges; + } + + public void setGroups(Set<MSentryGroup> groups) { + this.groups = groups; + } + + public Set<MSentryGroup> getGroups() { + return groups; + } + + public Set<MSentryUser> getUsers() { + return users; + } + + public void setUsers(Set<MSentryUser> users) { + this.users = users; + } + + public void removePrivilege(MSentryPrivilege privilege) { + if (privileges.remove(privilege)) { + privilege.removeRole(this); + } + } + + public void appendPrivileges(Set<MSentryPrivilege> privileges) { + this.privileges.addAll(privileges); + } + + public void appendPrivilege(MSentryPrivilege privilege) { + if (privileges.add(privilege)) { + privilege.appendRole(this); + } + } + + public void removeGMPrivilege(MSentryGMPrivilege gmPrivilege) { + if (gmPrivileges.remove(gmPrivilege)) { + gmPrivilege.removeRole(this); + } + } + + public void appendGMPrivilege(MSentryGMPrivilege gmPrivilege) { + if (gmPrivileges.add(gmPrivilege)) { + gmPrivilege.appendRole(this); + } + } + + public void removeGMPrivileges() { + for (MSentryGMPrivilege privilege : ImmutableSet.copyOf(gmPrivileges)) { + privilege.removeRole(this); + } + Preconditions.checkState(gmPrivileges.isEmpty(), "gmPrivileges should be empty: " + gmPrivileges); + } + + public void appendGroups(Set<MSentryGroup> groups) { + this.groups.addAll(groups); + } + + public void appendGroup(MSentryGroup group) { + if (groups.add(group)) { + group.appendRole(this); + } + } + + public void removeGroup(MSentryGroup group) { + if (groups.remove(group)) { + group.removeRole(this); + } + } + + public void appendUsers(Set<MSentryUser> users) { + this.users.addAll(users); + } + + public void appendUser(MSentryUser user) { + if (users.add(user)) { + user.appendRole(this); + } + } + + public void removeUser(MSentryUser user) { + if (users.remove(user)) { + user.removeRole(this); + } + } + + public void removePrivileges() { + // copy is required since privilege.removeRole will call remotePrivilege + for (MSentryPrivilege privilege : ImmutableSet.copyOf(privileges)) { + privilege.removeRole(this); + } + Preconditions.checkState(privileges.isEmpty(), "Privileges should be empty: " + privileges); + } + + @Override + public String toString() { + return "MSentryRole [roleName=" + roleName + ", privileges=[..]" + ", gmPrivileges=[..]" + + ", groups=[...]" + ", users=[...]" + ", createTime=" + createTime + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((roleName == null) ? 0 : roleName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MSentryRole other = (MSentryRole) obj; + if (roleName == null) { + if (other.roleName != null) { + return false; + } + } else if (!roleName.equals(other.roleName)) { + return false; + } + return true; + } + +} 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/model/MSentryUser.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java new file mode 100644 index 0000000..ff57249 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryUser.java @@ -0,0 +1,116 @@ +/** + * 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.model; + +import java.util.Set; + +import javax.jdo.annotations.PersistenceCapable; + +/** + * Database backed Sentry User. Any changes to this object + * require re-running the maven build so DN an re-enhance. + */ +@PersistenceCapable +public class MSentryUser { + + /** + * User name is unique + */ + private String userName; + // set of roles granted to this user + private Set<MSentryRole> roles; + private long createTime; + + public MSentryUser(String userName, long createTime, Set<MSentryRole> roles) { + this.setUserName(userName); + this.createTime = createTime; + this.roles = roles; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public Set<MSentryRole> getRoles() { + return roles; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public void appendRole(MSentryRole role) { + if (roles.add(role)) { + role.appendUser(this); + } + } + + public void removeRole(MSentryRole role) { + if (roles.remove(role)) { + role.removeUser(this); + } + } + + @Override + public String toString() { + return "MSentryUser [userName=" + userName + ", roles=[...]" + ", createTime=" + createTime + + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((userName == null) ? 0 : userName.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MSentryUser other = (MSentryUser) obj; + if (createTime != other.createTime) { + return false; + } + if (userName == null) { + if (other.userName != null) { + return false; + } + } else if (!userName.equals(other.userName)) { + return false; + } + return true; + } +} \ 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/model/MSentryVersion.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java new file mode 100644 index 0000000..ff8830f --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/MSentryVersion.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.sentry.provider.db.service.model; + +import javax.jdo.annotations.PersistenceCapable; + +@PersistenceCapable +public class MSentryVersion { + private String schemaVersion; + private String versionComment; + + public MSentryVersion() { + } + + public MSentryVersion(String schemaVersion, String versionComment) { + this.schemaVersion = schemaVersion; + this.versionComment = versionComment; + } + + /** + * @return the versionComment + */ + public String getVersionComment() { + return versionComment; + } + + /** + * @param versionComment + * the versionComment to set + */ + public void setVersionComment(String versionComment) { + this.versionComment = versionComment; + } + + /** + * @return the schemaVersion + */ + public String getSchemaVersion() { + return schemaVersion; + } + + /** + * @param schemaVersion + * the schemaVersion to set + */ + public void setSchemaVersion(String schemaVersion) { + this.schemaVersion = schemaVersion; + } + +} 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/model/package.jdo ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo new file mode 100644 index 0000000..b3b9494 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo @@ -0,0 +1,242 @@ +<?xml version="1.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. +--> +<!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN" + "http://java.sun.com/dtd/jdo_2_0.dtd"> +<!-- + Size Limitations: + + Indexed VARCHAR: 767 bytes (MySQL running on InnoDB Engine http://bugs.mysql.com/bug.php?id=13315) + Non-indexed VARCHAR: 4000 bytes (max length on Oracle 9i/10g/11g) + +--> +<jdo> + <package name="org.apache.sentry.provider.db.service.model"> + <class name="MSentryGroup" identity-type="datastore" table="SENTRY_GROUP" detachable="true"> + <datastore-identity> + <column name="GROUP_ID"/> + </datastore-identity> + <field name="groupName"> + <column name="GROUP_NAME" length="128" jdbc-type="VARCHAR"/> + <index name="SentryGroupName" unique="true"/> + </field> + <field name = "createTime"> + <column name = "CREATE_TIME" jdbc-type="BIGINT"/> + </field> + + <field name="roles" mapped-by="groups"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/> + </field> + + </class> + + <class name="MSentryUser" identity-type="datastore" table="SENTRY_USER" detachable="true"> + <datastore-identity> + <column name="USER_ID"/> + </datastore-identity> + <field name="userName"> + <column name="USER_NAME" length="128" jdbc-type="VARCHAR"/> + <index name="SentryUserName" unique="true"/> + </field> + <field name = "createTime"> + <column name = "CREATE_TIME" jdbc-type="BIGINT"/> + </field> + + <field name="roles" mapped-by="users"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/> + </field> + + </class> + + <class name="MSentryRole" identity-type="datastore" table="SENTRY_ROLE" detachable="true"> + <datastore-identity> + <column name="ROLE_ID"/> + </datastore-identity> + <field name="roleName"> + <column name="ROLE_NAME" length="128" jdbc-type="VARCHAR"/> + <index name="SentryRoleName" unique="true"/> + </field> + <field name = "createTime"> + <column name = "CREATE_TIME" jdbc-type="BIGINT"/> + </field> + <field name = "privileges" table="SENTRY_ROLE_DB_PRIVILEGE_MAP" default-fetch-group="true"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryPrivilege"/> + <join> + <column name="ROLE_ID"/> + </join> + <element> + <column name="DB_PRIVILEGE_ID"/> + </element> + </field> + + <field name = "gmPrivileges" table="SENTRY_ROLE_GM_PRIVILEGE_MAP" default-fetch-group="true"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryGMPrivilege"/> + <join> + <column name="ROLE_ID"/> + </join> + <element> + <column name="GM_PRIVILEGE_ID"/> + </element> + </field> + + <field name = "groups" table="SENTRY_ROLE_GROUP_MAP" default-fetch-group="true"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryGroup"/> + <join> + <column name="ROLE_ID"/> + </join> + <element> + <column name="GROUP_ID"/> + </element> + </field> + + <field name = "users" table="SENTRY_ROLE_USER_MAP" default-fetch-group="true"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryUser"/> + <join> + <column name="ROLE_ID"/> + </join> + <element> + <column name="USER_ID"/> + </element> + </field> + </class> + + <class name="MSentryPrivilege" identity-type="datastore" table="SENTRY_DB_PRIVILEGE" detachable="true"> + <datastore-identity> + <column name="DB_PRIVILEGE_ID"/> + </datastore-identity> + <index name="PRIVILEGE_INDEX" unique="true"> + <field name="serverName"/> + <field name="dbName"/> + <field name="tableName"/> + <field name="columnName"/> + <field name="URI"/> + <field name="action"/> + <field name="grantOption"/> + </index> + <field name="privilegeScope"> + <column name="PRIVILEGE_SCOPE" length="40" jdbc-type="VARCHAR"/> + </field> + <field name="serverName"> + <column name="SERVER_NAME" length="4000" jdbc-type="VARCHAR"/> + </field> + <field name="dbName"> + <column name="DB_NAME" length="4000" jdbc-type="VARCHAR"/> + </field> + <field name="tableName"> + <column name="TABLE_NAME" length="4000" jdbc-type="VARCHAR"/> + </field> + <field name="columnName"> + <column name="COLUMN_NAME" length="4000" jdbc-type="VARCHAR"/> + </field> + <field name="URI"> + <column name="URI" length="4000" jdbc-type="VARCHAR"/> + </field> + <field name="action"> + <column name="ACTION" length="40" jdbc-type="VARCHAR"/> + </field> + <field name = "createTime"> + <column name = "CREATE_TIME" jdbc-type="BIGINT"/> + </field> + <field name="grantOption"> + <column name="WITH_GRANT_OPTION" length="1" jdbc-type="CHAR"/> + </field> + <field name="roles" mapped-by="privileges"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/> + </field> + </class> + + <class name="MSentryGMPrivilege" identity-type="datastore" table="SENTRY_GM_PRIVILEGE" detachable="true"> + <datastore-identity> + <column name="GM_PRIVILEGE_ID"/> + </datastore-identity> + <index name="GM_PRIVILEGE_INDEX" unique="true"> + <field name="componentName"/> + <field name="serviceName"/> + <field name="resourceName0"/> + <field name="resourceType0"/> + <field name="resourceName1"/> + <field name="resourceType1"/> + <field name="resourceName2"/> + <field name="resourceType2"/> + <field name="resourceName3"/> + <field name="resourceType3"/> + <field name="action"/> + <field name="grantOption"/> + </index> + <field name="componentName"> + <column name="COMPONENT_NAME" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="serviceName"> + <column name="SERVICE_NAME" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceName0"> + <column name="RESOURCE_NAME_0" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceType0"> + <column name="RESOURCE_TYPE_0" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceName1"> + <column name="RESOURCE_NAME_1" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceType1"> + <column name="RESOURCE_TYPE_1" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceName2"> + <column name="RESOURCE_NAME_2" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceType2"> + <column name="RESOURCE_TYPE_2" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceName3"> + <column name="RESOURCE_NAME_3" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="resourceType3"> + <column name="RESOURCE_TYPE_3" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="action"> + <column name="ACTION" length="100" jdbc-type="VARCHAR"/> + </field> + <field name="scope"> + <column name="SCOPE" length="100" jdbc-type="VARCHAR"/> + </field> + <field name = "createTime"> + <column name = "CREATE_TIME" jdbc-type="BIGINT"/> + </field> + <field name="grantOption"> + <column name="WITH_GRANT_OPTION" length="1" jdbc-type="CHAR"/> + </field> + <field name="roles" mapped-by="gmPrivileges"> + <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/> + </field> + </class> + + <class name="MSentryVersion" table="SENTRY_VERSION" identity-type="datastore" detachable="true"> + <datastore-identity> + <column name="VER_ID"/> + </datastore-identity> + <field name ="schemaVersion"> + <column name="SCHEMA_VERSION" length="127" jdbc-type="VARCHAR" allows-null="false"/> + </field> + <field name ="versionComment"> + <column name="VERSION_COMMENT" length="255" jdbc-type="VARCHAR" allows-null="false"/> + </field> + </class> + + </package> +</jdo> + 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/CommitContext.java ---------------------------------------------------------------------- diff --git a/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java new file mode 100644 index 0000000..c74dbf3 --- /dev/null +++ b/sentry-service/sentry-service-server/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java @@ -0,0 +1,42 @@ +/** + * 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.util.UUID; + +/** + * Stores the UUID associated with the server who processed + * a commit and a commit order sequence id. + */ +public class CommitContext { + + private final String serverUUID; + private final long sequenceId; + + public CommitContext(UUID serverUUID, long sequenceId) { + this.serverUUID = serverUUID.toString(); + this.sequenceId = sequenceId; + } + public String getServerUUID() { + return serverUUID; + } + public long getSequenceId() { + return sequenceId; + } +} \ No newline at end of file
