목차

소개

사전 요구 사항

요구 사항

사용되는 구성 요소

구성

스크립트

오류

문제 해결

관련 정보

스포일러 (읽으려면 강조 표시)

Cisco는 이 개발 설계에 대한 공식적인 지원을 제공하지 않습니다. API가 애플리케이션과 어떻게 상호 작용하는지 쉽게 이해할 수 있도록 참조용으로 작성되었습니다. 사용자는 이 설계를 프로덕션 수준의 구현을 위한 기초가 아닌 교육 목적으로만 사용해야 합니다.  이 문서에 제시된 코드를 실행하는 것은 사용자의 책임이며, Cisco는 그 사용으로 인해 발생하는 모든 문제에 대해 어떠한 책임도 명시적으로 부인합니다.

Cisco는 이 개발 설계에 대한 공식적인 지원을 제공하지 않습니다. API가 애플리케이션과 어떻게 상호 작용하는지 쉽게 이해할 수 있도록 참조용으로 작성되었습니다. 사용자는 이 설계를 프로덕션 수준의 구현을 위한 기초가 아닌 교육 목적으로만 사용해야 합니다. 이 문서에 제시된 코드를 실행하는 것은 사용자의 책임이며, Cisco는 그 사용으로 인해 발생하는 모든 문제에 대해 어떠한 책임도 명시적으로 부인합니다.

소개

이 문서에서는 Python 및 REST API를 사용하여 대상 목록에서 가능한 모든 작업을 수행하는 방법에 대해 설명합니다.

사전 요구 사항

다음 주제에 대한 지식을 보유하고 있으면 유용합니다.

1. 비단뱀

2. REST API

3. Cisco 보안 액세스

요구 사항

다음 요건을 충족해야 계속 진행할 수 있습니다.

- Cisco Secure Access 사용자 계정(전체 관리자 역할)

- Cisco Security Cloud SCSO(Single Sign On) 계정을 사용하여 Secure Access에 로그인합니다.

- Secure Access API 키 생성

사용되는 구성 요소

이 문서의 정보는 다음 소프트웨어 및 하드웨어 버전을 기반으로 합니다.

- 보안 액세스 대시보드

- 파이썬 3.x

이 문서의 정보는 특정 랩 환경의 디바이스를 토대로 작성되었습니다. 이 문서에 사용된 모든 디바이스는 초기화된(기본) 컨피그레이션으로 시작되었습니다. 현재 네트워크가 작동 중인 경우 모든 명령의 잠재적인 영향을 미리 숙지하시기 바랍니다.

구성

오류 처리, 토큰 유효성(3600초) 등과 같은 여러 측면을 고려하여 이 코드를 작성하는 데는 여러 가지 방법이 있습니다.

스크립트를 실행하기 전에 이러한 Python 라이브러리가 설치되어 있는지 확인하십시오.

pip install requests pip install oauthlib pip install requests_oauthlib

스크립트

이 스크립트에서는 client_id 및 을 client_secretAPI KeyKey Secret 각각 과 로 대체하십시오.

