1) Compatibility
1) This tool has been tested with the following versions of Cisco ISE:
1) See this article for Cisco Meraki requirements.
1) Current Unit Tests Used before each Commit:
1) Enable API access in your Meraki dashboard organization and obtain an API key (instructions) 2) Keep your API key safe and secure, as it is similar to a password for your dashboard. You will supply this API key to Adaptive Policy Sync later.
1) Enable API (ERS) access in Cisco ISE 2) Create an ERS Admin user account for ISE ERS access.
1) If you plan to integrate with pxGrid for ISE Push-Notifications, you will need to create a new pxGrid Certificate for your application.
mkdir $HOME/adaptivepolicy
docker pull joshand/adaptive-policy-ise-sync:latest
docker run -it -p 8000:8020 \
--restart unless-stopped \
--name=Adaptive-Policy-ISE-Sync \
-e DJANGO_SUPERUSER_USERNAME=admin \
-e DJANGO_SUPERUSER_PASSWORD=password \
-e DJANGO_SUPERUSER_EMAIL=admin@example.com \
-e DJANGO_SUPERUSER_APIKEY=1234567890abcdefghijklmnopqrstuvwxyz1234 \
-v $HOME/adaptivepolicy:/opt/app/adaptive_policy_sync/config \
joshand/adaptive-policy-ise-sync:latest
git clone https://github.com/meraki/adaptive-policy-ise-sync.git
cd adaptive-policy-ise-sync/
virtualenv venv --python=python3
source venv/bin/activate
pip install -r requirements.txt
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
Username (leave blank to use 'username'): admin
Email address: email@domain.com
Password:
Password (again):
Superuser created successfully.
python manage.py drf_create_token admin
Generated token 1234567890abcdefghijklmnopqrstuvwxyz1234 for user admin
python manage.py runscript tasks &
python manage.py runserver 8000
Access your Adaptive Policy Sync Instance using the port that you've configured (http://127.0.0.1:8000 if you used the examples above)
Click the "Start Now" button to begin the configuration process.
Enter the IP Address or Fully Qualified Domain Name of your ISE Server, the username and password of the user that you created for ERS access via the instructions above. If you will be utilizing pxGrid integration, check the box "Enable pxGrid Integration". Click Next.
If you chose to configure pxGrid Integration, you will need to upload the Certificate that you generated in ISE for your client. Give it a description, then click the Browse... button.
Navigate to the location that you downloaded the certificate ZIP file to, select the file, then click Open. When you return to the previous screen, click the Next button.
Enter the IP Address or Fully Qualified Domain Name of your ISE Server (that has pxGrid enabled), enter the Client Name that you configured in ISE. Then select the .cer and .key files cooresponding to that client. Enter the password that you set for your client. Then, choose the .cer file for the ISE node that you specified as the pxGrid server. Click Next.
Generally, you will not need to change the Meraki Dashboard API URL. Enter your Dashboard API Key, then Tab to the next field or click somewhere in the open window. Adaptive Policy Sync will generate a list of Organiations that your API key has access to and display them in the dropdown list. Select the Organization that you will be using for Adaptive Policy. Then, click Next.
Now, choose the authoritative source for Policy. This will be used to determine which source to use if there are configuration conflicts, and it will control which policy source will be used if policy objects are deleted. Set the Manual Synchronization Interval, ensure that the "Enable Synchronization" box is checked, then click Finish.
You will be taken to the Adaptive Policy Sync Landing page. In the left navigation pane, navigate to Status -> SGTs.
Select the checkbox for all of the SGTs you wish to sync. When complete, click the "Save" button.
1) Add your Dashboard Organization to Adaptive Policy Sync using the following API call. You will need to provide your Organization ID that you would like to connect to Adapative Policy sync.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST --data-binary '{"orgid": "1234567890"}' http://127.0.0.1:8000/api/v0/organization/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/organization/11112222-3333-4444-5555-666677778888/","orgid":"1234567890","force_rebuild":false,"skip_sync":false,"last_update":"2020-10-16T23:17:13.525068Z","last_sync":null}
2) Add your Meraki Dashboard Instance to Adaptive Policy Sync using the following API call. You will need to provide your Meraki Dashboard API key that you would like to connect to Adapative Policy sync.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST --data-binary '{"description": "My Meraki Dashboard","apikey": "1234567890abcdefghijklmnopqrstuvwxyz1234","webhook_enable": true,"webhook_ngrok": true,"webhook_url": "","organization":["11112222-3333-4444-5555-666677778888"]}' http://127.0.0.1:8000/api/v0/dashboard/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/dashboard/11112222-3333-4444-5555-666677778888/","description":"My Meraki Dashboard","baseurl":"https://api.meraki.com/api/v1","apikey":"1234567890abcdefghijklmnopqrstuvwxyz1234","organization":["11112222-3333-4444-5555-666677778888"],"force_rebuild":false,"last_update":"2020-10-16T23:19:06.267462Z","last_sync":null,"webhook_enable":true,"webhook_ngrok":true,"webhook_url":""}
1) Add your Cisco ISE Server to Adaptive Policy Sync using the following API call. You will need to provide your ISE ERS Admin username and password.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST --data-binary '{"description": "My ISE Server","ipaddress": "10.1.2.3","username": "ersadmin","password": "erspassword","pxgrid_enable": false'} http://127.0.0.1:8000/api/v0/iseserver/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/iseserver/11112222-3333-4444-5555-666677778888/","description":"My ISE Server","ipaddress":"10.1.2.3","username":"ersadmin","password":"erspassword","force_rebuild":false,"skip_sync":false,"last_update":"2020-04-14T21:49:55.635413Z","last_sync":null,"pxgrid_enable":false,"pxgrid_ip":null,"pxgrid_cliname":null,"pxgrid_clicert":null,"pxgrid_clikey":null,"pxgrid_clipw":null,"pxgrid_isecert":null}
1) Upload the certificate ZIP file to Adaptive Policy Sync using the following API call. The description field is arbritrary and can be set to anything you like.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -F "description=isecerts" -F "file=@1582839825923_cert.zip" -X POST http://127.0.0.1:8000/api/v0/uploadzip/
2) View a list of all files that were part of the ZIP file in order to get their ID numbers using the following API call. To make it easier to read, you will want to pipe the output through a JSON formatter such as 'jq', 'python -mjson.tool', 'json_pp', or 'jsonpretty' to name a few.
curl --silent -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -X GET http://127.0.0.1:8000/api/v0/upload/ | jq
``` json
{
"count": 6,
"next": null,
"previous": null,
"results": [
{
"id": "11112222-3333-4444-5555-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-3333-4444-5555-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/CertificateServicesEndpointSubCA-iseserver_.cer",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/CertificateServicesEndpointSubCA-iseserver_.cer",
"uploaded_at": "2020-04-14T21:39:23.179183Z"
},
{
"id": "11112222-3333-5555-4444-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-3333-4444-5555-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/CertificateServicesNodeCA-iseserver_.cer",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/CertificateServicesNodeCA-iseserver_.cer",
"uploaded_at": "2020-04-14T21:39:23.181974Z"
},
{
"id": "11112222-4444-3333-5555-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-4444-3333-5555-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/CertificateServicesRootCA-iseserver_.cer",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/CertificateServicesRootCA-iseserver_.cer",
"uploaded_at": "2020-04-14T21:39:23.186234Z"
},
{
"id": "11112222-4444-5555-3333-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-4444-5555-3333-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/ctssync.yourdomain.com_.cer",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/ctssync.yourdomain.com_.cer",
"uploaded_at": "2020-04-14T21:39:23.176694Z"
},
{
"id": "11112222-5555-4444-3333-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-5555-4444-3333-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/ctssync.yourdomain.com_.key",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/ctssync.yourdomain.com_.key",
"uploaded_at": "2020-04-14T21:39:23.191285Z"
},
{
"id": "11112222-5555-3333-4444-666677778888",
"url": "http://127.0.0.1:8000/api/v0/upload/11112222-5555-3333-4444-666677778888/",
"description": "isecerts-upload/1582839825923_cert.zip-upload/iseserver_.yourdomain.com_iseserver_.yourdomain.com.cer",
"file": "http://127.0.0.1:8000/api/v0/upload/upload/iseserver_.yourdomain.com_iseserver_.yourdomain.com.cer",
"uploaded_at": "2020-04-14T21:39:23.188911Z"
}
]
}
```
3) Add your Cisco ISE Server to Adaptive Policy Sync using the following API call. You will need to provide your ISE ERS Admin username and password. A few additional notes:
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST --data-binary '{"description": "My ISE Server","ipaddress": "10.1.2.3","username": "ersadmin","password": "erspassword","pxgrid_enable": true,"pxgrid_ip": "10.1.2.3","pxgrid_cliname": "ctssync","pxgrid_clicert": "11112222-4444-5555-3333-666677778888","pxgrid_clikey": "11112222-5555-4444-3333-666677778888","pxgrid_clipw": "certpassword","pxgrid_isecert": "11112222-5555-3333-4444-666677778888"}' http://127.0.0.1:8000/api/v0/iseserver/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/iseserver/11112222-3333-4444-5555-666677778888/","description":"My ISE Server","ipaddress":"10.1.2.3","username":"ersadmin","password":"erspassword","force_rebuild":false,"skip_sync":false,"last_update":"2020-04-14T21:49:55.635413Z","last_sync":null,"pxgrid_enable":true,"pxgrid_ip":"10.1.2.3","pxgrid_cliname":"ctssync","pxgrid_clicert":"11112222-4444-5555-3333-666677778888","pxgrid_clikey":"11112222-5555-4444-3333-666677778888","pxgrid_clipw":"certpassword","pxgrid_isecert":"11112222-5555-3333-4444-666677778888"}
4) If you elected to not automatically accept certificate-based connections, you will need to check ISE after about 5 minutes (or you can re-start the app to trigger this immediately) in order to approve the pxGrid connection from your client.
1) Next, establish a syncronization session between your configured ISE server and your configured Meraki Dashboard instance using the following API call. You will need the ID numbers of your Dashboard instance and your ISE Server that were created above. You can specify a value in seconds for "sync_interval" - this represents how often Adaptive Policy Sync will request updated data from Cisco ISE and Meraki Dashboard and push Synchronization Changes.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST --data-binary '{"description": "Sync Session","dashboard": "11112222-3333-4444-5555-666677778888","iseserver": "11112222-3333-4444-5555-666677778888","ise_source": true,"sync_enabled": true,"apply_changes": true,"sync_interval": 300}' http://127.0.0.1:8000/api/v0/syncsession/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/syncsession/11112222-3333-4444-5555-666677778888/","description":"Sync Session","dashboard":"11112222-3333-4444-5555-666677778888","iseserver":"11112222-3333-4444-5555-666677778888","ise_source":true,"force_rebuild":false,"sync_enabled":true,"apply_changes":true,"sync_interval":300,"last_update":"2020-04-14T21:59:31.496696Z"}
1) By default, no tags are synchronized between Cisco ISE and Meraki Dashboard. You will need to enable synchronization on any tags that you wish to synchronize. First, get a list of all tags that Adaptive Policy Sync has learned using the following API call. To make it easier to read, you will want to pipe the output through a JSON formatter such as 'jq', 'python -mjson.tool', 'json_pp', or 'jsonpretty' to name a few.
curl --silent -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X GET http://127.0.0.1:8000/api/v0/tag/ | jq
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "11112222-3333-4444-5555-666677778888",
"url": "http://127.0.0.1:8000/api/v0/tag/11112222-3333-4444-5555-666677778888/",
"name": "Employees",
"description": "Organization Employees",
"do_sync": false,
"syncsession": "11112222-3333-4444-5555-666677778888",
"tag_number": 4,
"meraki_id": none,
"ise_id": "11112222-3333-4444-5555-666677778888",
"last_update": "2020-04-15T15:00:17.911065Z",
"in_sync": false
},
{
"id": "11112222-3333-5555-4444-666677778888",
"url": "http://127.0.0.1:8000/api/v0/tag/11112222-3333-5555-4444-666677778888/",
"name": "Guest",
"description": "Guest Users",
"do_sync": false,
"syncsession": "11112222-3333-4444-5555-666677778888",
"tag_number": 5,
"meraki_id": none,
"ise_id": "11112222-3333-4444-5555-666677778888",
"last_update": "2020-04-15T15:00:17.894175Z",
"in_sync": false
}
]
}
2) Enable synchronization on all tags that you wish to synchronize. Use the following API call in order to enable synchronization.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X PATCH --data-binary '{"do_sync": true}' http://127.0.0.1:8000/api/v0/tag/11112222-3333-4444-5555-666677778888/
{"id":"11112222-3333-4444-5555-666677778888","url":"http://127.0.0.1:8000/api/v0/tag/11112222-3333-4444-5555-666677778888/","name":"Employees","description":"Organization Employees","do_sync":true,"syncsession":"11112222-3333-4444-5555-666677778888","tag_number":4,"meraki_id":none,"ise_id":"11112222-3333-4444-5555-666677778888","last_update":"2020-04-15T15:05:17.054369Z","in_sync":false}
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X PATCH --data-binary '{"do_sync": true}' http://127.0.0.1:8000/api/v0/tag/11112222-3333-5555-4444-666677778888/
{"id":"11112222-3333-5555-4444-666677778888","url":"http://127.0.0.1:8000/api/v0/tag/11112222-3333-5555-4444-666677778888/","name":"Guest","description":"Guest Users","do_sync":true,"syncsession":"11112222-3333-4444-5555-666677778888","tag_number":5,"meraki_id":none,"ise_id":"11112222-3333-4444-5555-666677778888","last_update":"2020-04-15T15:05:17.054369Z","in_sync":false}
3) Check tag synchronization status by running the same call that you issued in step 1. Notice that these tags now show "insync": true. Note: it may take some time depending on your configured "sync_interval"_
curl --silent -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X GET http://127.0.0.1:8000/api/v0/tag/ | jq
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "11112222-3333-4444-5555-666677778888",
"url": "http://127.0.0.1:8000/api/v0/tag/11112222-3333-4444-5555-666677778888/",
"name": "Employees",
"description": "Organization Employees",
"do_sync": false,
"syncsession": "11112222-3333-4444-5555-666677778888",
"tag_number": 4,
"meraki_id": "28",
"ise_id": "11112222-3333-4444-5555-666677778888",
"last_update": "2020-04-15T16:12:39.705857Z",
"in_sync": true
},
{
"id": "11112222-3333-5555-4444-666677778888",
"url": "http://127.0.0.1:8000/api/v0/tag/11112222-3333-5555-4444-666677778888/",
"name": "Guest",
"description": "Guest Users",
"do_sync": false,
"syncsession": "11112222-3333-4444-5555-666677778888",
"tag_number": 5,
"meraki_id": "27",
"ise_id": "11112222-3333-4444-5555-666677778888",
"last_update": "2020-04-15T16:12:39.695225Z",
"in_sync": true
}
]
}
Open the Adaptive Policy Sync Interface. In the left navigation pane, navigate to Configuration -> Backup/Restore.
To create an immediate backup, click the "Backup Now" button. This will generate a backup file in JSON format, and will be stored in the "config" directory. If you are using the Docker command provided above, the config directory will map to the "adaptivepolicy" directory in your machine profile directory.
To restore the database from a backup file, click the "Restore" button next to the backup file in question. The file will be loaded into the Database immediately.
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST http://127.0.0.1:8000/api/v0/backup/
{"filename": "20200703-230325.json"}
curl -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X POST http://127.0.0.1:8000/api/v0/backup/
{"success": true}
Tags are not synchronizing.
API
curl --silent -L -H "Authorization: Bearer 1234567890abcdefghijklmnopqrstuvwxyz1234" -H 'Content-Type: application/json' -X GET http://127.0.0.1:8000/api/v0/tag/11112222-3333-4444-5555-666677778888/?detail=true | jq
UI
You can get synchronization detail for a specific tag by selecting the UUID of that tag in the UI under Status -> SGTs.
This will show you the raw data being received by the Meraki Dashboard API as well as the ISE ERS API. The "match_report" field (Sync Details in the UI) will show you what components match or do not match. The "update_dest" (Who Needs Update? in the UI) field will show whether Meraki Dashboard or Cisco ISE needs to be updated. The "push_config" field (Config Push in the UI) will show you the specific API call that will be issued in order to make an update.
Database Access