diff --git a/repository/src/main/java/org/apache/atlas/discovery/AtlasAuthorization.java b/repository/src/main/java/org/apache/atlas/discovery/AtlasAuthorization.java index 8f264bb327..247901ab86 100644 --- a/repository/src/main/java/org/apache/atlas/discovery/AtlasAuthorization.java +++ b/repository/src/main/java/org/apache/atlas/discovery/AtlasAuthorization.java @@ -196,29 +196,58 @@ private static boolean isAccessAllowed(String entityTypeName, String entityQuali return false; } - public static boolean isRelationshipAccessAllowed(String endOneGuid, String endTwoGuid, String action) throws AtlasBaseException { + public static boolean isRelationshipAccessAllowed(String action, String endOneGuid, String endTwoGuid) throws AtlasBaseException { if (endOneGuid == null || endTwoGuid == null) { return false; } - List> clauses = null; - try { - clauses = getElasticsearchDSLForRelationshipActions(Arrays.asList(action), endOneGuid, endTwoGuid); - } catch (JsonProcessingException e) { - return false; - } - Map dsl = getMap("query", getMap("bool", getMap("should", clauses))); try { + Map dsl = getElasticsearchDSLForRelationshipActions(Arrays.asList(action), endOneGuid, endTwoGuid); ObjectMapper mapper = new ObjectMapper(); String dslString = mapper.writeValueAsString(dsl); - Integer count = getCountFromElasticsearch(dslString); + RestClient restClient = getLowLevelClient(); + AtlasElasticsearchQuery elasticsearchQuery = new AtlasElasticsearchQuery("janusgraph_vertex_index", restClient); + Map elasticsearchResult = null; + elasticsearchResult = elasticsearchQuery.runQueryWithLowLevelClient(dslString); + Integer count = null; + if (elasticsearchResult!=null) { + count = (Integer) elasticsearchResult.get("total"); + } if (count != null && count == 2) { - return true; + List> docs = (List>) elasticsearchResult.get("data"); + List matchedClausesEndOne = new ArrayList<>(); + List matchedClausesEndTwo = new ArrayList<>(); + for (Map doc : docs) { + List matched_queries = (List) doc.get("matched_queries"); + if (matched_queries != null && !matched_queries.isEmpty()) { + Map source = (Map) doc.get("_source"); + String guid = (String) source.get("__guid"); + if (endOneGuid.equals(guid)) { + for (String matched_query : matched_queries) { + if (matched_query.equals("tag-clause")) { + matchedClausesEndOne.add("tag-clause"); + } else if (matched_query.startsWith("end-one-")) { + matchedClausesEndOne.add(matched_query.substring(8)); + } + } + } else { + for (String matched_query : matched_queries) { + if (matched_query.equals("tag-clause")) { + matchedClausesEndTwo.add("tag-clause"); + } else if (matched_query.startsWith("end-two-")) { + matchedClausesEndTwo.add(matched_query.substring(8)); + } + } + } + } + } + if (arrayListContains(matchedClausesEndOne, matchedClausesEndTwo)) { + return true; + } } LOG.info(dslString); } catch (JsonProcessingException e) { - e.printStackTrace(); + return false; } - return false; } @@ -415,24 +444,44 @@ private static Integer getCountFromElasticsearch(String query) throws AtlasBaseE return count; } - public static List> getElasticsearchDSLForRelationshipActions(List actions, String endOneGuid, String endTwoGuid) throws JsonProcessingException { - List> clauses = new ArrayList<>(); + public static Map getElasticsearchDSLForRelationshipActions(List actions, String endOneGuid, String endTwoGuid) throws JsonProcessingException { + List> policiesClauses = new ArrayList<>(); List resourcePolicies = getRelevantPolicies(null, null, "atlas", actions); - List> resourcePoliciesClauses = getDSLForRelationshipResourcePolicies(resourcePolicies, endOneGuid, endTwoGuid); + List> resourcePoliciesClauses = getDSLForRelationshipResourcePolicies(resourcePolicies); List tagPolicies = getRelevantPolicies(null, null, "atlas_tag", actions); - Map tagPoliciesClause = getDSLForTagResourcePolicies(tagPolicies, endOneGuid, endTwoGuid); + List> tagPoliciesClauses = getDSLForRelationshipTagPolicies(tagPolicies); List abacPolicies = getRelevantPolicies(null, null, "atlas_abac", actions); - List> abacPoliciesClauses = getDSLForRelationshipAbacPolicies(abacPolicies, endOneGuid, endTwoGuid); + List> abacPoliciesClauses = getDSLForRelationshipAbacPolicies(abacPolicies); - clauses.addAll(resourcePoliciesClauses); - if (tagPoliciesClause != null) { - clauses.add(tagPoliciesClause); + policiesClauses.addAll(resourcePoliciesClauses); + policiesClauses.addAll(tagPoliciesClauses); + policiesClauses.addAll(abacPoliciesClauses); + + List> clauses = new ArrayList<>(); + + Map policiesBoolClause = new HashMap<>(); + if (policiesClauses.isEmpty()) { + policiesBoolClause.put("must_not", getMap("match_all", new HashMap<>())); + } else { + policiesBoolClause.put("should", policiesClauses); + policiesBoolClause.put("minimum_should_match", 1); } - clauses.addAll(abacPoliciesClauses); + clauses.add(getMap("bool", policiesBoolClause)); - return clauses; + Map entitiesBoolClause = new HashMap<>(); + List> entityClauses = new ArrayList<>(); + entityClauses.add(getMap("term", getMap("__guid", endOneGuid))); + entityClauses.add(getMap("term", getMap("__guid", endTwoGuid))); + entitiesBoolClause.put("should", entityClauses); + entitiesBoolClause.put("minimum_should_match", 1); + clauses.add(getMap("bool", entitiesBoolClause)); + + Map boolClause = new HashMap<>(); + boolClause.put("filter", clauses); + + return getMap("query", getMap("bool", boolClause)); } public static Map getElasticsearchDSL(String persona, String purpose, List actions) { @@ -650,7 +699,7 @@ private static List> getDSLForRelationshipResourcePolicies(L List> endOneFilterList = new ArrayList<>(); if (!endOneEntities.isEmpty() || !endOneEntityTypes.isEmpty()) { - Map endOneDsl = getDSLForResources(endOneEntities, endOneEntityTypes); + Map endOneDsl = getDSLForResources(endOneEntities, endOneEntityTypes, null, null); endOneFilterList.add(endOneDsl); } endOneFilterList.addAll(endOneEntityDsl); @@ -658,7 +707,7 @@ private static List> getDSLForRelationshipResourcePolicies(L List> endTwoFilterList = new ArrayList<>(); if (!endTwoEntities.isEmpty() || !endTwoEntityTypes.isEmpty()) { - Map endTwoDsl = getDSLForResources(endTwoEntities, endTwoEntityTypes); + Map endTwoDsl = getDSLForResources(endTwoEntities, endTwoEntityTypes, null, null); endOneFilterList.add(endTwoDsl); } endTwoFilterList.addAll(endTwoEntityDsl); @@ -673,6 +722,90 @@ private static List> getDSLForRelationshipResourcePolicies(L return shouldClauses; } + private static List> getDSLForRelationshipAbacPolicies(List policies) throws JsonProcessingException { + List> shouldClauses = new ArrayList<>(); + for (RangerPolicy policy : policies) { + if ("RELATIONSHIP".equals(policy.getPolicyResourceCategory())) { + String filterCriteria = policy.getPolicyFilterCriteria(); + ObjectMapper mapper = new ObjectMapper(); + JsonNode filterCriteriaNode = mapper.readTree(filterCriteria); + + List relationshipEnds = new ArrayList<>(); + relationshipEnds.add("end-one"); + relationshipEnds.add("end-two"); + + for (String relationshipEnd : relationshipEnds) { + JsonNode endFilterCriteriaNode = filterCriteriaNode.get(relationshipEnd == "end-one" ? "endOneEntity" : "endTwoEntity"); + JsonNode Dsl = JsonToElasticsearchQuery.convertJsonToQuery(endFilterCriteriaNode, mapper); + String DslBase64 = Base64.getEncoder().encodeToString(Dsl.toString().getBytes()); + String clauseName = relationshipEnd + "-" + policy.getGuid(); + Map wrapperMap = new HashMap<>(); + wrapperMap.put("_name", clauseName); + wrapperMap.put("query", DslBase64); + shouldClauses.add(wrapperMap); + } + } + } + return shouldClauses; + } + + private static List> getDSLForRelationshipTagPolicies(List policies) { + // To reduce the number of clauses + Set allTags = new HashSet<>(); + for (RangerPolicy policy : policies) { + if (!policy.getResources().isEmpty()) { + List tags = policy.getResources().get("tag").getValues(); + if (!tags.isEmpty()) { + allTags.addAll(tags); + } + } + } + + List> clauses = new ArrayList<>(); + + if (!allTags.isEmpty()) { + Map termsMapA = new HashMap<>(); + termsMapA.put("_name", "tag-clause"); + termsMapA.put("terms", getMap("__traitNames", allTags)); + clauses.add(termsMapA); + + Map termsMapB = new HashMap<>(); + termsMapB.put("_name", "tag-clause"); + termsMapB.put("terms", getMap("__propagatedTraitNames", allTags)); + clauses.add(termsMapB); + } + return clauses; + } + + private static List> getDSLForRelationshipResourcePolicies(List policies) { + List> shouldClauses = new ArrayList<>(); + for (RangerPolicy policy : policies) { + if (!policy.getResources().isEmpty() && "RELATIONSHIP".equals(policy.getPolicyResourceCategory())) { + List relationshipEnds = new ArrayList<>(); + relationshipEnds.add("end-one"); + relationshipEnds.add("end-two"); + + for (String relationshipEnd : relationshipEnds) { + String clauseName = relationshipEnd + "-" + policy.getGuid(); + String entityParamName = relationshipEnd + "-entity"; + String entityTypeParamName = relationshipEnd + "-entity-type"; + String entityClassificationParamName = relationshipEnd + "-entity-classification"; + + List entities = policy.getResources().get(entityParamName).getValues(); + List entityTypes = policy.getResources().get(entityTypeParamName).getValues(); + List entityClassifications = policy.getResources().get(entityClassificationParamName).getValues(); + if (entities.contains("*") && entityTypes.contains("*") && entityClassifications.contains("*")) { + shouldClauses.add(getMap("match_all", getMap("_name", clauseName))); + } else { + Map dslForPolicyResources = getDSLForResources(entities, entityTypes, entityClassifications, clauseName); + shouldClauses.add(dslForPolicyResources); + } + } + } + } + return shouldClauses; + } + private static List> getDSLForResourcePolicies(List policies) { // To reduce the number of clauses @@ -697,21 +830,21 @@ private static List> getDSLForResourcePolicies(List dslForPolicyResources = getDSLForResources(entities, entityTypes); + Map dslForPolicyResources = getDSLForResources(entities, entityTypes, null, null); shouldClauses.add(dslForPolicyResources); } } } if (!combinedEntities.isEmpty()) { - shouldClauses.add(getDSLForResources(combinedEntities, new ArrayList<>())); + shouldClauses.add(getDSLForResources(combinedEntities, new ArrayList<>(), null, null)); } if (!combinedEntityTypes.isEmpty()) { - shouldClauses.add(getDSLForResources(new ArrayList<>(), combinedEntityTypes)); + shouldClauses.add(getDSLForResources(new ArrayList<>(), combinedEntityTypes, null, null)); } return shouldClauses; } - private static Map getDSLForResources(List entities, List typeNames){ + private static Map getDSLForResources(List entities, List typeNames, List classifications, String clauseName){ List> shouldClauses = new ArrayList<>(); List termsQualifiedNames = new ArrayList<>(); for (String entity: entities) { @@ -734,8 +867,23 @@ private static Map getDSLForResources(List entities, Lis boolClause.put("minimum_should_match", 1); } - if (!typeNames.isEmpty()) { - boolClause.put("filter", getMap("terms", getMap("__typeName.keyword", typeNames))); + List> filterClauses = new ArrayList<>(); + + if (!typeNames.isEmpty() && !typeNames.contains("*")) { + filterClauses.add(getMap("terms", getMap("__typeName.keyword", typeNames))); + } + + if (classifications != null && !classifications.isEmpty() && !classifications.contains("*")) { + filterClauses.add(getMap("terms", getMap("__traitNames", classifications))); + filterClauses.add(getMap("terms", getMap("__propagatedTraitNames", classifications))); + } + + if (!filterClauses.isEmpty()) { + boolClause.put("filter", filterClauses); + } + + if (clauseName != null) { + boolClause.put("_name", clauseName); } return getMap("bool", boolClause);