from oauthlib.oauth2 import BackendApplicationClient from oauthlib.oauth2 import TokenExpiredError from requests_oauthlib import OAuth2Session from requests.auth import HTTPBasicAuth import time import requests import pprint import json def fetch_headers(BToken): BT = f"Bearer {BToken}" headers = { 'Authorization':BT, "Content-Type": "application/json", "Accept": "application/json" } return headers # GET OAUTH 2.0 TOKEN def getToken(): token_url = 'https://api.sse.cisco.com/auth/v2/token' try: #ASSIGN your API Key to the variable client_id and Secret Key to the variable client_secret client_id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" client_secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" auth = HTTPBasicAuth(client_id, client_secret) client = BackendApplicationClient(client_id=client_id) oauth = OAuth2Session(client=client) token = oauth.fetch_token(token_url=token_url, auth=auth) print("\n######Token Generated Successfully######\n") return token except e as Exception: print(f"Encountered an error while Fetching the TOKEN :: {e}") # 1 - GET DESTINATION LISTS def fetch_destinationlists(h): url = "https://api.sse.cisco.com/policies/v2/destinationlists" try: response = requests.request('GET', url, headers=h) json_object = json.loads(response.content) #pprint.pprint(json_object) x=1 for item in json_object["data"]: print(f"Destination List : {x}") pprint.pprint(f"Name : {item['name']}") pprint.pprint(f"ID : {item['id']}") #pprint.pprint(f"Destination Count : {item['meta']['destinationCount']}") print("\n") x+=1 except e as Exception: print(f"Encountered an Error while Fetching the Destination Lists :: {e}") # 2 - GET DESTINATION LIST def get_destinationlist(h): try: choice = input("Enter the ID of the DestinationList:: ") url = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice response = requests.request('GET', url, headers=h) json_object = json.loads(response.content) print("\n\n") pprint.pprint(json_object) print("\n\n") except e as Exception: print(f"Encountered an Error while Fetching the Destination List Details :: {e}") # 3 - CREATE DESTINATION LIST def create_destinationlist(h): url = "https://api.sse.cisco.com/policies/v2/destinationlists" try: naav = input("Name of the DestinationList :: ") payload = { "access": "none", "isGlobal": False, "name": naav, } response = requests.request('POST', url, headers=h, data = json.dumps(payload)) json_object = json.loads(response.content) print("\n\n") pprint.pprint(json_object) print("\n\n") except e as Exception: print(f"Encountered an Error while Creating the Destination List :: {e}") # 4 - UPDATE DESTINATION LIST NAME def patch_destinationlist(h): try: choice = input("Enter the ID of the DestinationList for changing it's name :: ") url = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice naav = input("Enter New Name :: ") payload = {"name": naav} response = requests.request('PATCH', url, headers=h, data = json.dumps(payload)) json_object = json.loads(response.content) print("\n\n") pprint.pprint(json_object) print("\n\n") except e as Exception: print(f"Encountered an Error while Updating the Destination List :: {e}") # 5 - DELETE DESTINATION LIST def delete_destinationlist(h): try: choice = input("Enter the ID of the DestinationList for DELETION :: ") url = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice response = requests.request('DELETE', url, headers=h) json_object = json.loads(response.content) print("\n\n") pprint.pprint(json_object) print("\n\n") except Exception as e: print(f"Encountered an Error while Deleting the Destination List :: {e}") # 6 - GET DESTINATIONS FROM A DESTINATION LIST def fetch_detail(h): try: choice = input("DestinationList ID: ") url2 = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice + "/destinations" response = requests.request('GET', url2, headers=h) print("\n") json_dest = json.loads(response.content) pprint.pprint(json_dest) print("\n\n") except e as Exception: print(f"Encountered an Error while Fetching the Destinations from the Destination List :: {e}") # 7 - ADD DESTINATIONS TO A DESTINATION LIST def add_destinations(h): try: choice = input("Enter the ID of the DestinationList :: ") url = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice + "/destinations" destination_to_add = input("\nEnter the destination that you want to add :: ") payload = [{"destination": destination_to_add}] response = requests.request('POST', url, headers=h, data = json.dumps(payload)) print("\n") json_dest = json.loads(response.content) pprint.pprint(json_dest) print("\n\n") except e as Exception: print(f"Encountered an Error while Adding the Destination to the Destination List :: {e}") # 8 - DELETE DESTINATIONS FROM DESTINATION LIST def delete_entry(h): try: choice_del = input("\nCONFIRM DestinationList ID from which you want to delete the Destination :: ") url3 = "https://api.sse.cisco.com/policies/v2/destinationlists/" + choice_del + "/destinations/remove" dest = int(input("ID of the Destination that you want to remove: ")) payload = f"[{dest}]" response = requests.request('DELETE', url3, headers=h, data=payload) json_del = json.loads(response.content) print("\n\n") pprint.pprint(json_del) print("\n\n") except e as Exception: print(f"Encountered an Error while Deleting a Destination from the Destination List :: {e}") #FETCH COOKIE possess_cookie = " " while possess_cookie not in ["Y","y","N","n"]: possess_cookie = input("Token Already Generated? (Y/N) :: ") if possess_cookie.upper() =="N": cook = getToken() with open("cookie.txt","w") as wr: wr.writelines(cook["access_token"]) # print(f"Access Token = {cook["access_token"]}") #FETCH HEADERS with open("cookie.txt","r") as ree: h = fetch_headers(ree.readline()) print("\n") while True: action = input("""Available operations: 1. Get Destination Lists 2. Get Destination List 3. Create Destination List 4. Update Destination List Name 5. Delete Destination List 6. Get Destinations from Destination List 7. Add Destinations to a Destination List 8. Delete Destinations from Destination List 9. Exit Enter Your Choice :: """) print("\n") operation = action.replace(" ","") if operation == "1": fetch_destinationlists(h) elif operation == "2": fetch_destinationlists(h) get_destinationlist(h) elif operation == "3": create_destinationlist(h) elif operation == "4": fetch_destinationlists(h) patch_destinationlist(h) elif operation == "5": fetch_destinationlists(h) delete_destinationlist(h) elif operation == "6": fetch_destinationlists(h) fetch_detail(h) elif operation == "7": fetch_destinationlists(h) add_destinations(h) elif operation == "8": fetch_destinationlists(h) fetch_detail(h) delete_entry(h) elif operation == "9": break else: print("\n") print("==========INCORRECT INPUT==========") print("\n") print("Thank You!!! Good Bye!!!") time.sleep(5)

