Saturday 19 February 2022

Two ISE Development Import/Export Guest User

The existing ISE 2.2 is retiring and company has built a new ISE 3.0 patch 4 (verified working) for replacement. This article tells how to export existing guest accounts that are sponsored and import to the new ISE 

 

 

Creating API User on both 3.0 and 2.2 version

 

Machine generated alternative text:
Cisco ISE 
Administration • Identity Management 
Identities 
Users 
Groups 
External Identity Sources 
Identity Source Sequences 
Network Access Users 
Latest Manual Network Scan Res... 
62 Edit 
Settings 
Export 
+ Add 
Status 
Enabled 
Enabled 
Change Status 
Username 
guest_api_user 
super-sponsor 
Import 
Description 
Duplicate 
O Delete v 
First Name Last Name Email Address 
A License Warning 
Selected 1 Total 
User Identity Grou... 
SponsorAlIAccount 
ALL_ACCOUNTS (defa

 

 

Adding it to Sponsor Group

 

 

Sponsor group enable API

Machine generated alternative text:
Sponsor Can 
e 
e 
e 
Update guests' contact information (email, Mobile Number) 
View/print guests' passwords 
Send SMS notifications with guests' credentials 
Reset guests' account passwords 
Extend guest accounts 
Delete guests' accounts 
Suspend guests' accounts 
O Require sponsor to provide a reason 
Reinstate suspended guests' accounts 
Approve and view requests from self-registering guests 
O Any pending accounts 
Onl endin accounts assi ned to this s onsor 
Access Cisco ISE guest accounts using the programmatic interface (Guest REST API)

 

 

 

Export and import script:

 

 

Export user from existing ISE2.0

 

 

import http.client

import base64

import ssl

import sys

import json

import pandas as pd

 

 

# host and authentication credentials

host = "<SERVER_IP>"

user = "<USER_NAME>"

password = "<PASSWORD>"

 

 

conn = http.client.HTTPSConnection("{}:9060".format(host), context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2))

 

creds = str.encode(':'.join((user, password)))

encodedAuth = bytes.decode(base64.b64encode(creds))

 

headers = {

    'accept': "application/json",

    'authorization': " ".join(("Basic",encodedAuth)),

    'cache-control': "no-cache",

    }

 

guestList = []

   

# How many pages of guest accounts exist. Find the number at “Manage Account” in ISE.

for pageNumber in range (1,7):

    # Maximum of searching users per page is 100

    conn.request("GET", "/ers/config/guestuser?size=100&page="+str(pageNumber), headers=headers) # 

    res = conn.getresponse()

    data = res.read()

    Rawjsondata = json.loads(data.decode("utf-8"))

    blob = Rawjsondata["SearchResult"]["resources"]

    for item in blob:

        # print (item["name"],",",end='') # print the guest username

        conn.request("GET", item["link"]["href"], headers=headers) #Fetch the guest details data

        res = conn.getresponse() 

        data = res.read()

        Rawjsondata = json.loads(data.decode("utf-8"))

        subblob = Rawjsondata["GuestUser"] # This is the Guest detail containing stuff we want

        dGuestList = {}

        dGuestList.update({"* First name:":subblob["guestInfo"]["firstName"]})

        dGuestList.update({"* Last name:":subblob["guestInfo"]["lastName"]})

        dGuestList.update({"* Email address:":subblob["guestInfo"]["emailAddress"]})

        dGuestList.update({"Mobile number:":'+55555555555'})

        dGuestList.update({"Company:":'NA'})    

        dGuestList.update({"Person being visited (email):":subblob["guestInfo"]["emailAddress"]})

        dGuestList.update({"Reason for visit:":'NA'})

        dGuestList.update({"Username:":subblob["guestInfo"]["userName"]})

        dGuestList.update({"password":subblob["guestInfo"]["password"]})

        dGuestList.update({"guestType":subblob["guestType"]})

        dGuestList.update({"status":subblob["status"]})

        dGuestList.update({"sponsorUserName":subblob["sponsorUserName"]})

        dGuestList.update({"sponsorUserId":subblob["sponsorUserId"]})

        dGuestList.update({"enabled":subblob["guestInfo"]["enabled"]})

        dGuestList.update({"notificationLanguage":subblob["guestInfo"]["notificationLanguage"]})

        dGuestList.update({"creationTime":subblob["guestInfo"]["creationTime"]})

        dGuestList.update({"validDays":subblob["guestAccessInfo"]["validDays"]})

        dGuestList.update({"fromDate":subblob["guestAccessInfo"]["fromDate"]})

        dGuestList.update({"toDate":subblob["guestAccessInfo"]["toDate"]})

        dGuestList.update({"location":subblob["guestAccessInfo"]["location"]})

        # dGuestList.update({"ssid":subblob["guestAccessInfo"]["ssid"]})

 

        guestList.append(dGuestList)

    print("page: " + str(pageNumber))

 

