Create and manage Secure Access Key Admin API

Key Admin API Guide

This guide provides Python client samples for the Cisco Secure Access Key Admin API. You will need a Secure Access Key Admin API key. For more information, see Manage Key Admin API Keys.

  1. First get your Secure Access Key Admin API key and set up your environment, and then install the Secure Access API client. For more information, see Samples Overview.
  2. Run python3 main.py.
Note: Your Secure Access Key Admin API key must have the permissions to read and write on the admin key scope. For more information about the API key scopes, see Secure Access OAuth 2.0 Scopes.

Run the Script

  1. Copy the script to a local file called main.py. Locate the script in your environment in a directory above the cisco directory.
  2. Run python3 main.py.

main.py

"""
Copyright (c) 2025 Cisco and/or its affiliates.
This software is licensed to you under the terms of the Cisco Sample
Code License, Version 1.1 (the "License"). You may obtain a copy of the
License at

https://developer.cisco.com/docs/licenses

All use of the material herein must be in accordance with the terms of
the License. All rights not expressly granted by the License are
reserved. Unless required by applicable law or agreed to separately in
writing, software distributed under the License is distributed on an "AS
IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied.
"""

import requests
from requests_toolbelt import MultipartEncoder
import json
import os
from dotenv import load_dotenv

from cisco.secure_access import API
from cisco.secure_access import admin
from cisco.secure_access import deployments
from cisco.secure_access import GET
from cisco.secure_access import PATCH
from cisco.secure_access import POST
from cisco.secure_access import DELETE
from cisco.secure_access import token_url
from cisco.secure_access import client_id
from cisco.secure_access import client_secret

# Key Admin API endpoints
api_keys_endpoint = "apiKeys"
api_keys_details_endpoint = "apiKeys/{}"
api_keys_details_refresh_endpoint = "apiKeys/{}/refresh"

# Roaming Computers API endpoint
roaming_computers_endpoint = "roamingcomputers"

load_dotenv()

def get_api_keys(api):
    ''' Get the API keys. '''
    try:
        # Get the API keys in the organization
        response = api.Query(admin, api_keys_endpoint, GET)

        # Check if the API request was successful
        if response.status_code == 200:
            print(f"Success. GET {api_keys_endpoint}, {response.json()}")
            return response.json()
        else:
            print(f"Failed to get the API keys. Status code: {response.status_code}, Response: {response.text}.")
            return None
    except requests.exceptions.RequestException as e:
        print(f"An error occurred: {e}.")

def post_api_keys(api, name, scopes, description=None, expireAt=None):
    ''' Create a Secure Access API key. '''
    try:
        if name is None or scopes is None:
            raise ValueError("name and scopes are required to create the Secure Access API key.")

        # Prepare the payload
        payload = {
            "name": name,
            "expireAt": '',
            "scopes": scopes
        }

        # Create a Secure Access API key
        response = api.Query(admin, api_keys_endpoint, POST, payload)

        # Check the response status
        if response.status_code == 201:
            print(f"Success. POST {api_keys_endpoint}, {response.json()}")
            return response.json()
        else:
            print(f"Failed to create the Secure Access API key {name}. Status code: {response.status_code}, Response: {response.text}.")
            return None
    except Exception as e:
        print(f"An error occurred: {e}.")

def get_api_key(api, id):
    ''' Get the properties of the API key. '''
    try:
        if id is None:
            raise ValueError("id is required to get the API key.")
        url = api_keys_details_endpoint.format(id)

        # Get the properties for the Secure Access API key.
        response = api.Query(admin, url, GET)

        # Check if the API request was successful
        if response.status_code == 200:
            print(f"Success. GET {url}, {response.json()}.")
            return response.json()
        else:
            print(f"Failed to get the API key {id}. Status code: {response.status_code}, Response: {response.text}.")
            return
    except Exception as e:
        print(f"An error occurred: {e}.")