성과:

이 스크립트의 출력은 다음과 같아야 합니다.

Cookie Already Generated? (Y/N) :: y Available operations: 1. Get Destination Lists 2. Get Destination List 3. Create Destination List 4. Update Destination List Name 5. Delete Destination List 6. Get Destinations from Destination List 7. Add Destinations to a Destination List 8. Delete Destinations from Destination List 9. Exit Enter Your Choice ::

Token Already Generated? (Y/N) :: y Available operations: 1. Get Destination Lists 2. Get Destination List 3. Create Destination List 4. Update Destination List Name 5. Delete Destination List 6. Get Destinations from Destination List 7. Add Destinations to a Destination List 8. Delete Destinations from Destination List 9. Exit Enter Your Choice :: 1

이 프로그램이 성공적으로 실행되면 처음에 Cookie(쿠키)에 대한 질문이 표시됩니다Cookie Already Generated? (Y/N). 이 질문을 하는 이유는 일단 생성된 쿠키가 3600초(1시간) 동안 유효하기 때문에 쿠키를 여러 번 생성하지 않도록 하기 위해서입니다. 또는y 를 입력하면 새Y 쿠키가 생성되지 않습니다. 그러나 를 nN 입력하거나 입력하면 새 쿠키가 생성되어 동일한 디렉토리/폴더에 있는 로컬 텍스트 파일에 저장됩니다. 이 파일의 쿠키는 후속 요청에 사용됩니다.

오류

DestinationList ID를 언급해야 하는 작업에 대해 잘못된 ID를 입력하면 이 오류가 발생할 수 있습니다.

{'message': 'no Route matched with those values'}

DestinationList를 만드는 동안 255자를 초과하는 DestinationList의 이름을 언급하면 다음 오류가 표시됩니다.

{'code': 400, 'code_text': 'Bad Request', 'error': 'invalid_request', 'message': {'name': {'code': 'string_invalid', 'code_text': 'must be fewer than 255 characters long'}}, 'statusCode': 400, 'txId': 'l23f0cjk62fe'}

Secure Access Developers User Guide를 사용하여 정책, 로밍 컴퓨터, 보고서 등에 대한 정보를 가져올 수도 있습니다.

문제 해결

Secure Access API 엔드포인트는 HTTP 응답 코드를 사용하여 API 요청의 성공 또는 실패를 나타냅니다. 일반적으로 2xx 범위의 코드는 성공을 나타내고, 4xx 범위의 코드는 제공된 정보에서 발생한 오류를 나타내며, 5xx 범위의 코드는 서버 오류를 나타낸다. 문제를 해결하기 위한 접근 방식은 수신된 응답 코드에 따라 달라집니다.

REST API - 응답 코드 1

REST API - 응답 코드 2

관련 정보

- Cisco Secure Access 사용 설명서

- Cisco 기술 지원 및 다운로드

- 보안 액세스 API 키 추가

- 개발자 사용 설명서

- Python에서 REST API를 사용하도록 보안 액세스 구성

- cURL을 통해 대상 목록 관리