# print(guestList)

df = pd.DataFrame(guestList)

# df.drop(['id', 'link'], axis=1, inplace=True)

# df = pd.read_csv('all_guest.csv')

df = df[~df.status.str.contains("EXPIRED")]

 

locations = list(set(df['location'].tolist()))

 

# we export by filename of guest users’ location


for l in locations:  

    df.loc[df['location'] == l].to_csv(l+'.csv',index=False)

    print('Generating: ' + l +'.csv')

 

 

  

 

Exported sample CSV file:

A csv file with required fields such as username, password, valid date, from date and to Date. And it contains its original sponsor username.

 

 

  

Import users to new ISE 3.0

Let’s import the guest to the new ISE. Please be noted that we have to attempt an API call with sponsor’s username/fake password to create a shadow users, otherwise ISE will complaint the guest’s sponsor does not exist, so you will meet with a 501 error.

 

import http.client

import base64

import ssl

import sys

import json

import pandas as pd

import json

from time import sleep

from datetime import datetime, timedelta

 

host = "<SERVER_IP>"

user = "<USER_NAME>"

password = "<PASSWORD>"

 

portalId = "<SPONSOR_PORTAL_ID>"  # you will find this id by opening up the test url

 

 

conn = http.client.HTTPSConnection("{}:9060".format(host), context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2))

 

creds = str.encode(':'.join((user, password)))

encodedAuth = bytes.decode(base64.b64encode(creds))

 

 

df = pd.read_csv("Costa Rica.csv")

 

 # Create a JSON 

for index, row in df.iterrows():

    date_format = "%m/%d/%Y %H:%M"

    fromDate = datetime.today().strftime(date_format)

    toDate = (datetime.strptime(fromDate, date_format) + timedelta(days=int(row['validDays']))).strftime(date_format)

    # toDate = datetime.strptime(str(toDate), date_format)

    # print(fromDate, toDate, str(row['validDays']))

    

      

    req_body_json = """  {{

       "GuestUser" : {{

        "guestType": "{}",

        "sponsorUserName": "{}",

        "reasonForVisit": "Business meetng",

        "portalId": "{}",

        "status": "ACTIVE",

        "guestInfo" : {{

             "userName": "{}",

               "firstName": "{}",

              "lastName": "{}",

               "password": "{}",

               "emailAddress": "{}",

               "enabled": true,

               "notificationLanguage": "English",

               "enabled": "true"

        }},

        "guestAccessInfo" : {{

             "validDays": "{}",

               "fromDate": "{}",

              "toDate": "{}",

               "location": "{}"

        }}

    }}

}}

""".format(

           row['guestType'],

           row['sponsorUserName'],

           portalId,

           row['Username:'],

           row['* First name:'],

           row['* Last name:'],

           row['password'],

           row['* Email address:'],

           row['validDays'],

           str(fromDate),

           str(toDate),

           row['location']

           )

    

    

    headers = {

        'accept': "application/json",

        'content-type': "application/json",

        'authorization': " ".join(("Basic",encodedAuth)),

        'cache-control': "no-cache",

        }

 

 

    # --------------- Fake - Sponsor call  to create shadow accounts (will fail)

 

    sponsorUserName = row['sponsorUserName']

    conn2 = http.client.HTTPSConnection("{}:9060".format(host), context=ssl.SSLContext(ssl.PROTOCOL_TLSv1_2))

 

    creds2 = str.encode(':'.join((sponsorUserName, password)))

    encodedAuth2 = bytes.decode(base64.b64encode(creds2))

    

    headers2 = {

        'accept': "application/json",

        'content-type': "application/json",

        'authorization': " ".join(("Basic",encodedAuth2)),

        'cache-control': "no-cache",

        }

    conn2.request("POST", "/ers/config/guestuser/", headers=headers2, body=req_body_json)

        

      

# The followings are normal connection to create the guest

 

    conn.request("POST", "/ers/config/guestuser/", headers=headers, body=req_body_json)

 

    res = conn.getresponse()

    data = res.read()

    

    print('\nImporting-------->  '+row['Username:'] + '\n' + "Status: {}".format(res.status))

    print("Body:\n{}".format(data.decode("utf-8")))

    

    sleep(1)