Skip to content

Commit

Permalink
Drift notebook (#720)
Browse files Browse the repository at this point in the history
* First draft of the drift notebook

* Introduce some drift in configs

* first version of commentary

* pass over writing

* narration update

* Notebook name change

* link the notebook

* short term commit for diff view

* Revert "short term commit for diff view"

This reverts commit 2ddb8b9.

* name change, cleaner output, break into sections

* consistent title levels

* remove bgp process; separate helper file

* re-include diff snippet

* sphinx does not like multi-line shell commands
  • Loading branch information
ratulm committed May 12, 2021
1 parent 4156640 commit 82dd83d
Show file tree
Hide file tree
Showing 31 changed files with 5,465 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/source/public_notebooks.rst
Expand Up @@ -12,6 +12,7 @@ Basics

notebooks/linked/getting-started-with-batfish.ipynb
notebooks/linked/validating-configuration-settings.ipynb
notebooks/linked/uncovering-configuration-and-behavior-drift.ipynb

ACLs and firewalls
++++++++++++++++++
Expand Down
1 change: 1 addition & 0 deletions jupyter_notebooks/README.md
Expand Up @@ -4,6 +4,7 @@ The current list of notebooks are:
- **Basics**
- [Getting Started with Batfish](Getting%20started%20with%20Batfish.ipynb) [[video](https://www.youtube.com/watch?v=Ca7kPAtfFqo)] shows how to get started and provides an overview of the capabilities of Batfish.
- [Validating Configuration Settings](Validating%20Configuration%20Settings.ipynb) [[video](https://www.youtube.com/watch?v=qOXRaVs1Uz4)] shows how to validate different types of configuration settings (NTP server, TACACS server, AAA, SNMP, etc...) using Batfish.
- [Uncovering Configuration and Behavior Drift](Uncovering%20Configuration%20and%20Behavior%20Drift.ipynb) shows how to analyze conffiguration settings and network behavior differences between two network snapshots.
- **ACLs and firewalls**
- [Analyzing ACLs and Firewall Rules](Analyzing%20ACLs%20and%20Firewall%20Rules.ipynb) [[video](https://youtu.be/KixQYEDh33s)] shows how to analyze ACLs and firewalls rules using Batfish.
- [Provably Safe ACL and Firewall Changes](Provably%20Safe%20ACL%20and%20Firewall%20Changes.ipynb) [[video](https://www.youtube.com/watch?v=MJYLVL9UOWk)] shows a workflow to ensure changes to ACLs and firewall rules are correct and safe.
Expand Down
1,104 changes: 1,104 additions & 0 deletions jupyter_notebooks/Uncovering Configuration and Behavior Drift.ipynb

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions jupyter_notebooks/drift_helper.py
@@ -0,0 +1,60 @@
"""
Helper functions to print drift information in a readable manner
"""

import pandas as pd

def friendly_name(entity_type, row, key_columns):
"""
Returns a readable string as key, value pairs for an entity in a Pandas row.
"""
return ", ".join([f"{key}={row[key]}" for key in key_columns])


def diff_properties(diff_frame, entity_type, key_columns, properties):
"""
Prints the content of the diff_frame that is the answer of a differential
Batfish question, run for the specified entity_type and properties.
The entity is described using the key_columns parameter.
"""
if len(diff_frame) == 0:
print(f"{entity_type} properties are identical across the two snapshot")
return
snapshot_only = diff_frame[diff_frame["KeyPresence"] == "Only in Snapshot"]
reference_only = diff_frame[diff_frame["KeyPresence"] == "Only in Reference"]
both = diff_frame[diff_frame["KeyPresence"] == "In both"]
if len(snapshot_only) > 0:
print(f"\n{entity_type}s only in snapshot")
for index, row in snapshot_only.iterrows():
print(f" {friendly_name(entity_type, row, key_columns)}")
if len(reference_only) > 0:
print(f"\n{entity_type}s only in reference")
for index, row in reference_only.iterrows():
print(f" {friendly_name(entity_type, row, key_columns)}")
for index,row in both.iterrows():
print("\nDifferences for {}".format(friendly_name(entity_type, row, key_columns)))
for property in properties:
snapshot_setting = row[f"Snapshot_{property}"]
reference_setting = row[f"Reference_{property}"]
if snapshot_setting != reference_setting:
print(f" {property}: {reference_setting} -> {snapshot_setting}")


def diff_frames(snapshot_frame, reference_frame, entity_type):
"""
Prints the differences between snapshot and reference information about entity_type.
"""
combined = pd.merge(snapshot_frame, reference_frame, how="outer", indicator=True)
snapshot_only = combined[combined["_merge"] == "left_only"]
reference_only = combined[combined["_merge"] == "right_only"]
if len(snapshot_only) > 0:
print(f"\n{entity_type}s only in snapshot")
for index, row in snapshot_only.iterrows():
print(" ", friendly_name(entity_type, row, set(combined.columns) - {"_merge"}))
if len(reference_only) > 0:
print(f"\n{entity_type}s only in reference")
for index, row in reference_only.iterrows():
print(" ", friendly_name(entity_type, row, set(combined.columns) - {"_merge"}))
if len(snapshot_only) == 0 and len(reference_only) == 0:
print(f"\n{entity_type}s are identical across the two snapshots")
190 changes: 190 additions & 0 deletions jupyter_notebooks/networks/drift/reference/configs/as1border1.cfg
@@ -0,0 +1,190 @@

!
version 15.2
service timestamps debug datetime msec
service timestamps log datetime msec
!
hostname as1border1
!
boot-start-marker
boot-end-marker
!
!
!
no aaa new-model
no ip icmp rate-limit unreachable
ip cef
!
!
!
!
!
!
no ip domain lookup
ip domain name lab.local
no ipv6 cef
!
!
multilink bundle-name authenticated
!
!
!
!
!
!
!
!
!
ip tcp synwait-time 5
!
!
!
!
!
!
!
!
!
!
!
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
!
interface Ethernet0/0
no ip address
shutdown
duplex auto
!
interface GigabitEthernet0/0
ip address 1.0.1.1 255.255.255.0
media-type gbic
speed 1000
duplex full
negotiation auto
!
interface GigabitEthernet1/0
ip address 10.12.11.1 255.255.255.0
negotiation auto
!
router ospf 1
router-id 1.1.1.1
redistribute connected subnets
passive-interface Loopback0
network 1.0.0.0 0.255.255.255 area 1
!
router bgp 1
bgp router-id 1.1.1.1
bgp log-neighbor-changes
neighbor as1 peer-group
neighbor as1 remote-as 1
neighbor as2 peer-group
neighbor as2 remote-as 2
neighbor as3 peer-group
neighbor as3 remote-as 3
neighbor xanadu peer-group
neighbor xanadu remote-as 555
neighbor bad-ebgp peer-group
neighbor bad-ebgp remote-as 666
neighbor 1.10.1.1 peer-group as1
neighbor 1.10.1.1 update-source Loopback0
neighbor 3.2.2.2 peer-group bad-ebgp
neighbor 5.6.7.8 peer-group xanadu
neighbor 10.12.11.2 peer-group as2
!
address-family ipv4
bgp dampening
bgp additional-paths select all
bgp additional-paths send receive
network 1.0.1.0 mask 255.255.255.0
network 1.0.2.0 mask 255.255.255.0
neighbor as1 send-community
neighbor as1 advertise additional-paths all
neighbor as2 send-community
neighbor as2 route-map as2_to_as1 in
neighbor as2 route-map as1_to_as2 out
neighbor as3 send-community
neighbor as3 route-map as3_to_as1 in
neighbor as3 route-map as1_to_as3 out
neighbor 1.10.1.1 activate
neighbor 3.2.2.2 activate
neighbor 5.6.7.8 activate
neighbor 10.12.11.2 activate
maximum-paths eibgp 5
exit-address-family
!
ip forward-protocol nd
!
ip bgp-community new-format
ip community-list expanded as1_community permit _1:
ip community-list expanded as2_community permit _2:
ip community-list expanded as3_community permit _3:
!
no ip http server
no ip http secure-server
!
!
ip prefix-list default_list seq 5 permit 0.0.0.0/0
!
ip prefix-list inbound_route_filter seq 5 deny 1.0.0.0/8 le 32
ip prefix-list inbound_route_filter seq 10 permit 0.0.0.0/0 le 32
access-list 101 permit ip host 1.0.1.0 host 255.255.255.0
access-list 101 permit ip host 1.0.2.0 host 255.255.255.0
access-list 102 permit ip host 2.0.0.0 host 255.0.0.0
access-list 102 permit ip host 2.128.0.0 host 255.255.0.0
access-list 103 permit ip host 3.0.1.0 host 255.255.255.0
access-list 103 permit ip host 3.0.2.0 host 255.255.255.0
!
route-map as1_to_as2 permit 1
match ip address 101
set metric 50
set community 1:2 additive
!
route-map as1_to_as2 permit 3
match ip address 103
set metric 50
set community 1:2 additive
!
route-map as1_to_as2 permit 5
match ip address prefix-list default_list
set metric 50
set community 1:2 additive
!
route-map as2_to_as1 permit 100
match community as2_community
set local-preference 350
!
route-map as1_to_as3 permit 1
match ip address 101
set metric 50
set community 1:3 additive
!
route-map as1_to_as3 permit 2
match ip address 102
set metric 50
set community 1:3 additive
!
route-map as3_to_as1 permit 100
match community as3_community
set local-preference 350
!
!
!
control-plane
!
!
line con 0
exec-timeout 0 0
privilege level 15
logging synchronous
stopbits 1
line aux 0
exec-timeout 0 0
privilege level 15
logging synchronous
stopbits 1
line vty 0 4
login
!
!
end

0 comments on commit 82dd83d

Please sign in to comment.