Skip to content

Commit

Permalink
Merge pull request #575 from nautobot/feat-meraki_integration
Browse files Browse the repository at this point in the history
Add Meraki Integration
  • Loading branch information
jdrew82 authored Oct 21, 2024
2 parents de906f6 + ea4b02e commit 3bcf566
Show file tree
Hide file tree
Showing 70 changed files with 6,919 additions and 599 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ This Nautobot application framework includes the following integrations:
- Infoblox
- IPFabric
- Itential
- Cisco Meraki
- ServiceNow

Read more about integrations [here](https://docs.nautobot.com/projects/ssot/en/latest/user/integrations). To enable and configure integrations follow the instructions from [the install guide](https://docs.nautobot.com/projects/ssot/en/latest/admin/install/#integrations-configuration).
Expand All @@ -42,16 +43,19 @@ Read more about integrations [here](https://docs.nautobot.com/projects/ssot/en/l
---

The dashboard view of the app.

![Dashboard View](https://raw.githubusercontent.com/nautobot/nautobot-app-ssot/develop/docs/images/dashboard_initial.png)

---

The detailed view of the example data source that is prepackaged within this app.

![Data Source Detail View](https://raw.githubusercontent.com/nautobot/nautobot-app-ssot/develop/docs/images/data_source_detail.png)

---

The detailed view of an executed sync.

![Sync Detail View](https://raw.githubusercontent.com/nautobot/nautobot-app-ssot/develop/docs/images/sync_detail.png)

---
Expand Down Expand Up @@ -83,6 +87,7 @@ The SSoT framework includes a number of integrations with external Systems of Re
* Cisco DNA Center
* Infoblox
* Itential
* Cisco Meraki
* ServiceNow

> Note that the Arista CloudVision integration is currently incompatible with the [Arista Labs](https://labs.arista.com/) environment due to a TLS issue. It has been confirmed to work in on-prem environments previously.
Expand Down
1 change: 1 addition & 0 deletions changes/574.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added integration with Cisco Meraki.
1 change: 1 addition & 0 deletions changes/574.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Updated DNA Center Job to use SSoT verify_controller_managed_device_group utility function so code is more DRY.
1 change: 1 addition & 0 deletions changes/574.documentation
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added documentation for Meraki integration.
1 change: 1 addition & 0 deletions changes/574.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed the ACI integration's retrieval of Controller Managed Device Group name that was breaking ACI adapter.
3 changes: 3 additions & 0 deletions development/creds.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,6 @@ IPFABRIC_API_TOKEN=secrettoken
NAUTOBOT_SSOT_ENABLE_BOOTSTRAP="False"
NAUTOBOT_BOOTSTRAP_SSOT_ENVIRONMENT_BRANCH=develop
NAUTOBOT_BOOTSTRAP_SSOT_LOAD_SOURCE=file # or git

MERAKI_ORG_ID='123456'
MERAKI_TOKEN='vtx01710aa0fn452740055y1hs60ns8c107ho168'
2 changes: 2 additions & 0 deletions development/development.env
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ NAUTOBOT_SSOT_INFOBLOX_USERNAME="changeme"
NAUTOBOT_SSOT_INFOBLOX_VERIFY_SSL="True"
# NAUTOBOT_SSOT_INFOBLOX_WAPI_VERSION=""

NAUTOBOT_SSOT_ENABLE_MERAKI="False"

NAUTOBOT_SSOT_ENABLE_SERVICENOW="False"
SERVICENOW_INSTANCE=""
SERVICENOW_USERNAME=""
Expand Down
1 change: 1 addition & 0 deletions development/nautobot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@
"enable_infoblox": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_INFOBLOX")),
"enable_ipfabric": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_IPFABRIC")),
"enable_itential": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_ITENTIAL")),
"enable_meraki": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_MERAKI")),
"enable_servicenow": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_SERVICENOW")),
"hide_example_jobs": is_truthy(os.getenv("NAUTOBOT_SSOT_HIDE_EXAMPLE_JOBS")),
"device42_defaults": {
Expand Down
1 change: 1 addition & 0 deletions docs/admin/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,5 @@ Set up each integration using the specific guides:
- [Infoblox](./integrations/infoblox_setup.md)
- [IPFabric](./integrations/ipfabric_setup.md)
- [Itential](./integrations/itential_setup.md)
- [Cisco Meraki](./integrations/meraki_setup.md)
- [ServiceNow](./integrations/servicenow_setup.md)
1 change: 1 addition & 0 deletions docs/admin/integrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ This Nautobot app supports the following integrations:
- [Infoblox](./infoblox_setup.md)
- [IPFabric](./ipfabric_setup.md)
- [Itential](./itential_setup.md)
- [Cisco Meraki](./meraki_setup.md)
- [ServiceNow](./servicenow_setup.md)
25 changes: 25 additions & 0 deletions docs/admin/integrations/meraki_setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Cisco Meraki Integration Setup

This guide will walk you through steps to set up Cisco Meraki integration with the `nautobot_ssot` app.

## Prerequisites

Before configuring the integration, please ensure, that `nautobot-ssot` app was [installed with Cisco Meraki integration extra dependencies](../install.md#install-guide).

```shell
pip install nautobot-ssot[meraki]
```

## Configuration

Connecting to a Meraki instance is handled through the Nautobot [Controller](https://docs.nautobot.com/projects/core/en/stable/development/core/controllers/) object. There is an expectation that you will create an [ExternalIntegration](https://docs.nautobot.com/projects/core/en/stable/user-guide/platform-functionality/externalintegration/) with the requisite connection information for your Meraki dashboard attached to that Controller object. All imported Devices will be associated to a [ControllerManagedDeviceGroup](https://docs.nautobot.com/projects/core/en/stable/user-guide/core-data-model/dcim/controllermanageddevicegroup/) that is found or created during each Job run. It will update the group name to be "<Controller name\> Managed Devices" if it exists. When running the Sync Job you will specify which Meraki Controller instance you wish to synchronize with along with other settings for the synchronization.

Below is an example snippet from `nautobot_config.py` that demonstrates how to enable the Meraki integration:

```python
PLUGINS_CONFIG = {
"nautobot_ssot": {
"enable_meraki": is_truthy(os.getenv("NAUTOBOT_SSOT_ENABLE_MERAKI", "true")),
}
}
```
Binary file added docs/images/meraki_controller.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_dashboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_detail-view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_enabled_job.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_external_integration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_job_form.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_job_list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_job_settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_jobresult.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_network_loctype.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_org_id_secret.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_secretsgroup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/meraki_token_secret.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/user/integrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ This Nautobot app supports the following integrations:
- [Infoblox](./infoblox.md)
- [IPFabric](./ipfabric.md)
- [Itential](./itential.md)
- [Cisco Meraki](./meraki.md)
- [ServiceNow](./servicenow.md)
87 changes: 87 additions & 0 deletions docs/user/integrations/meraki.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Cisco Meraki SSoT Integration

The Cisco Meraki SSoT integration is built as part of the [Nautobot Single Source of Truth (SSoT)](https://github.com/nautobot/nautobot-app-ssot) app. The SSoT app enables Nautobot to be the aggregation point for data coming from multiple systems of record (SoR).

From Cisco Meraki into Nautobot, it synchronizes the following objects:

| Meraki | Nautobot |
| ----------------------- | ---------------------------- |
| Networks | Location* |
| Devices | Devices |
| Hardwares | DeviceTypes |
| OSVersions | SoftwareVersions |
| Ports | Interfaces |
| Prefixes | Prefixes |
| IP Addresses | IP Addresses |

`*` As of SSoT 3.2.0 the LocationType for Networks can be defined in the Job form.

## Usage

Once the app is installed and configured, you will be able to perform an inventory ingestion from Meraki into Nautobot. From the Nautobot SSoT Dashboard view (`/plugins/ssot/`), Meraki will show as a Data Source.

![Dashboard View](../../images/meraki_dashboard.png)

From the Dashboard, you can also view more information about the App by clicking on the `Meraki to Nautobot` link and see the Detail view. This view will show the mappings of Meraki objects to Nautobot objects, the sync history, and other configuration details for the App:

![Detail View](../../images/meraki_detail-view.png)

In order to utilize this integration you must first enable the Job. You can find the available installed Jobs under Jobs -> Jobs:

![Job List](../../images/meraki_job_list.png)

To enable the Job you must click on the orange pencil icon to the right of the `Meraki to Nautobot` Job. You will be presented with the settings for the Job as shown below:

![Job Settings](../../images/meraki_job_settings.png)

You'll need to check the `Enabled` checkbox and then the `Update` button at the bottom of the page. You will then see that the play button next to the Job changes to blue and becomes functional, linking to the Job form.

![Enabled Job](../../images/meraki_enabled_job.png)

Once the Job is enabled, you'll need to manually create a few objects in Nautobot to use with the Job. First, you'll need to create a Secret that contains your organization ID and token for authenticating to your desired Meraki instance:

![Org ID Secret](../../images/meraki_org_id_secret.png)

![Token Secret](../../images/meraki_token_secret.png)

Once the required Secrets are created, you'll need to create a SecretsGroup that pairs them together and defines the Access Type of HTTP(S) like shown below:

![DNAC SecretsGroup](../../images/meraki_secretsgroup.png)

With the SecretsGroup defined containing your instance credentials you'll then need to create an ExternalIntegration object to store the information about the Meraki instance you wish to synchronize with.

![DNAC ExternalIntegration](../../images/meraki_external_integration.png)

> The only required portions are the Name, Remote URL, Verify SSL, and Secrets Group.
The final step before running the Job is to create a Controller that references the ExternalIntegration that you just created. You can attach a `Managed Device Group` to the Controller for all imported Devices to be placed in. If you don't create a Managed Device Group, one will be created automatically and associated to the specified Controller with the name of `<Controller name> Managed Devices`.

![DNAC Controller](../../images/meraki_controller.png)

> You can utilize multiple Meraki Controllers with this integration as long as you specify a unique Tenant per Controller. The failure to use differing Tenants will have the Devices, Prefixes, and IPAddresses potentially removed if they are non-existent on the additional Controller. Locations should remain unaffected.
With those configured, you will then need to define a LocationType to use for the imported Networks. With those created, you can run the Job to start the synchronization:

![Job Form](../../images/meraki_job_form.png)

If you wish to just test the synchronization but not have any data created in Nautobot you'll want to select the `Dryrun` toggle. Clicking the `Debug` toggle will enable more verbose logging to inform you of what is occuring behind the scenes. After those toggles there are also dropdowns that allow you to specify the Meraki Controller to synchronize with and to define the LocationType to use for the imported Networks from Meraki. In addition, there are also some optional settings on the Job form:

- Should the LocationType that you specify for the imported Networks require a parent Location to be assigned, you can define this parent one of two ways:

1. The Parent Location field allows you to define a singular Location that will be assigned as the parent for all imported Network Locations.

2. The Location Mapping field allows you to define a dictionary of Location mappings. This feature is intended for specifying parent Locations for the Network Locations in Meraki. This is useful if this information is missing from Meraki but required for Nautobot or to allow you to change the information as it's imported to match information from another System of Record. The expected pattern for this field is `{"<Location Name>": {"parent": "<Parent location Name>"}}`.

In addition, there are two methods provided to assign Roles to your imported Devices:

1. The Hostname Mapping field allows you to specify list of tuples containing a regular expression pattern to match against Device hostnames and the Role to assign if matched. Ex: [(".*FW.*", "Firewall")]

2. The DeviceType Mapping field allows you to specify a list of tuples containing a string to match against the Device model and the Role to assign when matched. The string to match can simply be the series letters, ie MX for firewalls, or explicit models like MX84. Ex: [("MS", "Switch")]

- Finally there is an option to specify a Tenant to be assigned to the imported Devices, Prefixes, and IPAddreses. This is handy for cases where you have multiple Meraki instances that are used by differing business units.

Running this Job will redirect you to a `Nautobot Job Result` view.

![JobResult View](../../images/meraki_jobresult.png)

Once the Job has finished you can click on the `SSoT Sync Details` button at the top right of the Job Result page to see detailed information about the data that was synchronized from Meraki and the outcome of the sync Job.
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ nav:
- Infoblox: "user/integrations/infoblox.md"
- IPFabric: "user/integrations/ipfabric.md"
- Itential: "user/integrations/itential.md"
- Cisco Meraki: "user/integrations/meraki.md"
- ServiceNow: "user/integrations/servicenow.md"
- Modeling: "user/modeling.md"
- Performance: "user/performance.md"
Expand All @@ -133,6 +134,7 @@ nav:
- Infoblox: "admin/integrations/infoblox_setup.md"
- IPFabric: "admin/integrations/ipfabric_setup.md"
- Itential: "admin/integrations/itential_setup.md"
- Cisco Meraki: "admin/integrations/meraki_setup.md"
- ServiceNow: "admin/integrations/servicenow_setup.md"
- Upgrade: "admin/upgrade.md"
- Uninstall: "admin/uninstall.md"
Expand Down
2 changes: 2 additions & 0 deletions nautobot_ssot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"nautobot_ssot_dna_center",
"nautobot_ssot_infoblox",
"nautobot_ssot_ipfabric",
"nautobot_ssot_itential",
"nautobot_ssot_meraki",
"nautobot_ssot_servicenow",
]

Expand Down
4 changes: 2 additions & 2 deletions nautobot_ssot/integrations/aci/diffsync/adapters/aci.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ def load_devices(self):
site=self.site,
site_tag=self.site,
controller_group=(
self.job.apic.controller_managed_device_groups.name
if self.job.apic.controller_managed_device_groups
self.job.apic.controller_managed_device_groups.first().name
if self.job.apic.controller_managed_device_groups.count() != 0
else ""
),
)
Expand Down
11 changes: 3 additions & 8 deletions nautobot_ssot/integrations/dna_center/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
from django.urls import reverse
from nautobot.apps.jobs import BooleanVar, JSONVar, ObjectVar
from nautobot.core.celery import register_jobs
from nautobot.dcim.models import Controller, ControllerManagedDeviceGroup, LocationType
from nautobot.dcim.models import Controller, LocationType
from nautobot.extras.choices import SecretsGroupAccessTypeChoices, SecretsGroupSecretTypeChoices
from nautobot.tenancy.models import Tenant

from nautobot_ssot.exceptions import ConfigurationError
from nautobot_ssot.integrations.dna_center.diffsync.adapters import dna_center, nautobot
from nautobot_ssot.integrations.dna_center.utils.dna_center import DnaCenterClient
from nautobot_ssot.jobs.base import DataMapping, DataSource
from nautobot_ssot.utils import verify_controller_managed_device_group

name = "DNA Center SSoT" # pylint: disable=invalid-name

Expand Down Expand Up @@ -107,16 +108,10 @@ def data_mappings(cls):
DataMapping("IP Addresses", None, "IP Addresses", reverse("ipam:ipaddress_list")),
)

def get_controller_group(self):
"""Method to get or create ControllerManagedDeviceGroup for imported Devices."""
self.controller_group = ControllerManagedDeviceGroup.objects.update_or_create(
controller=self.dnac, defaults={"name": f"{self.dnac.name} Managed Devices"}
)[0]

def load_source_adapter(self):
"""Load data from DNA Center into DiffSync models."""
self.logger.info(f"Loading data from {self.dnac.name}")
self.get_controller_group()
verify_controller_managed_device_group(controller=self.dnac)
_sg = self.dnac.external_integration.secrets_group
username = _sg.get_secret_value(
access_type=SecretsGroupAccessTypeChoices.TYPE_HTTP,
Expand Down
1 change: 1 addition & 0 deletions nautobot_ssot/integrations/meraki/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Base module for Meraki integration."""
1 change: 1 addition & 0 deletions nautobot_ssot/integrations/meraki/diffsync/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""DiffSync models and adapters for Meraki SSoT."""
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Adapter classes for loading DiffSyncModels with data from Meraki or Nautobot."""
Loading

0 comments on commit 3bcf566

Please sign in to comment.