Search in sources :

Example 1 with AclReachabilityQuerySynthesizer

use of org.batfish.z3.AclReachabilityQuerySynthesizer in project batfish by batfish.

the class Batfish method answerAclReachability.

@Override
public AnswerElement answerAclReachability(String aclNameRegexStr, NamedStructureEquivalenceSets<?> aclEqSets) {
    AclLinesAnswerElement answerElement = new AclLinesAnswerElement();
    Pattern aclNameRegex;
    try {
        aclNameRegex = Pattern.compile(aclNameRegexStr);
    } catch (PatternSyntaxException e) {
        throw new BatfishException("Supplied regex for nodes is not a valid java regex: \"" + aclNameRegexStr + "\"", e);
    }
    Map<String, Configuration> configurations = loadConfigurations();
    List<NodSatJob<AclLine>> jobs = new ArrayList<>();
    for (Entry<String, ?> e : aclEqSets.getSameNamedStructures().entrySet()) {
        String aclName = e.getKey();
        if (!aclNameRegex.matcher(aclName).matches()) {
            continue;
        }
        // operator error
        if (aclName.contains("~ZONE_INTERFACE_FILTER~") || aclName.contains("~INBOUND_ZONE_FILTER~")) {
            continue;
        }
        Set<?> s = (Set<?>) e.getValue();
        for (Object o : s) {
            NamedStructureEquivalenceSet<?> aclEqSet = (NamedStructureEquivalenceSet<?>) o;
            String hostname = aclEqSet.getRepresentativeElement();
            SortedSet<String> eqClassNodes = aclEqSet.getNodes();
            answerElement.addEquivalenceClass(aclName, hostname, eqClassNodes);
            Configuration c = configurations.get(hostname);
            IpAccessList acl = c.getIpAccessLists().get(aclName);
            int numLines = acl.getLines().size();
            if (numLines == 0) {
                _logger.redflag("RED_FLAG: Acl \"" + hostname + ":" + aclName + "\" contains no lines\n");
                continue;
            }
            AclReachabilityQuerySynthesizer query = new AclReachabilityQuerySynthesizer(hostname, aclName, numLines);
            Synthesizer aclSynthesizer = synthesizeAcls(Collections.singletonMap(hostname, c));
            NodSatJob<AclLine> job = new NodSatJob<>(_settings, aclSynthesizer, query);
            jobs.add(job);
        }
    }
    Map<AclLine, Boolean> output = new TreeMap<>();
    computeNodSatOutput(jobs, output);
    // rearrange output for next step
    Map<String, Map<String, List<AclLine>>> arrangedAclLines = new TreeMap<>();
    for (Entry<AclLine, Boolean> e : output.entrySet()) {
        AclLine line = e.getKey();
        String hostname = line.getHostname();
        Map<String, List<AclLine>> byAclName = arrangedAclLines.computeIfAbsent(hostname, k -> new TreeMap<>());
        String aclName = line.getAclName();
        List<AclLine> aclLines = byAclName.computeIfAbsent(aclName, k -> new ArrayList<>());
        aclLines.add(line);
    }
    // now get earliest more general lines
    List<NodFirstUnsatJob<AclLine, Integer>> step2Jobs = new ArrayList<>();
    for (Entry<String, Map<String, List<AclLine>>> e : arrangedAclLines.entrySet()) {
        String hostname = e.getKey();
        Configuration c = configurations.get(hostname);
        Synthesizer aclSynthesizer = synthesizeAcls(Collections.singletonMap(hostname, c));
        Map<String, List<AclLine>> byAclName = e.getValue();
        for (Entry<String, List<AclLine>> e2 : byAclName.entrySet()) {
            String aclName = e2.getKey();
            IpAccessList ipAccessList = c.getIpAccessLists().get(aclName);
            List<AclLine> lines = e2.getValue();
            for (int i = 0; i < lines.size(); i++) {
                AclLine line = lines.get(i);
                boolean reachable = output.get(line);
                if (!reachable) {
                    List<AclLine> toCheck = new ArrayList<>();
                    for (int j = 0; j < i; j++) {
                        AclLine earlierLine = lines.get(j);
                        boolean earlierIsReachable = output.get(earlierLine);
                        if (earlierIsReachable) {
                            toCheck.add(earlierLine);
                        }
                    }
                    EarliestMoreGeneralReachableLineQuerySynthesizer query = new EarliestMoreGeneralReachableLineQuerySynthesizer(line, toCheck, ipAccessList);
                    NodFirstUnsatJob<AclLine, Integer> job = new NodFirstUnsatJob<>(_settings, aclSynthesizer, query);
                    step2Jobs.add(job);
                }
            }
        }
    }
    Map<AclLine, Integer> step2Output = new TreeMap<>();
    computeNodFirstUnsatOutput(step2Jobs, step2Output);
    for (AclLine line : output.keySet()) {
        Integer earliestMoreGeneralReachableLine = step2Output.get(line);
        line.setEarliestMoreGeneralReachableLine(earliestMoreGeneralReachableLine);
    }
    Set<Pair<String, String>> aclsWithUnreachableLines = new TreeSet<>();
    Set<Pair<String, String>> allAcls = new TreeSet<>();
    int numUnreachableLines = 0;
    int numLines = output.entrySet().size();
    for (Entry<AclLine, Boolean> e : output.entrySet()) {
        AclLine aclLine = e.getKey();
        boolean sat = e.getValue();
        String hostname = aclLine.getHostname();
        String aclName = aclLine.getAclName();
        Pair<String, String> qualifiedAclName = new Pair<>(hostname, aclName);
        allAcls.add(qualifiedAclName);
        if (!sat) {
            numUnreachableLines++;
            aclsWithUnreachableLines.add(qualifiedAclName);
        }
    }
    for (Entry<AclLine, Boolean> e : output.entrySet()) {
        AclLine aclLine = e.getKey();
        int index = aclLine.getLine();
        boolean sat = e.getValue();
        String hostname = aclLine.getHostname();
        String aclName = aclLine.getAclName();
        Pair<String, String> qualifiedAclName = new Pair<>(hostname, aclName);
        IpAccessList ipAccessList = configurations.get(hostname).getIpAccessLists().get(aclName);
        IpAccessListLine ipAccessListLine = ipAccessList.getLines().get(index);
        AclReachabilityEntry line = new AclReachabilityEntry(index, ipAccessListLine.getName());
        if (aclsWithUnreachableLines.contains(qualifiedAclName)) {
            if (sat) {
                _logger.debugf("%s:%s:%d:'%s' is REACHABLE\n", hostname, aclName, line.getIndex(), line.getName());
                answerElement.addReachableLine(hostname, ipAccessList, line);
            } else {
                _logger.debugf("%s:%s:%d:'%s' is UNREACHABLE\n\t%s\n", hostname, aclName, line.getIndex(), line.getName(), ipAccessListLine.toString());
                Integer earliestMoreGeneralLineIndex = aclLine.getEarliestMoreGeneralReachableLine();
                if (earliestMoreGeneralLineIndex != null) {
                    IpAccessListLine earliestMoreGeneralLine = ipAccessList.getLines().get(earliestMoreGeneralLineIndex);
                    line.setEarliestMoreGeneralLineIndex(earliestMoreGeneralLineIndex);
                    line.setEarliestMoreGeneralLineName(earliestMoreGeneralLine.getName());
                    if (!earliestMoreGeneralLine.getAction().equals(ipAccessListLine.getAction())) {
                        line.setDifferentAction(true);
                    }
                }
                answerElement.addUnreachableLine(hostname, ipAccessList, line);
                aclsWithUnreachableLines.add(qualifiedAclName);
            }
        } else {
            answerElement.addReachableLine(hostname, ipAccessList, line);
        }
    }
    for (Pair<String, String> qualfiedAcl : aclsWithUnreachableLines) {
        String hostname = qualfiedAcl.getFirst();
        String aclName = qualfiedAcl.getSecond();
        _logger.debugf("%s:%s has at least 1 unreachable line\n", hostname, aclName);
    }
    int numAclsWithUnreachableLines = aclsWithUnreachableLines.size();
    int numAcls = allAcls.size();
    double percentUnreachableAcls = 100d * numAclsWithUnreachableLines / numAcls;
    double percentUnreachableLines = 100d * numUnreachableLines / numLines;
    _logger.debugf("SUMMARY:\n");
    _logger.debugf("\t%d/%d (%.1f%%) acls have unreachable lines\n", numAclsWithUnreachableLines, numAcls, percentUnreachableAcls);
    _logger.debugf("\t%d/%d (%.1f%%) acl lines are unreachable\n", numUnreachableLines, numLines, percentUnreachableLines);
    return answerElement;
}
Also used : NamedStructureEquivalenceSet(org.batfish.datamodel.collections.NamedStructureEquivalenceSet) HostConfiguration(org.batfish.representation.host.HostConfiguration) Configuration(org.batfish.datamodel.Configuration) ImmutableConfiguration(org.apache.commons.configuration2.ImmutableConfiguration) AwsConfiguration(org.batfish.representation.aws.AwsConfiguration) IptablesVendorConfiguration(org.batfish.representation.iptables.IptablesVendorConfiguration) VendorConfiguration(org.batfish.vendor.VendorConfiguration) AclLine(org.batfish.z3.AclLine) NodFirstUnsatJob(org.batfish.z3.NodFirstUnsatJob) ArrayList(java.util.ArrayList) TreeSet(java.util.TreeSet) IpAccessList(org.batfish.datamodel.IpAccessList) ImmutableList(com.google.common.collect.ImmutableList) ArrayList(java.util.ArrayList) List(java.util.List) IpAccessListLine(org.batfish.datamodel.IpAccessListLine) CleanBatfishException(org.batfish.common.CleanBatfishException) BatfishException(org.batfish.common.BatfishException) AclLinesAnswerElement(org.batfish.datamodel.answers.AclLinesAnswerElement) AclReachabilityEntry(org.batfish.datamodel.answers.AclLinesAnswerElement.AclReachabilityEntry) GenericConfigObject(org.batfish.datamodel.GenericConfigObject) JSONObject(org.codehaus.jettison.json.JSONObject) IpAccessList(org.batfish.datamodel.IpAccessList) Map(java.util.Map) TreeMap(java.util.TreeMap) Collectors.toMap(java.util.stream.Collectors.toMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) NavigableMap(java.util.NavigableMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) ImmutableMap(com.google.common.collect.ImmutableMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) TreeMultiSet(org.batfish.datamodel.collections.TreeMultiSet) ImmutableSortedSet(com.google.common.collect.ImmutableSortedSet) SortedSet(java.util.SortedSet) ImmutableSet(com.google.common.collect.ImmutableSet) HashSet(java.util.HashSet) NamedStructureEquivalenceSet(org.batfish.datamodel.collections.NamedStructureEquivalenceSet) Set(java.util.Set) TreeSet(java.util.TreeSet) LinkedHashSet(java.util.LinkedHashSet) MultiSet(org.batfish.datamodel.collections.MultiSet) AclReachabilityQuerySynthesizer(org.batfish.z3.AclReachabilityQuerySynthesizer) EarliestMoreGeneralReachableLineQuerySynthesizer(org.batfish.z3.EarliestMoreGeneralReachableLineQuerySynthesizer) ReachabilityQuerySynthesizer(org.batfish.z3.ReachabilityQuerySynthesizer) QuerySynthesizer(org.batfish.z3.QuerySynthesizer) AclReachabilityQuerySynthesizer(org.batfish.z3.AclReachabilityQuerySynthesizer) BlacklistDstIpQuerySynthesizer(org.batfish.z3.BlacklistDstIpQuerySynthesizer) StandardReachabilityQuerySynthesizer(org.batfish.z3.StandardReachabilityQuerySynthesizer) EarliestMoreGeneralReachableLineQuerySynthesizer(org.batfish.z3.EarliestMoreGeneralReachableLineQuerySynthesizer) ReachEdgeQuerySynthesizer(org.batfish.z3.ReachEdgeQuerySynthesizer) Synthesizer(org.batfish.z3.Synthesizer) MultipathInconsistencyQuerySynthesizer(org.batfish.z3.MultipathInconsistencyQuerySynthesizer) PatternSyntaxException(java.util.regex.PatternSyntaxException) Pair(org.batfish.common.Pair) NodeInterfacePair(org.batfish.datamodel.collections.NodeInterfacePair) NodSatJob(org.batfish.z3.NodSatJob) Pattern(java.util.regex.Pattern) TreeMap(java.util.TreeMap) AtomicInteger(java.util.concurrent.atomic.AtomicInteger)

Aggregations

ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 ImmutableSortedMap (com.google.common.collect.ImmutableSortedMap)1 ImmutableSortedSet (com.google.common.collect.ImmutableSortedSet)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 Map (java.util.Map)1 NavigableMap (java.util.NavigableMap)1 Set (java.util.Set)1 SortedMap (java.util.SortedMap)1 SortedSet (java.util.SortedSet)1 TreeMap (java.util.TreeMap)1 TreeSet (java.util.TreeSet)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1