def patch_api_keys(api, id, name, scopes, description=None, allowedIPs=None):
    ''' Update a Secure Access API key. '''
    try:
        if name is None or scopes is None:
            raise ValueError("name, expireAt, and scopes are required to update the Secure Access API key.")
        if id is None:
            raise ValueError("id is required to get the API key.")
        url = api_keys_details_endpoint.format(id)

        # Prepare the payload
        payload = {
            "name": name,
            "scopes": scopes
        }

        # Update a Secure Access API key
        response = api.Query(admin, url, PATCH, payload)

        # Check the response status
        if response.status_code == 200:
            print(f"Success. PATCH {url}, {response.json()}")
            return response.json()
        else:
            print(f"Failed to create the Secure Access API key {id}, {name}. Status code: {response.status_code}, Response: {response.text}.")
            return None
    except Exception as e:
        print(f"An error occurred: {e}.")

def delete_api_keys(api, id):
    ''' Delete the API key. '''
    try:
        if id is None:
            raise ValueError("id is required to delete the API key.")
        url = api_keys_details_endpoint.format(id)

        # Delete the API key.
        response = api.Query(admin, url, DELETE)

        # Check if the API request was successful
        if response.status_code == 204:
            print(f"No Content. DELETE {url}.")
        else:
            print(f"Failed to delete the API key {id}. Status code: {response.status_code}, Response: {response.text}.")
    except Exception as e:
        print(f"An error occurred: {e}.")

def refresh_api_keys(api, id):
    ''' Refresh a Secure Access API key. '''
    try:
        if id is None:
            raise ValueError("id is required to refresh the Secure Access API key.")

        url = api_keys_details_refresh_endpoint.format(id)

        # Refresh the Secure Access API key credentials
        response = api.Query(admin, url, POST)

        # Check the response status
        if response.status_code == 200:
            print(f"Success. POST {url}, {response.json()}")
            return response.json()
        else:
            print(f"Failed to refresh the Secure Access API key {id}. Status code: {response.status_code}, Response: {response.text}.")
            return None
    except Exception as e:
        print(f"An error occurred: {e}.")

def get_roaming_computers(api):
    ''' Get Roaming Computers. '''
    try:
        # Get Roaming Computers in the organization
        response = api.Query(deployments, roaming_computers_endpoint, GET)

        # Check if the API request was successful
        if response.status_code == 200:
            print(f"Success. GET {roaming_computers_endpoint}, {response.json()}")
            return response.json()
        else:
            print(f"Failed to get the Roaming Computers. Status code: {response.status_code}, Response: {response.text}.")
            return None
    except requests.exceptions.RequestException as e:
        print(f"An error occurred: {e}.")

def main():
    # Exit out if the required client_id or client_secret is not set
    for var in ['API_SECRET', 'API_KEY', 'OUTPUT_DIR']:
        if os.environ.get(var) == None:
            print("Required environment variable: {} not set".format(var))
            exit()

    # Get your API token
    api = API(token_url, client_id, client_secret)

    try:

        # Get Secure Access API keys
        json_data = get_api_keys(api)

        # Create a Secure Access API key
        name = 'api key for roaming-computers'
        expireAt = '' # no expiration
        policies_roaming_computers_read_scope = 'deployments.roamingcomputers:read'
        scopes = []
        scopes.append(policies_roaming_computers_read_scope)
        json_data = post_api_keys(api, name, scopes)

        # Get the Secure Access API key
        id = json_data['key']['id'] if 'id' in json_data['key'] else None
        json_data = get_api_key(api, id)

        # Set new values for the properties of the Secure Access API key
        name = "second update api key for roaming computers"
        scopes.append('deployments.roamingcomputers:write')
        json_data = patch_api_keys(api, id, name, scopes)

        # Refresh the Secure Access API key credentials
        json_data = refresh_api_keys(api, id)

        # Use the created Secure Access API key to generate a new access token
        api_key_client_id = json_data['key']['clientId'] if 'clientId' in json_data['key'] else None
        api_key_client_secret = json_data['key']['clientSecret'] if 'clientSecret' in json_data['key'] else None
        keyadmin_api = API(token_url, api_key_client_id, api_key_client_secret)

        # Use the created Secure Access API key to get a list of the roaming computers.
        json_data = get_roaming_computers(keyadmin_api)
        print(json.dumps(json_data, indent=4))

        # Delete the Secure Access API key created to get the roaming computers.
        delete_api_keys(api, id)
    except Exception as e:
        print(e)

# main
if __name__ == "__main__":
    main()